| /* | |
| * 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 |