blob: 690076ca61b6ed2f186559bb3aebe943ffd1c943 [file] [log] [blame]
Åsa Persson062acd92021-08-16 07:33:131/*
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
18namespace webrtc {
19namespace {
20constexpr int kInputFps = 30;
21constexpr int kNumFrames = 60;
22} // namespace
23
24class FramerateControllerTest : public ::testing::Test {
25 protected:
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
36TEST_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
42TEST_F(FramerateControllerTest, AllFramesDroppedIfZeroRequested) {
43 controller_.SetMaxFramerate(0);
44
45 for (int i = 1; i < kNumFrames; ++i)
46 EXPECT_TRUE(controller_.ShouldDropFrame(GetNextTimestampNs()));
47}
48
49TEST_F(FramerateControllerTest, AllFramesDroppedIfNegativeRequested) {
50 controller_.SetMaxFramerate(-1);
51
52 for (int i = 1; i < kNumFrames; ++i)
53 EXPECT_TRUE(controller_.ShouldDropFrame(GetNextTimestampNs()));
54}
55
56TEST_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
64TEST_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
72TEST_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
79TEST_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
93TEST_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
104TEST_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
117TEST_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
132TEST_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
Åsa Persson59947d22021-08-26 10:04:27146TEST_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
Åsa Persson062acd92021-08-16 07:33:13162} // namespace webrtc