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