/* * Copyright (c) 2024 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 "modules/audio_coding/neteq/delay_constraints.h" #include "rtc_base/checks.h" #include "test/gtest.h" namespace webrtc { namespace { constexpr int kMaxNumberOfPackets = 200; constexpr int kFrameSizeMs = 20; constexpr int kMaxBufferSizeMs = kMaxNumberOfPackets * kFrameSizeMs; TEST(DelayConstraintsTest, NoConstraints) { DelayConstraints constraints(kMaxNumberOfPackets, 0); EXPECT_EQ(constraints.Clamp(100), 100); EXPECT_EQ(constraints.Clamp(0), 0); } TEST(DelayConstraintsTest, MaxDelay) { DelayConstraints constraints(kMaxNumberOfPackets, 0); constexpr int kMaxDelayMs = 60; EXPECT_TRUE(constraints.SetMaximumDelay(kMaxDelayMs)); EXPECT_EQ(constraints.Clamp(100), kMaxDelayMs); } TEST(DelayConstraintsTest, MinDelay) { DelayConstraints constraints(kMaxNumberOfPackets, 0); constexpr int kMinDelayMs = 7 * kFrameSizeMs; constraints.SetMinimumDelay(kMinDelayMs); EXPECT_EQ(constraints.Clamp(20), kMinDelayMs); } TEST(DelayConstraintsTest, BaseMinimumDelayCheckValidRange) { DelayConstraints constraints(kMaxNumberOfPackets, 0); // Base minimum delay should be between [0, 10000] milliseconds. EXPECT_FALSE(constraints.SetBaseMinimumDelay(-1)); EXPECT_FALSE(constraints.SetBaseMinimumDelay(10001)); EXPECT_EQ(constraints.GetBaseMinimumDelay(), 0); EXPECT_TRUE(constraints.SetBaseMinimumDelay(7999)); EXPECT_EQ(constraints.GetBaseMinimumDelay(), 7999); } TEST(DelayConstraintsTest, BaseMinimumDelayLowerThanMinimumDelay) { DelayConstraints constraints(kMaxNumberOfPackets, 0); constexpr int kBaseMinimumDelayMs = 100; constexpr int kMinimumDelayMs = 200; // Base minimum delay sets lower bound on minimum. That is why when base // minimum delay is lower than minimum delay we use minimum delay. RTC_DCHECK_LT(kBaseMinimumDelayMs, kMinimumDelayMs); EXPECT_TRUE(constraints.SetBaseMinimumDelay(kBaseMinimumDelayMs)); EXPECT_TRUE(constraints.SetMinimumDelay(kMinimumDelayMs)); EXPECT_EQ(constraints.effective_minimum_delay_ms_for_test(), kMinimumDelayMs); } TEST(DelayConstraintsTest, BaseMinimumDelayGreaterThanMinimumDelay) { DelayConstraints constraints(kMaxNumberOfPackets, 0); constexpr int kBaseMinimumDelayMs = 70; constexpr int kMinimumDelayMs = 30; // Base minimum delay sets lower bound on minimum. That is why when base // minimum delay is greater than minimum delay we use base minimum delay. RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs); EXPECT_TRUE(constraints.SetBaseMinimumDelay(kBaseMinimumDelayMs)); EXPECT_TRUE(constraints.SetMinimumDelay(kMinimumDelayMs)); EXPECT_EQ(constraints.effective_minimum_delay_ms_for_test(), kBaseMinimumDelayMs); } TEST(DelayConstraintsTest, BaseMinimumDelayGreaterThanBufferSize) { DelayConstraints constraints(kMaxNumberOfPackets, 0); constexpr int kBaseMinimumDelayMs = kMaxBufferSizeMs + 1; constexpr int kMinimumDelayMs = 12; constexpr int kMaximumDelayMs = 20; constexpr int kMaxBufferSizeMsQ75 = 3 * kMaxBufferSizeMs / 4; EXPECT_TRUE(constraints.SetPacketAudioLength(kFrameSizeMs)); EXPECT_TRUE(constraints.SetMaximumDelay(kMaximumDelayMs)); // Base minimum delay is greater than minimum delay, that is why we clamp // it to current the highest possible value which is maximum delay. RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs); RTC_DCHECK_GT(kBaseMinimumDelayMs, kMaxBufferSizeMs); RTC_DCHECK_GT(kBaseMinimumDelayMs, kMaximumDelayMs); RTC_DCHECK_LT(kMaximumDelayMs, kMaxBufferSizeMsQ75); EXPECT_TRUE(constraints.SetMinimumDelay(kMinimumDelayMs)); EXPECT_TRUE(constraints.SetBaseMinimumDelay(kBaseMinimumDelayMs)); // Unset maximum value. EXPECT_TRUE(constraints.SetMaximumDelay(0)); // With maximum value unset, the highest possible value now is 75% of // currently possible maximum buffer size. EXPECT_EQ(constraints.effective_minimum_delay_ms_for_test(), kMaxBufferSizeMsQ75); } TEST(DelayConstraintsTest, BaseMinimumDelayGreaterThanMaximumDelay) { DelayConstraints constraints(kMaxNumberOfPackets, 0); constexpr int kMaximumDelayMs = 400; constexpr int kBaseMinimumDelayMs = kMaximumDelayMs + 1; constexpr int kMinimumDelayMs = 20; // Base minimum delay is greater than minimum delay, that is why we clamp // it to current the highest possible value which is kMaximumDelayMs. RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs); RTC_DCHECK_GT(kBaseMinimumDelayMs, kMaximumDelayMs); RTC_DCHECK_LT(kMaximumDelayMs, kMaxBufferSizeMs); EXPECT_TRUE(constraints.SetMaximumDelay(kMaximumDelayMs)); EXPECT_TRUE(constraints.SetMinimumDelay(kMinimumDelayMs)); EXPECT_TRUE(constraints.SetBaseMinimumDelay(kBaseMinimumDelayMs)); EXPECT_EQ(constraints.effective_minimum_delay_ms_for_test(), kMaximumDelayMs); } TEST(DelayConstraintsTest, BaseMinimumDelayLowerThanMaxSize) { DelayConstraints constraints(kMaxNumberOfPackets, 0); constexpr int kMaximumDelayMs = 400; constexpr int kBaseMinimumDelayMs = kMaximumDelayMs - 1; constexpr int kMinimumDelayMs = 20; // Base minimum delay is greater than minimum delay, and lower than maximum // delays that is why it is used. RTC_DCHECK_GT(kBaseMinimumDelayMs, kMinimumDelayMs); RTC_DCHECK_LT(kBaseMinimumDelayMs, kMaximumDelayMs); EXPECT_TRUE(constraints.SetMaximumDelay(kMaximumDelayMs)); EXPECT_TRUE(constraints.SetMinimumDelay(kMinimumDelayMs)); EXPECT_TRUE(constraints.SetBaseMinimumDelay(kBaseMinimumDelayMs)); EXPECT_EQ(constraints.effective_minimum_delay_ms_for_test(), kBaseMinimumDelayMs); } TEST(DelayConstraintsTest, MinimumDelayMemorization) { DelayConstraints constraints(kMaxNumberOfPackets, 0); // Check that when we increase base minimum delay to value higher than // minimum delay then minimum delay is still memorized. This allows to // restore effective minimum delay to memorized minimum delay value when we // decrease base minimum delay. constexpr int kBaseMinimumDelayMsLow = 10; constexpr int kMinimumDelayMs = 20; constexpr int kBaseMinimumDelayMsHigh = 30; EXPECT_TRUE(constraints.SetBaseMinimumDelay(kBaseMinimumDelayMsLow)); EXPECT_TRUE(constraints.SetMinimumDelay(kMinimumDelayMs)); // Minimum delay is used as it is higher than base minimum delay. EXPECT_EQ(constraints.effective_minimum_delay_ms_for_test(), kMinimumDelayMs); EXPECT_TRUE(constraints.SetBaseMinimumDelay(kBaseMinimumDelayMsHigh)); // Base minimum delay is used as it is now higher than minimum delay. EXPECT_EQ(constraints.effective_minimum_delay_ms_for_test(), kBaseMinimumDelayMsHigh); EXPECT_TRUE(constraints.SetBaseMinimumDelay(kBaseMinimumDelayMsLow)); // Check that minimum delay is memorized and is used again. EXPECT_EQ(constraints.effective_minimum_delay_ms_for_test(), kMinimumDelayMs); } TEST(DelayConstraintsTest, BaseMinimumDelay) { DelayConstraints constraints(kMaxNumberOfPackets, 0); constexpr int kBaseMinimumDelayMs = 7 * kFrameSizeMs; EXPECT_TRUE(constraints.SetBaseMinimumDelay(kBaseMinimumDelayMs)); EXPECT_EQ(constraints.GetBaseMinimumDelay(), kBaseMinimumDelayMs); EXPECT_EQ(constraints.Clamp(20), kBaseMinimumDelayMs); } TEST(DelayConstraintsTest, Failures) { DelayConstraints constraints(kMaxNumberOfPackets, 0); // Wrong packet size. EXPECT_FALSE(constraints.SetPacketAudioLength(0)); EXPECT_FALSE(constraints.SetPacketAudioLength(-1)); // Minimum delay higher than a maximum delay is not accepted. EXPECT_TRUE(constraints.SetMaximumDelay(20)); EXPECT_FALSE(constraints.SetMinimumDelay(40)); // Maximum delay less than minimum delay is not accepted. EXPECT_TRUE(constraints.SetMaximumDelay(100)); EXPECT_TRUE(constraints.SetMinimumDelay(80)); EXPECT_FALSE(constraints.SetMaximumDelay(60)); } } // namespace } // namespace webrtc