diff options
Diffstat (limited to 'third_party/libwebrtc/common_video/framerate_controller_unittest.cc')
-rw-r--r-- | third_party/libwebrtc/common_video/framerate_controller_unittest.cc | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/third_party/libwebrtc/common_video/framerate_controller_unittest.cc b/third_party/libwebrtc/common_video/framerate_controller_unittest.cc new file mode 100644 index 0000000000..690076ca61 --- /dev/null +++ b/third_party/libwebrtc/common_video/framerate_controller_unittest.cc @@ -0,0 +1,162 @@ +/* + * Copyright 2021 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "common_video/framerate_controller.h" + +#include <limits> + +#include "rtc_base/time_utils.h" +#include "test/gtest.h" + +namespace webrtc { +namespace { +constexpr int kInputFps = 30; +constexpr int kNumFrames = 60; +} // namespace + +class FramerateControllerTest : public ::testing::Test { + protected: + int64_t GetNextTimestampNs() { + int64_t interval_us = rtc::kNumMicrosecsPerSec / kInputFps; + next_timestamp_us_ += interval_us; + return next_timestamp_us_ * rtc::kNumNanosecsPerMicrosec; + } + + int64_t next_timestamp_us_ = rtc::TimeMicros(); + FramerateController controller_; +}; + +TEST_F(FramerateControllerTest, NoFramesDroppedIfNothingRequested) { + // Default max framerate is maxdouble. + for (int i = 1; i < kNumFrames; ++i) + EXPECT_FALSE(controller_.ShouldDropFrame(GetNextTimestampNs())); +} + +TEST_F(FramerateControllerTest, AllFramesDroppedIfZeroRequested) { + controller_.SetMaxFramerate(0); + + for (int i = 1; i < kNumFrames; ++i) + EXPECT_TRUE(controller_.ShouldDropFrame(GetNextTimestampNs())); +} + +TEST_F(FramerateControllerTest, AllFramesDroppedIfNegativeRequested) { + controller_.SetMaxFramerate(-1); + + for (int i = 1; i < kNumFrames; ++i) + EXPECT_TRUE(controller_.ShouldDropFrame(GetNextTimestampNs())); +} + +TEST_F(FramerateControllerTest, EverySecondFrameDroppedIfHalfRequested) { + controller_.SetMaxFramerate(kInputFps / 2); + + // The first frame should not be dropped. + for (int i = 1; i < kNumFrames; ++i) + EXPECT_EQ(i % 2 == 0, controller_.ShouldDropFrame(GetNextTimestampNs())); +} + +TEST_F(FramerateControllerTest, EveryThirdFrameDroppedIfTwoThirdsRequested) { + controller_.SetMaxFramerate(kInputFps * 2 / 3); + + // The first frame should not be dropped. + for (int i = 1; i < kNumFrames; ++i) + EXPECT_EQ(i % 3 == 0, controller_.ShouldDropFrame(GetNextTimestampNs())); +} + +TEST_F(FramerateControllerTest, NoFrameDroppedIfTwiceRequested) { + controller_.SetMaxFramerate(kInputFps * 2); + + for (int i = 1; i < kNumFrames; ++i) + EXPECT_FALSE(controller_.ShouldDropFrame(GetNextTimestampNs())); +} + +TEST_F(FramerateControllerTest, TestAverageFramerate) { + const double kMaxFps = 18.2; + controller_.SetMaxFramerate(kMaxFps); + + const int kNumSec = 10; + int frames_kept = 0; + for (int i = 0; i < kInputFps * kNumSec; ++i) { + if (!controller_.ShouldDropFrame(GetNextTimestampNs())) + ++frames_kept; + } + double average_fps = static_cast<double>(frames_kept) / kNumSec; + EXPECT_NEAR(kMaxFps, average_fps, 0.01); +} + +TEST_F(FramerateControllerTest, NoFrameDroppedForLargeTimestampOffset) { + controller_.SetMaxFramerate(kInputFps); + EXPECT_FALSE(controller_.ShouldDropFrame(0)); + + const int64_t kLargeOffsetNs = -987654321LL * 1000; + EXPECT_FALSE(controller_.ShouldDropFrame(kLargeOffsetNs)); + + int64_t input_interval_ns = rtc::kNumNanosecsPerSec / kInputFps; + EXPECT_FALSE(controller_.ShouldDropFrame(kLargeOffsetNs + input_interval_ns)); +} + +TEST_F(FramerateControllerTest, NoFrameDroppedIfInputWithJitterRequested) { + controller_.SetMaxFramerate(kInputFps); + + // Input fps with jitter. + int64_t input_interval_ns = rtc::kNumNanosecsPerSec / kInputFps; + EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 0 / 10)); + EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 10 / 10 - 1)); + EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 25 / 10)); + EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 30 / 10)); + EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 35 / 10)); + EXPECT_FALSE(controller_.ShouldDropFrame(input_interval_ns * 50 / 10)); +} + +TEST_F(FramerateControllerTest, FrameDroppedWhenReductionRequested) { + controller_.SetMaxFramerate(kInputFps); + + // Expect no frame drop. + for (int i = 1; i < kNumFrames; ++i) + EXPECT_FALSE(controller_.ShouldDropFrame(GetNextTimestampNs())); + + // Reduce max frame rate. + controller_.SetMaxFramerate(kInputFps / 2); + + // Verify that every other frame is dropped. + for (int i = 1; i < kNumFrames; ++i) + EXPECT_EQ(i % 2 == 0, controller_.ShouldDropFrame(GetNextTimestampNs())); +} + +TEST_F(FramerateControllerTest, NoFramesDroppedAfterReset) { + controller_.SetMaxFramerate(0); + + // All frames dropped. + for (int i = 1; i < kNumFrames; ++i) + EXPECT_TRUE(controller_.ShouldDropFrame(GetNextTimestampNs())); + + controller_.Reset(); + + // Expect no frame drop after reset. + for (int i = 1; i < kNumFrames; ++i) + EXPECT_FALSE(controller_.ShouldDropFrame(GetNextTimestampNs())); +} + +TEST_F(FramerateControllerTest, TestKeepFrame) { + FramerateController controller(kInputFps / 2); + + EXPECT_FALSE(controller.ShouldDropFrame(GetNextTimestampNs())); + EXPECT_TRUE(controller.ShouldDropFrame(GetNextTimestampNs())); + EXPECT_FALSE(controller.ShouldDropFrame(GetNextTimestampNs())); + EXPECT_TRUE(controller.ShouldDropFrame(GetNextTimestampNs())); + EXPECT_FALSE(controller.ShouldDropFrame(GetNextTimestampNs())); + + // Next frame should be dropped. + // Keep this frame (e.g. in case of a key frame). + controller.KeepFrame(GetNextTimestampNs()); + // Expect next frame to be dropped instead. + EXPECT_TRUE(controller.ShouldDropFrame(GetNextTimestampNs())); +} + +} // namespace webrtc |