summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc')
-rw-r--r--third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc145
1 files changed, 132 insertions, 13 deletions
diff --git a/third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc b/third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc
index 052b0a6c61..0fef2400f0 100644
--- a/third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc
+++ b/third_party/libwebrtc/video/frame_cadence_adapter_unittest.cc
@@ -70,7 +70,7 @@ std::unique_ptr<FrameCadenceAdapterInterface> CreateAdapter(
class MockCallback : public FrameCadenceAdapterInterface::Callback {
public:
- MOCK_METHOD(void, OnFrame, (Timestamp, int, const VideoFrame&), (override));
+ MOCK_METHOD(void, OnFrame, (Timestamp, bool, const VideoFrame&), (override));
MOCK_METHOD(void, OnDiscardedFrame, (), (override));
MOCK_METHOD(void, RequestRefreshFrame, (), (override));
};
@@ -115,13 +115,13 @@ TEST(FrameCadenceAdapterTest, CountsOutstandingFramesToProcess) {
MockCallback callback;
auto adapter = CreateAdapter(no_field_trials, time_controller.GetClock());
adapter->Initialize(&callback);
- EXPECT_CALL(callback, OnFrame(_, 2, _)).Times(1);
- EXPECT_CALL(callback, OnFrame(_, 1, _)).Times(1);
+ EXPECT_CALL(callback, OnFrame(_, true, _)).Times(1);
+ EXPECT_CALL(callback, OnFrame(_, false, _)).Times(1);
auto frame = CreateFrame();
adapter->OnFrame(frame);
adapter->OnFrame(frame);
time_controller.AdvanceTime(TimeDelta::Zero());
- EXPECT_CALL(callback, OnFrame(_, 1, _)).Times(1);
+ EXPECT_CALL(callback, OnFrame(_, false, _)).Times(1);
adapter->OnFrame(frame);
time_controller.AdvanceTime(TimeDelta::Zero());
}
@@ -184,6 +184,29 @@ TEST(FrameCadenceAdapterTest, FrameRateFollowsMaxFpsWhenZeroHertzActivated) {
}
}
+TEST(FrameCadenceAdapterTest, ZeroHertzAdapterSupportsMaxFpsChange) {
+ ZeroHertzFieldTrialEnabler enabler;
+ GlobalSimulatedTimeController time_controller(Timestamp::Zero());
+ auto adapter = CreateAdapter(enabler, time_controller.GetClock());
+ MockCallback callback;
+ adapter->Initialize(&callback);
+ adapter->SetZeroHertzModeEnabled(
+ FrameCadenceAdapterInterface::ZeroHertzModeParams{});
+ adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 1});
+ time_controller.AdvanceTime(TimeDelta::Zero());
+ EXPECT_EQ(adapter->GetInputFrameRateFps(), 1u);
+ adapter->OnFrame(CreateFrame());
+ time_controller.AdvanceTime(TimeDelta::Seconds(1));
+ adapter->OnConstraintsChanged(VideoTrackSourceConstraints{0, 2});
+ time_controller.AdvanceTime(TimeDelta::Zero());
+ EXPECT_EQ(adapter->GetInputFrameRateFps(), 2u);
+ adapter->OnFrame(CreateFrame());
+ // Ensure that the max_fps has been changed from 1 to 2 fps even if it was
+ // changed while zero hertz was already active.
+ EXPECT_CALL(callback, OnFrame);
+ time_controller.AdvanceTime(TimeDelta::Millis(500));
+}
+
TEST(FrameCadenceAdapterTest,
FrameRateFollowsRateStatisticsAfterZeroHertzDeactivated) {
ZeroHertzFieldTrialEnabler enabler;
@@ -230,7 +253,7 @@ TEST(FrameCadenceAdapterTest, ForwardsFramesDelayed) {
EXPECT_CALL(callback, OnFrame).Times(0);
adapter->OnFrame(frame);
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int,
+ .WillOnce(Invoke([&](Timestamp post_time, bool,
const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(),
@@ -309,7 +332,7 @@ TEST(FrameCadenceAdapterTest, RepeatsFramesDelayed) {
adapter->OnFrame(frame);
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(), original_timestamp_us);
EXPECT_EQ(frame.ntp_time_ms(), original_ntp_time.ToMs());
@@ -318,7 +341,7 @@ TEST(FrameCadenceAdapterTest, RepeatsFramesDelayed) {
Mock::VerifyAndClearExpectations(&callback);
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(),
original_timestamp_us + rtc::kNumMicrosecsPerSec);
@@ -329,7 +352,7 @@ TEST(FrameCadenceAdapterTest, RepeatsFramesDelayed) {
Mock::VerifyAndClearExpectations(&callback);
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(),
original_timestamp_us + 2 * rtc::kNumMicrosecsPerSec);
@@ -359,7 +382,7 @@ TEST(FrameCadenceAdapterTest,
// Send one frame, expect a repeat.
adapter->OnFrame(CreateFrame());
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(), 0);
EXPECT_EQ(frame.ntp_time_ms(), 0);
@@ -367,7 +390,7 @@ TEST(FrameCadenceAdapterTest,
time_controller.AdvanceTime(TimeDelta::Seconds(1));
Mock::VerifyAndClearExpectations(&callback);
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp post_time, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp post_time, bool, const VideoFrame& frame) {
EXPECT_EQ(post_time, time_controller.GetClock()->CurrentTime());
EXPECT_EQ(frame.timestamp_us(), 0);
EXPECT_EQ(frame.ntp_time_ms(), 0);
@@ -399,7 +422,7 @@ TEST(FrameCadenceAdapterTest, StopsRepeatingFramesDelayed) {
// Send the new frame at 2.5s, which should appear after 3.5s.
adapter->OnFrame(CreateFrameWithTimestamps(&time_controller));
EXPECT_CALL(callback, OnFrame)
- .WillOnce(Invoke([&](Timestamp, int, const VideoFrame& frame) {
+ .WillOnce(Invoke([&](Timestamp, bool, const VideoFrame& frame) {
EXPECT_EQ(frame.timestamp_us(), 5 * rtc::kNumMicrosecsPerSec / 2);
EXPECT_EQ(frame.ntp_time_ms(),
original_ntp_time.ToMs() + 5u * rtc::kNumMillisecsPerSec / 2);
@@ -708,6 +731,8 @@ class ZeroHertzLayerQualityConvergenceTest : public ::testing::Test {
static constexpr TimeDelta kMinFrameDelay = TimeDelta::Millis(100);
static constexpr TimeDelta kIdleFrameDelay =
FrameCadenceAdapterInterface::kZeroHertzIdleRepeatRatePeriod;
+ // Restricts non-idle repeat rate to 5 fps (default is 10 fps);
+ static constexpr int kRestrictedMaxFps = 5;
ZeroHertzLayerQualityConvergenceTest() {
adapter_->Initialize(&callback_);
@@ -725,7 +750,7 @@ class ZeroHertzLayerQualityConvergenceTest : public ::testing::Test {
std::initializer_list<TimeDelta> list) {
Timestamp origin = time_controller_.GetClock()->CurrentTime();
for (auto delay : list) {
- EXPECT_CALL(callback_, OnFrame(origin + delay, _, _));
+ EXPECT_CALL(callback_, OnFrame(origin + delay, false, _));
time_controller_.AdvanceTime(origin + delay -
time_controller_.GetClock()->CurrentTime());
}
@@ -810,6 +835,100 @@ TEST_F(ZeroHertzLayerQualityConvergenceTest,
});
}
+TEST_F(ZeroHertzLayerQualityConvergenceTest,
+ UnconvergedRepeatRateAdaptsDownWhenRestricted) {
+ PassFrame();
+ ScheduleDelayed(1.5 * kMinFrameDelay, [&] {
+ adapter_->UpdateVideoSourceRestrictions(kRestrictedMaxFps);
+ });
+ ExpectFrameEntriesAtDelaysFromNow({
+ 1 * kMinFrameDelay, // Original frame emitted at non-restricted rate.
+
+ // 1.5 * kMinFrameDelay: restricts max fps to 5 fps which should result
+ // in a new non-idle repeat delay of 2 * kMinFrameDelay.
+ 2 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
+ 4 * kMinFrameDelay, // Unconverged repeats at restricted rate. This
+ // happens 2 * kMinFrameDelay after the last frame.
+ 6 * kMinFrameDelay, // ...
+ });
+}
+
+TEST_F(ZeroHertzLayerQualityConvergenceTest,
+ UnconvergedRepeatRateAdaptsUpWhenGoingFromRestrictedToUnrestricted) {
+ PassFrame();
+ ScheduleDelayed(1.5 * kMinFrameDelay, [&] {
+ adapter_->UpdateVideoSourceRestrictions(kRestrictedMaxFps);
+ });
+ ScheduleDelayed(5.5 * kMinFrameDelay, [&] {
+ adapter_->UpdateVideoSourceRestrictions(absl::nullopt);
+ });
+ ExpectFrameEntriesAtDelaysFromNow({
+ 1 * kMinFrameDelay, // Original frame emitted at non-restricted rate.
+
+ // 1.5 * kMinFrameDelay: restricts max fps to 5 fps which should result
+ // in a new non-idle repeat delay of 2 * kMinFrameDelay.
+ 2 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
+ 4 * kMinFrameDelay, // Unconverged repeat at restricted rate.
+
+ // 5.5 * kMinFrameDelay: removes frame-rate restriction and we should
+ // then go back to 10 fps as unconverged repeat rate.
+ 6 * kMinFrameDelay, // Last unconverged repeat at restricted rate.
+ 7 * kMinFrameDelay, // Back to unconverged repeat at non-restricted rate.
+ 8 * kMinFrameDelay, // We are now unrestricted.
+ 9 * kMinFrameDelay, // ...
+ });
+}
+
+TEST_F(ZeroHertzLayerQualityConvergenceTest,
+ UnconvergedRepeatRateMaintainsRestrictionOnReconfigureToHigherMaxFps) {
+ PassFrame();
+ ScheduleDelayed(1.5 * kMinFrameDelay, [&] {
+ adapter_->UpdateVideoSourceRestrictions(kRestrictedMaxFps);
+ });
+ ScheduleDelayed(2.5 * kMinFrameDelay, [&] {
+ adapter_->OnConstraintsChanged(VideoTrackSourceConstraints{
+ /*min_fps=*/0, /*max_fps=*/2 * TimeDelta::Seconds(1) / kMinFrameDelay});
+ });
+ ScheduleDelayed(3 * kMinFrameDelay, [&] { PassFrame(); });
+ ScheduleDelayed(8 * kMinFrameDelay, [&] {
+ adapter_->OnConstraintsChanged(VideoTrackSourceConstraints{
+ /*min_fps=*/0,
+ /*max_fps=*/0.2 * TimeDelta::Seconds(1) / kMinFrameDelay});
+ });
+ ScheduleDelayed(9 * kMinFrameDelay, [&] { PassFrame(); });
+ ExpectFrameEntriesAtDelaysFromNow({
+ 1 * kMinFrameDelay, // Original frame emitted at non-restricted rate.
+
+ // 1.5 * kMinFrameDelay: restricts max fps to 5 fps which should result
+ // in a new non-idle repeat delay of 2 * kMinFrameDelay.
+ 2 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
+
+ // 2.5 * kMinFrameDelay: new constraint asks for max rate of 20 fps.
+ // The 0Hz adapter is reconstructed for 20 fps but inherits the current
+ // restriction for rate of non-converged frames of 5 fps.
+
+ // A new frame is passed at 3 * kMinFrameDelay. The previous repeat
+ // cadence was stopped by the change in constraints.
+ 3.5 * kMinFrameDelay, // Original frame emitted at non-restricted 20 fps.
+ // The delay is 0.5 * kMinFrameDelay.
+ 5.5 * kMinFrameDelay, // Unconverged repeat at restricted rate.
+ // The delay is 2 * kMinFrameDelay when restricted.
+ 7.5 * kMinFrameDelay, // ...
+
+ // 8 * kMinFrameDelay: new constraint asks for max rate of 2 fps.
+ // The 0Hz adapter is reconstructed for 2 fps and will therefore not obey
+ // the current restriction for rate of non-converged frames of 5 fps
+ // since the new max rate is lower.
+
+ // A new frame is passed at 9 * kMinFrameDelay. The previous repeat
+ // cadence was stopped by the change in constraints.
+ 14 * kMinFrameDelay, // Original frame emitted at non-restricted 2 fps.
+ // The delay is 5 * kMinFrameDelay.
+ 19 * kMinFrameDelay, // Unconverged repeat at non-restricted rate.
+ 24 * kMinFrameDelay, // ...
+ });
+}
+
class FrameCadenceAdapterMetricsTest : public ::testing::Test {
public:
FrameCadenceAdapterMetricsTest() : time_controller_(Timestamp::Millis(1)) {
@@ -869,7 +988,7 @@ TEST(FrameCadenceAdapterRealTimeTest, TimestampsDoNotDrift) {
constexpr int kSleepMs = rtc::kNumMillisecsPerSec / 2;
EXPECT_CALL(callback, OnFrame)
.WillRepeatedly(
- Invoke([&](Timestamp, int, const VideoFrame& incoming_frame) {
+ Invoke([&](Timestamp, bool, const VideoFrame& incoming_frame) {
++frame_counter;
// Avoid the first OnFrame and sleep on the second.
if (frame_counter == 2) {