[M108 Migration][VD] Avoid pending frame counter becoming negative
[platform/framework/web/chromium-efl.git] / cc / metrics / video_playback_roughness_reporter_unittest.cc
1 // Copyright 2020 The Chromium Authors
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 "cc/metrics/video_playback_roughness_reporter.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <random>
10 #include <vector>
11
12 #include "base/callback.h"
13 #include "base/test/bind.h"
14 #include "base/time/time.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 using VideoFrame = media::VideoFrame;
18 using VideoFrameMetadata = media::VideoFrameMetadata;
19
20 namespace cc {
21
22 class VideoPlaybackRoughnessReporterTest : public ::testing::Test {
23  protected:
24   std::unique_ptr<VideoPlaybackRoughnessReporter> reporter_;
25   base::TimeTicks time_;
26   int token_ = 0;
27
28   template <class T>
29   void SetReportingCallabck(T cb) {
30     reporter_ = std::make_unique<VideoPlaybackRoughnessReporter>(
31         base::BindLambdaForTesting(cb));
32   }
33
34   VideoPlaybackRoughnessReporter* reporter() {
35     DCHECK(reporter_);
36     return reporter_.get();
37   }
38
39   scoped_refptr<VideoFrame> MakeFrame(base::TimeDelta duration,
40                                       int frame_size = 100) {
41     scoped_refptr<VideoFrame> result = media::VideoFrame::CreateColorFrame(
42         gfx::Size(frame_size, frame_size), 0x80, 0x80, 0x80, base::TimeDelta());
43     result->metadata().wallclock_frame_duration = duration;
44     return result;
45   }
46
47   ::testing::AssertionResult CheckSizes() {
48     size_t max_frames =
49         2 * size_t{VideoPlaybackRoughnessReporter::kMaxWindowSize};
50     if (reporter()->frames_.size() > max_frames)
51       return ::testing::AssertionFailure();
52
53     constexpr int max_worst_windows_size =
54         1 + VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit *
55                 (100 - VideoPlaybackRoughnessReporter::kPercentileToSubmit) /
56                 100;
57     if (reporter()->worst_windows_.size() > max_worst_windows_size)
58       return ::testing::AssertionFailure()
59              << "windows " << reporter()->worst_windows_.size();
60     return ::testing::AssertionSuccess();
61   }
62
63   void NormalRun(double fps,
64                  double hz,
65                  std::vector<int> cadence,
66                  int frames,
67                  int frame_size = 100) {
68     base::TimeDelta vsync = base::Seconds(1 / hz);
69     base::TimeDelta ideal_duration = base::Seconds(1 / fps);
70     for (int idx = 0; idx < frames; idx++) {
71       int frame_cadence = cadence[idx % cadence.size()];
72       base::TimeDelta duration = vsync * frame_cadence;
73       auto frame = MakeFrame(ideal_duration, frame_size);
74       reporter()->FrameSubmitted(token_, *frame, vsync);
75       reporter()->FramePresented(token_++, time_, true);
76       reporter()->ProcessFrameWindow();
77       time_ += duration;
78     }
79   }
80
81   void BatchPresentationRun(double fps,
82                             double hz,
83                             std::vector<int> cadence,
84                             int frames) {
85     base::TimeDelta vsync = base::Seconds(1 / hz);
86     base::TimeDelta ideal_duration = base::Seconds(1 / fps);
87     constexpr int batch_size = 3;
88     for (int idx = 0; idx < frames; idx++) {
89       auto frame = MakeFrame(ideal_duration);
90       reporter()->FrameSubmitted(idx, *frame, vsync);
91       if (idx % batch_size == batch_size - 1) {
92         for (int i = batch_size - 1; i >= 0; i--) {
93           int presented_idx = idx - i;
94           int frame_cadence = cadence[presented_idx % cadence.size()];
95           base::TimeDelta duration = vsync * frame_cadence;
96           reporter()->FramePresented(presented_idx, time_, true);
97           time_ += duration;
98         }
99       }
100
101       reporter()->ProcessFrameWindow();
102     }
103   }
104
105   void FreezingRun(double fps,
106                    double hz,
107                    std::vector<int> cadence,
108                    int frames,
109                    int frame_size = 100,
110                    int freeze_on_frame = 50,
111                    int frozen_vsyncs = 10) {
112     base::TimeDelta vsync = base::Seconds(1 / hz);
113     base::TimeDelta ideal_duration = base::Seconds(1 / fps);
114     for (int idx = 0; idx < frames; idx++) {
115       int frame_cadence = cadence[idx % cadence.size()];
116       base::TimeDelta duration = vsync * frame_cadence;
117       auto frame = MakeFrame(ideal_duration, frame_size);
118       reporter()->FrameSubmitted(token_, *frame, vsync);
119       reporter()->FramePresented(token_++, time_, true);
120       reporter()->ProcessFrameWindow();
121       if (idx == freeze_on_frame)
122         time_ += duration * frozen_vsyncs;
123       else
124         time_ += duration;
125     }
126   }
127 };
128
129 TEST_F(VideoPlaybackRoughnessReporterTest, BestCase24fps) {
130   int call_count = 0;
131   int fps = 24;
132   SetReportingCallabck(
133       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
134         ASSERT_EQ(measurement.frames, fps);
135         ASSERT_EQ(measurement.refresh_rate_hz, 60);
136         ASSERT_NEAR(measurement.duration.InMillisecondsF(), 1000.0, 1.0);
137         ASSERT_NEAR(measurement.roughness, 5.9, 0.1);
138         ASSERT_NEAR(measurement.freezing.InSecondsF(), 0.0, 0.1);
139         call_count++;
140       });
141   int frames_to_run =
142       VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit * fps + 10;
143   NormalRun(fps, 60, {2, 3}, frames_to_run);
144   EXPECT_EQ(call_count, 1);
145 }
146
147 TEST_F(VideoPlaybackRoughnessReporterTest, BestCase24fpsOn120Hz) {
148   int call_count = 0;
149   int fps = 24;
150   SetReportingCallabck(
151       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
152         ASSERT_EQ(measurement.frames, fps);
153         ASSERT_EQ(measurement.refresh_rate_hz, 120);
154         ASSERT_NEAR(measurement.duration.InMillisecondsF(), 1000.0, 1.0);
155         ASSERT_NEAR(measurement.roughness, 0.0, 0.1);
156         ASSERT_NEAR(measurement.freezing.InSecondsF(), 0.0, 0.1);
157         call_count++;
158       });
159   int frames_to_run =
160       VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit * fps + 10;
161   NormalRun(fps, 120, {5}, frames_to_run);
162   EXPECT_EQ(call_count, 1);
163 }
164
165 TEST_F(VideoPlaybackRoughnessReporterTest, BestCase30fps) {
166   int call_count = 0;
167   int fps = 30;
168   SetReportingCallabck(
169       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
170         ASSERT_EQ(measurement.frames, fps);
171         ASSERT_NEAR(measurement.duration.InMillisecondsF(), 1000.0, 1.0);
172         ASSERT_NEAR(measurement.roughness, 0.0, 0.1);
173         ASSERT_NEAR(measurement.freezing.InSecondsF(), 0.0, 0.1);
174         call_count++;
175       });
176   int frames_to_run =
177       VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit * fps + 1;
178   NormalRun(fps, 60, {2}, frames_to_run);
179   EXPECT_EQ(call_count, 1);
180 }
181
182 // This cadence pattern was used in the small user study and was found
183 // to be perceived by participants as not as good as ideal 30fps playback but
184 // better than the pattern from UserStudyBad.
185 // The main characteristic of this test is that cadence breaks by having a frame
186 // shown only once, but the very next frame is being shown 3 times thus
187 // fixing the synchronization.
188 TEST_F(VideoPlaybackRoughnessReporterTest, UserStudyOkay) {
189   int call_count = 0;
190   int fps = 30;
191   SetReportingCallabck(
192       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
193         ASSERT_EQ(measurement.frames, fps);
194         ASSERT_NEAR(measurement.duration.InMillisecondsF(), 1000.0, 1.0);
195         ASSERT_NEAR(measurement.roughness, 4.3, 0.1);
196         ASSERT_NEAR(measurement.freezing.InSecondsF(), 0.0, 0.1);
197         call_count++;
198       });
199   int frames_to_run =
200       VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit * fps + 1;
201   NormalRun(fps, 60, {2, 2, 2, 2, 2, 2, 1, 3, 2, 2, 2, 2, 2, 2, 2},
202             frames_to_run);
203   EXPECT_EQ(call_count, 1);
204 }
205
206 // This cadence pattern was used in the small user study and was found
207 // to be perceived as worst of all options in the study.
208 // The main characteristic of this test is that cadence breaks by having a frame
209 // shown only once, and it takes 2 more frames for a frame that is shown 3 times
210 // thus fixing the synchronization.
211 TEST_F(VideoPlaybackRoughnessReporterTest, UserStudyBad) {
212   int call_count = 0;
213   int fps = 30;
214   SetReportingCallabck(
215       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
216         ASSERT_EQ(measurement.frames, fps);
217         ASSERT_NEAR(measurement.duration.InMillisecondsF(), 1000.0, 1.0);
218         ASSERT_NEAR(measurement.roughness, 7.46, 0.1);
219         ASSERT_NEAR(measurement.freezing.InSecondsF(), 0.0, 0.1);
220         call_count++;
221       });
222   int frames_to_run =
223       VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit * fps + 1;
224   NormalRun(fps, 60, {2, 2, 2, 2, 2, 1, 2, 2, 3, 2, 2, 2, 2, 2, 2},
225             frames_to_run);
226   EXPECT_EQ(call_count, 1);
227 }
228
229 TEST_F(VideoPlaybackRoughnessReporterTest, Glitchy24fps) {
230   int call_count = 0;
231   int fps = 24;
232   SetReportingCallabck(
233       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
234         ASSERT_EQ(measurement.frames, fps);
235         ASSERT_NEAR(measurement.duration.InMillisecondsF(), 1000.0, 1.0);
236         ASSERT_NEAR(measurement.roughness, 14.8, 0.1);
237         ASSERT_NEAR(measurement.freezing.InSecondsF(), 0.0, 0.1);
238         call_count++;
239       });
240   int frames_to_run =
241       VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit * fps + 1;
242   NormalRun(fps, 60, {2, 3, 1, 3, 2, 4, 2, 3, 2, 3, 3, 3}, frames_to_run);
243   EXPECT_EQ(call_count, 1);
244 }
245
246 TEST_F(VideoPlaybackRoughnessReporterTest, BestCase60fps) {
247   int call_count = 0;
248   int fps = 60;
249   SetReportingCallabck(
250       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
251         ASSERT_EQ(measurement.frames, fps);
252         ASSERT_NEAR(measurement.duration.InMillisecondsF(), 1000.0, 1.0);
253         ASSERT_NEAR(measurement.roughness, 0.0, 0.1);
254         ASSERT_NEAR(measurement.freezing.InSecondsF(), 0.0, 0.1);
255         call_count++;
256       });
257   int frames_to_run =
258       VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit * fps + 1;
259   NormalRun(fps, 60, {1}, frames_to_run);
260   EXPECT_EQ(call_count, 1);
261 }
262
263 TEST_F(VideoPlaybackRoughnessReporterTest, BestCase50fps) {
264   int call_count = 0;
265   int fps = 50;
266   SetReportingCallabck(
267       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
268         ASSERT_EQ(measurement.frames, fps);
269         ASSERT_NEAR(measurement.duration.InMillisecondsF(), 1000.0, 1.0);
270         ASSERT_NEAR(measurement.roughness, 8.1, 01);
271         ASSERT_NEAR(measurement.freezing.InSecondsF(), 0.0, 0.1);
272         call_count++;
273       });
274   int frames_to_run =
275       VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit * fps + 1;
276   NormalRun(fps, 60, {1, 1, 1, 1, 2}, frames_to_run);
277   EXPECT_EQ(call_count, 1);
278 }
279
280 // Test that we understand the roughness algorithm by checking that we can
281 // get any result we need.
282 TEST_F(VideoPlaybackRoughnessReporterTest, PredictableRoughnessValue) {
283   int fps = 12;
284   int frames_in_window = fps;
285   int call_count = 0;
286   double intended_roughness = 4.2;
287   base::TimeDelta vsync = base::Seconds(1.0 / fps);
288   // Calculating the error value that needs to be injected into one frame
289   // in order to get desired roughness.
290   base::TimeDelta error = base::Milliseconds(
291       std::sqrt(intended_roughness * intended_roughness * frames_in_window));
292
293   auto callback =
294       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
295         ASSERT_EQ(frames_in_window, measurement.frames);
296         ASSERT_NEAR(measurement.roughness, intended_roughness, 0.1);
297         ASSERT_NEAR(measurement.freezing.InSecondsF(), 0.0, 0.1);
298         call_count++;
299       };
300   SetReportingCallabck(callback);
301   int token = 0;
302   int win_count = 50;
303   for (int win_idx = 0; win_idx < win_count; win_idx++) {
304     for (int frame_idx = 0; frame_idx < frames_in_window; frame_idx++) {
305       base::TimeTicks time;
306       time += token * vsync;
307       if (frame_idx == frames_in_window - 1)
308         time += error;
309
310       auto frame = MakeFrame(vsync);
311       reporter()->FrameSubmitted(token, *frame, vsync);
312       reporter()->FramePresented(token++, time, true);
313       reporter()->ProcessFrameWindow();
314     }
315   }
316   reporter()->Reset();
317   EXPECT_EQ(call_count, 1);
318 }
319
320 // Test that the reporter indeed takes 95% worst window.
321 TEST_F(VideoPlaybackRoughnessReporterTest, TakingPercentile) {
322   int token = 0;
323   int fps = 12;
324   int frames_in_window = fps;
325   int call_count = 0;
326   int win_count = 100;
327   base::TimeDelta vsync = base::Seconds(1.0 / fps);
328   std::vector<double> targets;
329   targets.reserve(win_count);
330   for (int i = 0; i < win_count; i++)
331     targets.push_back(i * 0.1);
332   double expected_roughness =
333       VideoPlaybackRoughnessReporter::kPercentileToSubmit * 0.1;
334   std::mt19937 rnd(1);
335   std::shuffle(targets.begin(), targets.end(), rnd);
336
337   auto callback =
338       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
339         ASSERT_EQ(frames_in_window, measurement.frames);
340         ASSERT_NEAR(measurement.roughness, expected_roughness, 0.05);
341         call_count++;
342       };
343   SetReportingCallabck(callback);
344
345   for (int win_idx = 0; win_idx < win_count; win_idx++) {
346     double roughness = targets[win_idx];
347     // Calculating the error value that needs to be injected into one frame
348     // in order to get desired roughness.
349     base::TimeDelta error =
350         base::Milliseconds(std::sqrt(roughness * roughness * frames_in_window));
351
352     for (int frame_idx = 0; frame_idx < frames_in_window; frame_idx++) {
353       base::TimeTicks time;
354       time += token * vsync;
355       if (frame_idx == frames_in_window - 1)
356         time += error;
357
358       auto frame = MakeFrame(vsync);
359       reporter()->FrameSubmitted(token, *frame, vsync);
360       reporter()->FramePresented(token++, time, true);
361       reporter()->ProcessFrameWindow();
362     }
363   }
364   reporter()->Reset();
365   EXPECT_EQ(call_count, 1);
366 }
367
368 // Test that even if no windows can be reported due to unstable presentation
369 // feedback, the reporter still doesn't run out of memory.
370 TEST_F(VideoPlaybackRoughnessReporterTest, LongRunWithoutWindows) {
371   int call_count = 0;
372   base::TimeDelta vsync = base::Milliseconds(1);
373   SetReportingCallabck(
374       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
375         call_count++;
376       });
377   for (int i = 0; i < 10000; i++) {
378     auto frame = MakeFrame(vsync);
379     reporter()->FrameSubmitted(i, *frame, vsync);
380     if (i % 2 == 0)
381       reporter()->FramePresented(i, base::TimeTicks() + i * vsync, true);
382     reporter()->ProcessFrameWindow();
383     ASSERT_TRUE(CheckSizes());
384   }
385   EXPECT_EQ(call_count, 0);
386 }
387
388 // Test that the reporter is no spooked by FramePresented() on unknown frame
389 // tokens.
390 TEST_F(VideoPlaybackRoughnessReporterTest, PresentingUnknownFrames) {
391   int call_count = 0;
392   base::TimeDelta vsync = base::Milliseconds(1);
393   SetReportingCallabck(
394       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
395         call_count++;
396       });
397   for (int i = 0; i < 10000; i++) {
398     auto frame = MakeFrame(vsync);
399     reporter()->FrameSubmitted(i, *frame, vsync);
400     reporter()->FramePresented(i + 100000, base::TimeTicks() + i * vsync, true);
401     reporter()->ProcessFrameWindow();
402     ASSERT_TRUE(CheckSizes());
403   }
404   EXPECT_EQ(call_count, 0);
405 }
406
407 // Test that the reporter is ignoring frames with unreliable
408 // presentation timestamp.
409 TEST_F(VideoPlaybackRoughnessReporterTest, IgnoringUnreliableTimings) {
410   int call_count = 0;
411   base::TimeDelta vsync = base::Milliseconds(1);
412   SetReportingCallabck(
413       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
414         call_count++;
415       });
416   for (int i = 0; i < 10000; i++) {
417     auto frame = MakeFrame(vsync);
418     reporter()->FrameSubmitted(i, *frame, vsync);
419     reporter()->FramePresented(i, base::TimeTicks() + i * vsync, false);
420     reporter()->ProcessFrameWindow();
421     ASSERT_TRUE(CheckSizes());
422   }
423   EXPECT_EQ(call_count, 0);
424 }
425
426 // Test that Reset() causes reporting if there is sufficient number of windows
427 // accumulated.
428 TEST_F(VideoPlaybackRoughnessReporterTest, ReportingInReset) {
429   int call_count = 0;
430   int fps = 60;
431   auto callback =
432       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
433         call_count++;
434       };
435   SetReportingCallabck(callback);
436
437   // Set number of frames insufficient for reporting in Reset()
438   int frames_to_run =
439       VideoPlaybackRoughnessReporter::kMinWindowsBeforeSubmit * fps - 1;
440   NormalRun(fps, 60, {1}, frames_to_run);
441   // No calls since, not enough windows were reported
442   EXPECT_EQ(call_count, 0);
443
444   // Reset the reporter, still no calls
445   reporter()->Reset();
446   EXPECT_EQ(call_count, 0);
447
448   // Set number of frames sufficient for reporting in Reset()
449   frames_to_run =
450       VideoPlaybackRoughnessReporter::kMinWindowsBeforeSubmit * fps + 1;
451   NormalRun(fps, 60, {1}, frames_to_run);
452
453   // No calls since, not enough windows were reported
454   EXPECT_EQ(call_count, 0);
455
456   // A window should be reported in the Reset()
457   reporter()->Reset();
458   EXPECT_EQ(call_count, 1);
459 }
460
461 // Test that a change of display refresh rate or frame size causes reporting
462 // iff there is sufficient number of windows accumulated.
463 TEST_F(VideoPlaybackRoughnessReporterTest, ReportingAfterParameterChange) {
464   struct Report {
465     int hz;
466     int height;
467     double roughness;
468   };
469   std::vector<Report> reports;
470   int fps = 60;
471   auto callback =
472       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
473         reports.push_back({measurement.refresh_rate_hz,
474                            measurement.frame_size.height(),
475                            measurement.roughness});
476       };
477   SetReportingCallabck(callback);
478
479   int frames_to_run =
480       (VideoPlaybackRoughnessReporter::kMinWindowsBeforeSubmit - 1) * fps + 3;
481   NormalRun(fps, 59, {1}, frames_to_run, 480);
482   ASSERT_TRUE(reports.empty());
483
484   frames_to_run =
485       (VideoPlaybackRoughnessReporter::kMinWindowsBeforeSubmit + 1) * fps + 3;
486   NormalRun(fps, 60, {1}, frames_to_run, 480);
487   // Check that if parameters change after only a few windows, nothing gets
488   // reported.
489   ASSERT_TRUE(reports.empty());
490
491   frames_to_run =
492       (VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit + 1) * fps + 3;
493   NormalRun(fps, 120, {2}, frames_to_run, 481);
494
495   // Check that if parameters change after sufficient number of windows
496   // roughness is reported. The second report is done normally after max
497   // number of windows is seen.
498   ASSERT_EQ(reports.size(), 2u);
499   EXPECT_EQ(reports[0].hz, 60);
500   EXPECT_EQ(reports[0].height, 480);
501   EXPECT_EQ(reports[0].roughness, 0.0);
502   EXPECT_EQ(reports[1].hz, 120);
503   EXPECT_EQ(reports[1].height, 481);
504   EXPECT_EQ(reports[1].roughness, 0.0);
505 }
506
507 // Test that reporting works even if frame presentation signal come out of
508 // order.
509 TEST_F(VideoPlaybackRoughnessReporterTest, BatchPresentation) {
510   int call_count = 0;
511   int fps = 60;
512
513   // Try 60 fps
514   SetReportingCallabck(
515       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
516         ASSERT_EQ(measurement.frames, fps);
517         ASSERT_NEAR(measurement.duration.InMillisecondsF(), 1000.0, 1.0);
518         ASSERT_NEAR(measurement.roughness, 0.0, 0.1);
519         call_count++;
520       });
521   int frames_to_run =
522       VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit * fps + 10;
523   BatchPresentationRun(fps, 60, {1}, frames_to_run);
524   EXPECT_EQ(call_count, 1);
525
526   // Try 24fps
527   SetReportingCallabck(
528       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
529         ASSERT_EQ(measurement.frames, fps);
530         ASSERT_NEAR(measurement.duration.InMillisecondsF(), 1000.0, 1.0);
531         ASSERT_NEAR(measurement.roughness, 5.9, 0.1);
532         ASSERT_NEAR(measurement.freezing.InSecondsF(), 0, 0.01);
533         call_count++;
534       });
535   fps = 24;
536   frames_to_run =
537       VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit * fps + 10;
538   BatchPresentationRun(fps, 60, {2, 3}, frames_to_run);
539   EXPECT_EQ(call_count, 2);
540 }
541
542 TEST_F(VideoPlaybackRoughnessReporterTest, Freezing30fps) {
543   int call_count = 0;
544   int fps = 30;
545   SetReportingCallabck(
546       [&](const VideoPlaybackRoughnessReporter::Measurement& measurement) {
547         ASSERT_EQ(measurement.frames, fps);
548         ASSERT_NEAR(measurement.duration.InMillisecondsF(), 1000.0, 1.0);
549         ASSERT_NEAR(measurement.roughness, 0.0, 0.1);
550         ASSERT_NEAR(measurement.freezing.InSecondsF(), 0.25, 0.05);
551         call_count++;
552       });
553   int frames_to_run =
554       VideoPlaybackRoughnessReporter::kMaxWindowsBeforeSubmit * fps + 1;
555   FreezingRun(fps, 60, {2}, frames_to_run);
556   EXPECT_EQ(call_count, 1);
557 }
558
559 }  // namespace cc