mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 05:40:42 +01:00

Results from test (CallPerfTest.TestEncodeFramerateVp8Simulcast): Simulcast streams: 0: max_fps:20 -> StreamStats.encode_frame_rate:15 (before), 20 (after) 1: max_fps:30 Bug: webrtc:13031 Change-Id: I30e6b2dcb2746859bd3e21b098bfa7b0fb3b2dda Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/230120 Commit-Queue: Åsa Persson <asapersson@webrtc.org> Reviewed-by: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Erik Språng <sprang@webrtc.org> Cr-Commit-Position: refs/heads/main@{#34867}
162 lines
5.4 KiB
C++
162 lines
5.4 KiB
C++
/*
|
|
* 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
|