xref: /aosp_15_r20/external/webrtc/common_video/framerate_controller_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright 2021 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "common_video/framerate_controller.h"
12 
13 #include <limits>
14 
15 #include "rtc_base/time_utils.h"
16 #include "test/gtest.h"
17 
18 namespace webrtc {
19 namespace {
20 constexpr int kInputFps = 30;
21 constexpr int kNumFrames = 60;
22 }  // namespace
23 
24 class FramerateControllerTest : public ::testing::Test {
25  protected:
GetNextTimestampNs()26   int64_t GetNextTimestampNs() {
27     int64_t interval_us = rtc::kNumMicrosecsPerSec / kInputFps;
28     next_timestamp_us_ += interval_us;
29     return next_timestamp_us_ * rtc::kNumNanosecsPerMicrosec;
30   }
31 
32   int64_t next_timestamp_us_ = rtc::TimeMicros();
33   FramerateController controller_;
34 };
35 
TEST_F(FramerateControllerTest,NoFramesDroppedIfNothingRequested)36 TEST_F(FramerateControllerTest, NoFramesDroppedIfNothingRequested) {
37   // Default max framerate is maxdouble.
38   for (int i = 1; i < kNumFrames; ++i)
39     EXPECT_FALSE(controller_.ShouldDropFrame(GetNextTimestampNs()));
40 }
41 
TEST_F(FramerateControllerTest,AllFramesDroppedIfZeroRequested)42 TEST_F(FramerateControllerTest, AllFramesDroppedIfZeroRequested) {
43   controller_.SetMaxFramerate(0);
44 
45   for (int i = 1; i < kNumFrames; ++i)
46     EXPECT_TRUE(controller_.ShouldDropFrame(GetNextTimestampNs()));
47 }
48 
TEST_F(FramerateControllerTest,AllFramesDroppedIfNegativeRequested)49 TEST_F(FramerateControllerTest, AllFramesDroppedIfNegativeRequested) {
50   controller_.SetMaxFramerate(-1);
51 
52   for (int i = 1; i < kNumFrames; ++i)
53     EXPECT_TRUE(controller_.ShouldDropFrame(GetNextTimestampNs()));
54 }
55 
TEST_F(FramerateControllerTest,EverySecondFrameDroppedIfHalfRequested)56 TEST_F(FramerateControllerTest, EverySecondFrameDroppedIfHalfRequested) {
57   controller_.SetMaxFramerate(kInputFps / 2);
58 
59   // The first frame should not be dropped.
60   for (int i = 1; i < kNumFrames; ++i)
61     EXPECT_EQ(i % 2 == 0, controller_.ShouldDropFrame(GetNextTimestampNs()));
62 }
63 
TEST_F(FramerateControllerTest,EveryThirdFrameDroppedIfTwoThirdsRequested)64 TEST_F(FramerateControllerTest, EveryThirdFrameDroppedIfTwoThirdsRequested) {
65   controller_.SetMaxFramerate(kInputFps * 2 / 3);
66 
67   // The first frame should not be dropped.
68   for (int i = 1; i < kNumFrames; ++i)
69     EXPECT_EQ(i % 3 == 0, controller_.ShouldDropFrame(GetNextTimestampNs()));
70 }
71 
TEST_F(FramerateControllerTest,NoFrameDroppedIfTwiceRequested)72 TEST_F(FramerateControllerTest, NoFrameDroppedIfTwiceRequested) {
73   controller_.SetMaxFramerate(kInputFps * 2);
74 
75   for (int i = 1; i < kNumFrames; ++i)
76     EXPECT_FALSE(controller_.ShouldDropFrame(GetNextTimestampNs()));
77 }
78 
TEST_F(FramerateControllerTest,TestAverageFramerate)79 TEST_F(FramerateControllerTest, TestAverageFramerate) {
80   const double kMaxFps = 18.2;
81   controller_.SetMaxFramerate(kMaxFps);
82 
83   const int kNumSec = 10;
84   int frames_kept = 0;
85   for (int i = 0; i < kInputFps * kNumSec; ++i) {
86     if (!controller_.ShouldDropFrame(GetNextTimestampNs()))
87       ++frames_kept;
88   }
89   double average_fps = static_cast<double>(frames_kept) / kNumSec;
90   EXPECT_NEAR(kMaxFps, average_fps, 0.01);
91 }
92 
TEST_F(FramerateControllerTest,NoFrameDroppedForLargeTimestampOffset)93 TEST_F(FramerateControllerTest, NoFrameDroppedForLargeTimestampOffset) {
94   controller_.SetMaxFramerate(kInputFps);
95   EXPECT_FALSE(controller_.ShouldDropFrame(0));
96 
97   const int64_t kLargeOffsetNs = -987654321LL * 1000;
98   EXPECT_FALSE(controller_.ShouldDropFrame(kLargeOffsetNs));
99 
100   int64_t input_interval_ns = rtc::kNumNanosecsPerSec / kInputFps;
101   EXPECT_FALSE(controller_.ShouldDropFrame(kLargeOffsetNs + input_interval_ns));
102 }
103 
TEST_F(FramerateControllerTest,NoFrameDroppedIfInputWithJitterRequested)104 TEST_F(FramerateControllerTest, NoFrameDroppedIfInputWithJitterRequested) {
105   controller_.SetMaxFramerate(kInputFps);
106 
107   // Input fps with jitter.
108   int64_t input_interval_ns = rtc::kNumNanosecsPerSec / kInputFps;
109   EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 0 / 10));
110   EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 10 / 10 - 1));
111   EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 25 / 10));
112   EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 30 / 10));
113   EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 35 / 10));
114   EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 50 / 10));
115 }
116 
TEST_F(FramerateControllerTest,FrameDroppedWhenReductionRequested)117 TEST_F(FramerateControllerTest, FrameDroppedWhenReductionRequested) {
118   controller_.SetMaxFramerate(kInputFps);
119 
120   // Expect no frame drop.
121   for (int i = 1; i < kNumFrames; ++i)
122     EXPECT_FALSE(controller_.ShouldDropFrame(GetNextTimestampNs()));
123 
124   // Reduce max frame rate.
125   controller_.SetMaxFramerate(kInputFps / 2);
126 
127   // Verify that every other frame is dropped.
128   for (int i = 1; i < kNumFrames; ++i)
129     EXPECT_EQ(i % 2 == 0, controller_.ShouldDropFrame(GetNextTimestampNs()));
130 }
131 
TEST_F(FramerateControllerTest,NoFramesDroppedAfterReset)132 TEST_F(FramerateControllerTest, NoFramesDroppedAfterReset) {
133   controller_.SetMaxFramerate(0);
134 
135   // All frames dropped.
136   for (int i = 1; i < kNumFrames; ++i)
137     EXPECT_TRUE(controller_.ShouldDropFrame(GetNextTimestampNs()));
138 
139   controller_.Reset();
140 
141   // Expect no frame drop after reset.
142   for (int i = 1; i < kNumFrames; ++i)
143     EXPECT_FALSE(controller_.ShouldDropFrame(GetNextTimestampNs()));
144 }
145 
TEST_F(FramerateControllerTest,TestKeepFrame)146 TEST_F(FramerateControllerTest, TestKeepFrame) {
147   FramerateController controller(kInputFps / 2);
148 
149   EXPECT_FALSE(controller.ShouldDropFrame(GetNextTimestampNs()));
150   EXPECT_TRUE(controller.ShouldDropFrame(GetNextTimestampNs()));
151   EXPECT_FALSE(controller.ShouldDropFrame(GetNextTimestampNs()));
152   EXPECT_TRUE(controller.ShouldDropFrame(GetNextTimestampNs()));
153   EXPECT_FALSE(controller.ShouldDropFrame(GetNextTimestampNs()));
154 
155   // Next frame should be dropped.
156   // Keep this frame (e.g. in case of a key frame).
157   controller.KeepFrame(GetNextTimestampNs());
158   // Expect next frame to be dropped instead.
159   EXPECT_TRUE(controller.ShouldDropFrame(GetNextTimestampNs()));
160 }
161 
162 }  // namespace webrtc
163