| OLD | NEW |
| (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 "content/browser/media/capture/smooth_event_sampler.h" | |
| 6 | |
| 7 #include "base/strings/stringprintf.h" | |
| 8 #include "testing/gtest/include/gtest/gtest.h" | |
| 9 | |
| 10 namespace content { | |
| 11 | |
| 12 namespace { | |
| 13 | |
| 14 bool AddEventAndConsiderSampling(SmoothEventSampler* sampler, | |
| 15 base::TimeTicks event_time) { | |
| 16 sampler->ConsiderPresentationEvent(event_time); | |
| 17 return sampler->ShouldSample(); | |
| 18 } | |
| 19 | |
| 20 void SteadyStateSampleAndAdvance(base::TimeDelta vsync, | |
| 21 SmoothEventSampler* sampler, | |
| 22 base::TimeTicks* t) { | |
| 23 ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t)); | |
| 24 ASSERT_TRUE(sampler->HasUnrecordedEvent()); | |
| 25 sampler->RecordSample(); | |
| 26 ASSERT_FALSE(sampler->HasUnrecordedEvent()); | |
| 27 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); | |
| 28 *t += vsync; | |
| 29 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); | |
| 30 } | |
| 31 | |
| 32 void SteadyStateNoSampleAndAdvance(base::TimeDelta vsync, | |
| 33 SmoothEventSampler* sampler, | |
| 34 base::TimeTicks* t) { | |
| 35 ASSERT_FALSE(AddEventAndConsiderSampling(sampler, *t)); | |
| 36 ASSERT_TRUE(sampler->HasUnrecordedEvent()); | |
| 37 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); | |
| 38 *t += vsync; | |
| 39 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)); | |
| 40 } | |
| 41 | |
| 42 base::TimeTicks InitialTestTimeTicks() { | |
| 43 return base::TimeTicks() + base::TimeDelta::FromSeconds(1); | |
| 44 } | |
| 45 | |
| 46 void TestRedundantCaptureStrategy(base::TimeDelta capture_period, | |
| 47 int redundant_capture_goal, | |
| 48 SmoothEventSampler* sampler, | |
| 49 base::TimeTicks* t) { | |
| 50 // Before any events have been considered, we're overdue for sampling. | |
| 51 ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t)); | |
| 52 | |
| 53 // Consider the first event. We want to sample that. | |
| 54 ASSERT_FALSE(sampler->HasUnrecordedEvent()); | |
| 55 ASSERT_TRUE(AddEventAndConsiderSampling(sampler, *t)); | |
| 56 ASSERT_TRUE(sampler->HasUnrecordedEvent()); | |
| 57 sampler->RecordSample(); | |
| 58 ASSERT_FALSE(sampler->HasUnrecordedEvent()); | |
| 59 | |
| 60 // After more than 250 ms has passed without considering an event, we should | |
| 61 // repeatedly be overdue for sampling. However, once the redundant capture | |
| 62 // goal is achieved, we should no longer be overdue for sampling. | |
| 63 *t += base::TimeDelta::FromMilliseconds(250); | |
| 64 for (int i = 0; i < redundant_capture_goal; i++) { | |
| 65 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 66 ASSERT_FALSE(sampler->HasUnrecordedEvent()); | |
| 67 ASSERT_TRUE(sampler->IsOverdueForSamplingAt(*t)) | |
| 68 << "Should sample until redundant capture goal is hit"; | |
| 69 sampler->RecordSample(); | |
| 70 *t += capture_period; // Timer fires once every capture period. | |
| 71 } | |
| 72 ASSERT_FALSE(sampler->IsOverdueForSamplingAt(*t)) | |
| 73 << "Should not be overdue once redundant capture goal achieved."; | |
| 74 } | |
| 75 | |
| 76 } // namespace | |
| 77 | |
| 78 // 60Hz sampled at 30Hz should produce 30Hz. In addition, this test contains | |
| 79 // much more comprehensive before/after/edge-case scenarios than the others. | |
| 80 TEST(SmoothEventSamplerTest, Sample60HertzAt30Hertz) { | |
| 81 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; | |
| 82 const int redundant_capture_goal = 200; | |
| 83 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60; | |
| 84 | |
| 85 SmoothEventSampler sampler(capture_period, redundant_capture_goal); | |
| 86 base::TimeTicks t = InitialTestTimeTicks(); | |
| 87 | |
| 88 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, | |
| 89 &sampler, &t); | |
| 90 | |
| 91 // Steady state, we should capture every other vsync, indefinitely. | |
| 92 for (int i = 0; i < 100; i++) { | |
| 93 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 94 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 95 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 96 } | |
| 97 | |
| 98 // Now pretend we're limited by backpressure in the pipeline. In this scenario | |
| 99 // case we are adding events but not sampling them. | |
| 100 for (int i = 0; i < 20; i++) { | |
| 101 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 102 ASSERT_EQ(i >= 14, sampler.IsOverdueForSamplingAt(t)); | |
| 103 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | |
| 104 ASSERT_TRUE(sampler.HasUnrecordedEvent()); | |
| 105 t += vsync; | |
| 106 } | |
| 107 | |
| 108 // Now suppose we can sample again. We should be back in the steady state, | |
| 109 // but at a different phase. | |
| 110 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); | |
| 111 for (int i = 0; i < 100; i++) { | |
| 112 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 113 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 114 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 115 } | |
| 116 } | |
| 117 | |
| 118 // 50Hz sampled at 30Hz should produce a sequence where some frames are skipped. | |
| 119 TEST(SmoothEventSamplerTest, Sample50HertzAt30Hertz) { | |
| 120 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; | |
| 121 const int redundant_capture_goal = 2; | |
| 122 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 50; | |
| 123 | |
| 124 SmoothEventSampler sampler(capture_period, redundant_capture_goal); | |
| 125 base::TimeTicks t = InitialTestTimeTicks(); | |
| 126 | |
| 127 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, | |
| 128 &sampler, &t); | |
| 129 | |
| 130 // Steady state, we should capture 1st, 2nd and 4th frames out of every five | |
| 131 // frames, indefinitely. | |
| 132 for (int i = 0; i < 100; i++) { | |
| 133 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 134 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 135 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 136 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 137 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 138 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 139 } | |
| 140 | |
| 141 // Now pretend we're limited by backpressure in the pipeline. In this scenario | |
| 142 // case we are adding events but not sampling them. | |
| 143 for (int i = 0; i < 20; i++) { | |
| 144 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 145 ASSERT_EQ(i >= 11, sampler.IsOverdueForSamplingAt(t)); | |
| 146 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | |
| 147 t += vsync; | |
| 148 } | |
| 149 | |
| 150 // Now suppose we can sample again. We should be back in the steady state | |
| 151 // again. | |
| 152 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); | |
| 153 for (int i = 0; i < 100; i++) { | |
| 154 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 155 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 156 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 157 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 158 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 159 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 // 75Hz sampled at 30Hz should produce a sequence where some frames are skipped. | |
| 164 TEST(SmoothEventSamplerTest, Sample75HertzAt30Hertz) { | |
| 165 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; | |
| 166 const int redundant_capture_goal = 32; | |
| 167 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 75; | |
| 168 | |
| 169 SmoothEventSampler sampler(capture_period, redundant_capture_goal); | |
| 170 base::TimeTicks t = InitialTestTimeTicks(); | |
| 171 | |
| 172 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, | |
| 173 &sampler, &t); | |
| 174 | |
| 175 // Steady state, we should capture 1st and 3rd frames out of every five | |
| 176 // frames, indefinitely. | |
| 177 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 178 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 179 for (int i = 0; i < 100; i++) { | |
| 180 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 181 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 182 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 183 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 184 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 185 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 186 } | |
| 187 | |
| 188 // Now pretend we're limited by backpressure in the pipeline. In this scenario | |
| 189 // case we are adding events but not sampling them. | |
| 190 for (int i = 0; i < 20; i++) { | |
| 191 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 192 ASSERT_EQ(i >= 16, sampler.IsOverdueForSamplingAt(t)); | |
| 193 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | |
| 194 t += vsync; | |
| 195 } | |
| 196 | |
| 197 // Now suppose we can sample again. We capture the next frame, and not the one | |
| 198 // after that, and then we're back in the steady state again. | |
| 199 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); | |
| 200 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 201 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 202 for (int i = 0; i < 100; i++) { | |
| 203 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 204 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 205 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 206 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 207 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 208 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 209 } | |
| 210 } | |
| 211 | |
| 212 // 30Hz sampled at 30Hz should produce 30Hz. | |
| 213 TEST(SmoothEventSamplerTest, Sample30HertzAt30Hertz) { | |
| 214 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; | |
| 215 const int redundant_capture_goal = 1; | |
| 216 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 30; | |
| 217 | |
| 218 SmoothEventSampler sampler(capture_period, redundant_capture_goal); | |
| 219 base::TimeTicks t = InitialTestTimeTicks(); | |
| 220 | |
| 221 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, | |
| 222 &sampler, &t); | |
| 223 | |
| 224 // Steady state, we should capture every vsync, indefinitely. | |
| 225 for (int i = 0; i < 200; i++) { | |
| 226 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 227 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 228 } | |
| 229 | |
| 230 // Now pretend we're limited by backpressure in the pipeline. In this scenario | |
| 231 // case we are adding events but not sampling them. | |
| 232 for (int i = 0; i < 10; i++) { | |
| 233 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 234 ASSERT_EQ(i >= 7, sampler.IsOverdueForSamplingAt(t)); | |
| 235 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | |
| 236 t += vsync; | |
| 237 } | |
| 238 | |
| 239 // Now suppose we can sample again. We should be back in the steady state. | |
| 240 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); | |
| 241 for (int i = 0; i < 100; i++) { | |
| 242 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 243 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 244 } | |
| 245 } | |
| 246 | |
| 247 // 24Hz sampled at 30Hz should produce 24Hz. | |
| 248 TEST(SmoothEventSamplerTest, Sample24HertzAt30Hertz) { | |
| 249 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; | |
| 250 const int redundant_capture_goal = 333; | |
| 251 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 24; | |
| 252 | |
| 253 SmoothEventSampler sampler(capture_period, redundant_capture_goal); | |
| 254 base::TimeTicks t = InitialTestTimeTicks(); | |
| 255 | |
| 256 TestRedundantCaptureStrategy(capture_period, redundant_capture_goal, | |
| 257 &sampler, &t); | |
| 258 | |
| 259 // Steady state, we should capture every vsync, indefinitely. | |
| 260 for (int i = 0; i < 200; i++) { | |
| 261 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 262 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 263 } | |
| 264 | |
| 265 // Now pretend we're limited by backpressure in the pipeline. In this scenario | |
| 266 // case we are adding events but not sampling them. | |
| 267 for (int i = 0; i < 10; i++) { | |
| 268 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 269 ASSERT_EQ(i >= 6, sampler.IsOverdueForSamplingAt(t)); | |
| 270 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | |
| 271 t += vsync; | |
| 272 } | |
| 273 | |
| 274 // Now suppose we can sample again. We should be back in the steady state. | |
| 275 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t)); | |
| 276 for (int i = 0; i < 100; i++) { | |
| 277 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 278 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 279 } | |
| 280 } | |
| 281 | |
| 282 // Tests that changing the minimum capture period during usage results in the | |
| 283 // desired behavior. | |
| 284 TEST(SmoothEventSamplerTest, Sample60HertzWithVariedCapturePeriods) { | |
| 285 const base::TimeDelta vsync = base::TimeDelta::FromSeconds(1) / 60; | |
| 286 const base::TimeDelta one_to_one_period = vsync; | |
| 287 const base::TimeDelta two_to_one_period = vsync * 2; | |
| 288 const base::TimeDelta two_and_three_to_one_period = | |
| 289 base::TimeDelta::FromSeconds(1) / 24; | |
| 290 const int redundant_capture_goal = 1; | |
| 291 | |
| 292 SmoothEventSampler sampler(one_to_one_period, redundant_capture_goal); | |
| 293 base::TimeTicks t = InitialTestTimeTicks(); | |
| 294 | |
| 295 TestRedundantCaptureStrategy(one_to_one_period, redundant_capture_goal, | |
| 296 &sampler, &t); | |
| 297 | |
| 298 // With the capture rate at 60 Hz, we should capture every vsync. | |
| 299 for (int i = 0; i < 100; i++) { | |
| 300 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 301 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 302 } | |
| 303 | |
| 304 // Now change to the capture rate to 30 Hz, and we should capture every other | |
| 305 // vsync. | |
| 306 sampler.SetMinCapturePeriod(two_to_one_period); | |
| 307 for (int i = 0; i < 100; i++) { | |
| 308 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 309 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 310 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 311 } | |
| 312 | |
| 313 // Now change the capture rate back to 60 Hz, and we should capture every | |
| 314 // vsync again. | |
| 315 sampler.SetMinCapturePeriod(one_to_one_period); | |
| 316 for (int i = 0; i < 100; i++) { | |
| 317 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 318 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 319 } | |
| 320 | |
| 321 // Now change the capture rate to 24 Hz, and we should capture with a 2-3-2-3 | |
| 322 // cadence. | |
| 323 sampler.SetMinCapturePeriod(two_and_three_to_one_period); | |
| 324 for (int i = 0; i < 100; i++) { | |
| 325 SCOPED_TRACE(base::StringPrintf("Iteration %d", i)); | |
| 326 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 327 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 328 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 329 SteadyStateNoSampleAndAdvance(vsync, &sampler, &t); | |
| 330 SteadyStateSampleAndAdvance(vsync, &sampler, &t); | |
| 331 } | |
| 332 } | |
| 333 | |
| 334 TEST(SmoothEventSamplerTest, DoubleDrawAtOneTimeStillDirties) { | |
| 335 const base::TimeDelta capture_period = base::TimeDelta::FromSeconds(1) / 30; | |
| 336 const base::TimeDelta overdue_period = base::TimeDelta::FromSeconds(1); | |
| 337 | |
| 338 SmoothEventSampler sampler(capture_period, 1); | |
| 339 base::TimeTicks t = InitialTestTimeTicks(); | |
| 340 | |
| 341 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | |
| 342 sampler.RecordSample(); | |
| 343 ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t)) | |
| 344 << "Sampled last event; should not be dirty."; | |
| 345 t += overdue_period; | |
| 346 | |
| 347 // Now simulate 2 events with the same clock value. | |
| 348 ASSERT_TRUE(AddEventAndConsiderSampling(&sampler, t)); | |
| 349 sampler.RecordSample(); | |
| 350 ASSERT_FALSE(AddEventAndConsiderSampling(&sampler, t)) | |
| 351 << "Two events at same time -- expected second not to be sampled."; | |
| 352 ASSERT_TRUE(sampler.IsOverdueForSamplingAt(t + overdue_period)) | |
| 353 << "Second event should dirty the capture state."; | |
| 354 sampler.RecordSample(); | |
| 355 ASSERT_FALSE(sampler.IsOverdueForSamplingAt(t + overdue_period)); | |
| 356 } | |
| 357 | |
| 358 namespace { | |
| 359 | |
| 360 struct DataPoint { | |
| 361 bool should_capture; | |
| 362 double increment_ms; | |
| 363 }; | |
| 364 | |
| 365 void ReplayCheckingSamplerDecisions(const DataPoint* data_points, | |
| 366 size_t num_data_points, | |
| 367 SmoothEventSampler* sampler) { | |
| 368 base::TimeTicks t = InitialTestTimeTicks(); | |
| 369 for (size_t i = 0; i < num_data_points; ++i) { | |
| 370 t += base::TimeDelta::FromMicroseconds( | |
| 371 static_cast<int64>(data_points[i].increment_ms * 1000)); | |
| 372 ASSERT_EQ(data_points[i].should_capture, | |
| 373 AddEventAndConsiderSampling(sampler, t)) | |
| 374 << "at data_points[" << i << ']'; | |
| 375 if (data_points[i].should_capture) | |
| 376 sampler->RecordSample(); | |
| 377 } | |
| 378 } | |
| 379 | |
| 380 } // namespace | |
| 381 | |
| 382 TEST(SmoothEventSamplerTest, DrawingAt24FpsWith60HzVsyncSampledAt30Hertz) { | |
| 383 // Actual capturing of timing data: Initial instability as a 24 FPS video was | |
| 384 // started from a still screen, then clearly followed by steady-state. | |
| 385 static const DataPoint data_points[] = { | |
| 386 { true, 1437.93 }, { true, 150.484 }, { true, 217.362 }, { true, 50.161 }, | |
| 387 { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 66.88 }, | |
| 388 { true, 50.161 }, { false, 0 }, { false, 0 }, { true, 50.16 }, | |
| 389 { true, 33.441 }, { true, 16.72 }, { false, 16.72 }, { true, 117.041 }, | |
| 390 { true, 16.72 }, { false, 16.72 }, { true, 50.161 }, { true, 50.16 }, | |
| 391 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 16.72 }, | |
| 392 { false, 0 }, { true, 50.161 }, { false, 0 }, { true, 33.44 }, | |
| 393 { true, 16.72 }, { false, 16.721 }, { true, 66.881 }, { false, 0 }, | |
| 394 { true, 33.441 }, { true, 16.72 }, { true, 50.16 }, { true, 16.72 }, | |
| 395 { false, 16.721 }, { true, 50.161 }, { true, 50.16 }, { false, 0 }, | |
| 396 { true, 33.441 }, { true, 50.337 }, { true, 50.183 }, { true, 16.722 }, | |
| 397 { true, 50.161 }, { true, 33.441 }, { true, 50.16 }, { true, 33.441 }, | |
| 398 { true, 50.16 }, { true, 33.441 }, { true, 50.16 }, { true, 33.44 }, | |
| 399 { true, 50.161 }, { true, 50.16 }, { true, 33.44 }, { true, 33.441 }, | |
| 400 { true, 50.16 }, { true, 50.161 }, { true, 33.44 }, { true, 33.441 }, | |
| 401 { true, 50.16 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 }, | |
| 402 { true, 50.161 }, { true, 33.44 }, { true, 50.161 }, { true, 33.44 }, | |
| 403 { true, 83.601 }, { true, 16.72 }, { true, 33.44 }, { false, 0 } | |
| 404 }; | |
| 405 | |
| 406 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); | |
| 407 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); | |
| 408 } | |
| 409 | |
| 410 TEST(SmoothEventSamplerTest, DrawingAt30FpsWith60HzVsyncSampledAt30Hertz) { | |
| 411 // Actual capturing of timing data: Initial instability as a 30 FPS video was | |
| 412 // started from a still screen, then followed by steady-state. Drawing | |
| 413 // framerate from the video rendering was a bit volatile, but averaged 30 FPS. | |
| 414 static const DataPoint data_points[] = { | |
| 415 { true, 2407.69 }, { true, 16.733 }, { true, 217.362 }, { true, 33.441 }, | |
| 416 { true, 33.44 }, { true, 33.44 }, { true, 33.441 }, { true, 33.44 }, | |
| 417 { true, 33.44 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, | |
| 418 { true, 16.721 }, { true, 33.44 }, { false, 0 }, { true, 50.161 }, | |
| 419 { true, 50.16 }, { false, 0 }, { true, 50.161 }, { true, 33.44 }, | |
| 420 { true, 16.72 }, { false, 0 }, { false, 16.72 }, { true, 66.881 }, | |
| 421 { false, 0 }, { true, 33.44 }, { true, 16.72 }, { true, 50.161 }, | |
| 422 { false, 0 }, { true, 33.538 }, { true, 33.526 }, { true, 33.447 }, | |
| 423 { true, 33.445 }, { true, 33.441 }, { true, 16.721 }, { true, 33.44 }, | |
| 424 { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, { true, 33.44 }, | |
| 425 { true, 33.441 }, { true, 33.44 }, { false, 0 }, { false, 16.72 }, | |
| 426 { true, 66.881 }, { true, 16.72 }, { false, 16.72 }, { true, 50.16 }, | |
| 427 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { true, 33.44 }, | |
| 428 { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { false, 0 }, | |
| 429 { true, 33.44 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, | |
| 430 { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 66.88 }, | |
| 431 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 }, | |
| 432 { true, 33.441 }, { true, 33.44 }, { true, 33.44 }, { false, 0 }, | |
| 433 { true, 16.72 }, { true, 50.161 }, { false, 0 }, { true, 50.16 }, | |
| 434 { false, 0.001 }, { true, 16.721 }, { true, 66.88 }, { true, 33.44 }, | |
| 435 { true, 33.441 }, { true, 33.44 }, { true, 50.161 }, { true, 16.72 }, | |
| 436 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 66.881 }, | |
| 437 { true, 33.44 }, { true, 16.72 }, { true, 33.441 }, { false, 16.72 }, | |
| 438 { true, 66.88 }, { true, 16.721 }, { true, 50.16 }, { true, 33.44 }, | |
| 439 { true, 16.72 }, { true, 33.441 }, { true, 33.44 }, { true, 33.44 } | |
| 440 }; | |
| 441 | |
| 442 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); | |
| 443 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); | |
| 444 } | |
| 445 | |
| 446 TEST(SmoothEventSamplerTest, DrawingAt60FpsWith60HzVsyncSampledAt30Hertz) { | |
| 447 // Actual capturing of timing data: WebGL Acquarium demo | |
| 448 // (http://webglsamples.googlecode.com/hg/aquarium/aquarium.html) which ran | |
| 449 // between 55-60 FPS in the steady-state. | |
| 450 static const DataPoint data_points[] = { | |
| 451 { true, 16.72 }, { true, 16.72 }, { true, 4163.29 }, { true, 50.193 }, | |
| 452 { true, 117.041 }, { true, 50.161 }, { true, 50.16 }, { true, 33.441 }, | |
| 453 { true, 50.16 }, { true, 33.44 }, { false, 0 }, { false, 0 }, | |
| 454 { true, 50.161 }, { true, 83.601 }, { true, 50.16 }, { true, 16.72 }, | |
| 455 { true, 33.441 }, { false, 16.72 }, { true, 50.16 }, { true, 16.72 }, | |
| 456 { false, 0.001 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, | |
| 457 { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, | |
| 458 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 }, | |
| 459 { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 }, | |
| 460 { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 }, | |
| 461 { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, | |
| 462 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 33.44 }, | |
| 463 { false, 0 }, { true, 16.721 }, { true, 50.161 }, { false, 0 }, | |
| 464 { true, 33.44 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, | |
| 465 { false, 0 }, { true, 33.44 }, { false, 16.72 }, { true, 16.72 }, | |
| 466 { true, 50.16 }, { false, 0 }, { true, 16.721 }, { true, 33.44 }, | |
| 467 { false, 0 }, { true, 33.44 }, { false, 16.721 }, { true, 16.721 }, | |
| 468 { true, 50.161 }, { false, 0 }, { true, 16.72 }, { true, 33.44 }, | |
| 469 { false, 0 }, { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, | |
| 470 { true, 50.16 }, { false, 0 }, { true, 16.72 }, { true, 33.441 }, | |
| 471 { true, 33.44 }, { false, 0 }, { true, 33.44 }, { true, 33.441 }, | |
| 472 { false, 0 }, { true, 33.44 }, { true, 33.441 }, { false, 0 }, | |
| 473 { true, 33.44 }, { false, 0 }, { true, 33.44 }, { false, 16.72 }, | |
| 474 { true, 16.721 }, { true, 50.161 }, { false, 0 }, { true, 16.72 }, | |
| 475 { true, 33.44 }, { true, 33.441 }, { false, 0 }, { true, 33.44 }, | |
| 476 { true, 33.44 }, { false, 0 }, { true, 33.441 }, { false, 16.72 }, | |
| 477 { true, 16.72 }, { true, 50.16 }, { false, 0 }, { true, 16.72 }, | |
| 478 { true, 33.441 }, { false, 0 }, { true, 33.44 }, { false, 16.72 }, | |
| 479 { true, 33.44 }, { false, 0 }, { true, 16.721 }, { true, 50.161 }, | |
| 480 { false, 0 }, { true, 16.72 }, { true, 33.44 }, { false, 0 }, | |
| 481 { true, 33.441 }, { false, 16.72 }, { true, 16.72 }, { true, 50.16 } | |
| 482 }; | |
| 483 | |
| 484 SmoothEventSampler sampler(base::TimeDelta::FromSeconds(1) / 30, 3); | |
| 485 ReplayCheckingSamplerDecisions(data_points, arraysize(data_points), &sampler); | |
| 486 } | |
| 487 | |
| 488 } // namespace content | |
| OLD | NEW |