decision_logic_unittest.cc (7986B)
1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 // Unit tests for DecisionLogic class and derived classes. 12 13 #include "modules/audio_coding/neteq/decision_logic.h" 14 15 #include <memory> 16 #include <optional> 17 #include <utility> 18 19 #include "api/neteq/neteq.h" 20 #include "api/neteq/neteq_controller.h" 21 #include "api/neteq/tick_timer.h" 22 #include "modules/audio_coding/neteq/delay_manager.h" 23 #include "modules/audio_coding/neteq/mock/mock_buffer_level_filter.h" 24 #include "modules/audio_coding/neteq/mock/mock_delay_manager.h" 25 #include "modules/audio_coding/neteq/mock/mock_packet_arrival_history.h" 26 #include "test/create_test_field_trials.h" 27 #include "test/gmock.h" 28 #include "test/gtest.h" 29 30 namespace webrtc { 31 32 namespace { 33 34 using ::testing::_; 35 using ::testing::Return; 36 37 constexpr int kSampleRate = 8000; 38 constexpr int kSamplesPerMs = kSampleRate / 1000; 39 constexpr int kOutputSizeSamples = kSamplesPerMs * 10; 40 constexpr int kMinTimescaleInterval = 5; 41 42 NetEqController::NetEqStatus CreateNetEqStatus(NetEq::Mode last_mode, 43 int current_delay_ms) { 44 NetEqController::NetEqStatus status; 45 status.play_dtmf = false; 46 status.last_mode = last_mode; 47 status.target_timestamp = 1234; 48 status.generated_noise_samples = 0; 49 status.expand_mutefactor = 0; 50 status.packet_buffer_info.num_samples = current_delay_ms * kSamplesPerMs; 51 status.packet_buffer_info.span_samples = current_delay_ms * kSamplesPerMs; 52 status.packet_buffer_info.span_samples_wait_time = 53 current_delay_ms * kSamplesPerMs; 54 status.packet_buffer_info.dtx_or_cng = false; 55 status.next_packet = { 56 .timestamp = status.target_timestamp, .is_dtx = false, .is_cng = false}; 57 status.sync_buffer_samples = 0; 58 return status; 59 } 60 61 } // namespace 62 63 class DecisionLogicTest : public ::testing::Test { 64 protected: 65 DecisionLogicTest() { 66 NetEqController::Config config; 67 config.tick_timer = &tick_timer_; 68 config.allow_time_stretching = true; 69 config.max_packets_in_buffer = 200; 70 config.base_min_delay_ms = 0; 71 auto delay_manager = std::make_unique<MockDelayManager>( 72 DelayManager::Config(CreateTestFieldTrials()), config.tick_timer); 73 mock_delay_manager_ = delay_manager.get(); 74 auto buffer_level_filter = std::make_unique<MockBufferLevelFilter>(); 75 mock_buffer_level_filter_ = buffer_level_filter.get(); 76 auto packet_arrival_history = 77 std::make_unique<MockPacketArrivalHistory>(&tick_timer_); 78 mock_packet_arrival_history_ = packet_arrival_history.get(); 79 decision_logic_ = std::make_unique<DecisionLogic>( 80 config, std::move(delay_manager), std::move(buffer_level_filter), 81 std::move(packet_arrival_history)); 82 decision_logic_->SetSampleRate(kSampleRate, kOutputSizeSamples); 83 } 84 85 TickTimer tick_timer_; 86 std::unique_ptr<DecisionLogic> decision_logic_; 87 MockDelayManager* mock_delay_manager_; 88 MockBufferLevelFilter* mock_buffer_level_filter_; 89 MockPacketArrivalHistory* mock_packet_arrival_history_; 90 }; 91 92 TEST_F(DecisionLogicTest, NormalOperation) { 93 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs()) 94 .WillRepeatedly(Return(100)); 95 EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_)) 96 .WillRepeatedly(Return(100)); 97 EXPECT_CALL(*mock_packet_arrival_history_, GetMaxDelayMs()) 98 .WillRepeatedly(Return(0)); 99 100 bool reset_decoder = false; 101 tick_timer_.Increment(kMinTimescaleInterval + 1); 102 EXPECT_EQ(decision_logic_->GetDecision( 103 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder), 104 NetEq::Operation::kNormal); 105 EXPECT_FALSE(reset_decoder); 106 } 107 108 TEST_F(DecisionLogicTest, Accelerate) { 109 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs()) 110 .WillRepeatedly(Return(100)); 111 EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_)) 112 .WillRepeatedly(Return(150)); 113 EXPECT_CALL(*mock_packet_arrival_history_, GetMaxDelayMs()) 114 .WillRepeatedly(Return(0)); 115 116 bool reset_decoder = false; 117 tick_timer_.Increment(kMinTimescaleInterval + 1); 118 EXPECT_EQ(decision_logic_->GetDecision( 119 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder), 120 NetEq::Operation::kAccelerate); 121 EXPECT_FALSE(reset_decoder); 122 } 123 124 TEST_F(DecisionLogicTest, FastAccelerate) { 125 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs()) 126 .WillRepeatedly(Return(100)); 127 EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_)) 128 .WillRepeatedly(Return(500)); 129 EXPECT_CALL(*mock_packet_arrival_history_, GetMaxDelayMs()) 130 .WillRepeatedly(Return(0)); 131 132 bool reset_decoder = false; 133 tick_timer_.Increment(kMinTimescaleInterval + 1); 134 EXPECT_EQ(decision_logic_->GetDecision( 135 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder), 136 NetEq::Operation::kFastAccelerate); 137 EXPECT_FALSE(reset_decoder); 138 } 139 140 TEST_F(DecisionLogicTest, PreemptiveExpand) { 141 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs()) 142 .WillRepeatedly(Return(100)); 143 EXPECT_CALL(*mock_packet_arrival_history_, GetDelayMs(_)) 144 .WillRepeatedly(Return(50)); 145 EXPECT_CALL(*mock_packet_arrival_history_, GetMaxDelayMs()) 146 .WillRepeatedly(Return(0)); 147 148 bool reset_decoder = false; 149 tick_timer_.Increment(kMinTimescaleInterval + 1); 150 EXPECT_EQ(decision_logic_->GetDecision( 151 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder), 152 NetEq::Operation::kPreemptiveExpand); 153 EXPECT_FALSE(reset_decoder); 154 } 155 156 TEST_F(DecisionLogicTest, PostponeDecodeAfterExpand) { 157 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs()) 158 .WillRepeatedly(Return(500)); 159 160 // Below 50% target delay threshold. 161 bool reset_decoder = false; 162 EXPECT_EQ(decision_logic_->GetDecision( 163 CreateNetEqStatus(NetEq::Mode::kExpand, 200), &reset_decoder), 164 NetEq::Operation::kExpand); 165 EXPECT_FALSE(reset_decoder); 166 167 // Above 50% target delay threshold. 168 EXPECT_EQ(decision_logic_->GetDecision( 169 CreateNetEqStatus(NetEq::Mode::kExpand, 250), &reset_decoder), 170 NetEq::Operation::kNormal); 171 EXPECT_FALSE(reset_decoder); 172 } 173 174 TEST_F(DecisionLogicTest, TimeStrechComfortNoise) { 175 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs()) 176 .WillRepeatedly(Return(500)); 177 178 { 179 bool reset_decoder = false; 180 // Below target window. 181 auto status = CreateNetEqStatus(NetEq::Mode::kCodecInternalCng, 200); 182 status.generated_noise_samples = 400 * kSamplesPerMs; 183 status.next_packet->timestamp = 184 status.target_timestamp + 400 * kSamplesPerMs; 185 EXPECT_EQ(decision_logic_->GetDecision(status, &reset_decoder), 186 NetEq::Operation::kCodecInternalCng); 187 EXPECT_FALSE(reset_decoder); 188 } 189 190 { 191 bool reset_decoder = false; 192 // Above target window. 193 auto status = CreateNetEqStatus(NetEq::Mode::kCodecInternalCng, 600); 194 status.generated_noise_samples = 200 * kSamplesPerMs; 195 status.next_packet->timestamp = 196 status.target_timestamp + 400 * kSamplesPerMs; 197 EXPECT_EQ(decision_logic_->GetDecision(status, &reset_decoder), 198 NetEq::Operation::kNormal); 199 EXPECT_FALSE(reset_decoder); 200 } 201 } 202 203 TEST_F(DecisionLogicTest, CngTimeout) { 204 auto status = CreateNetEqStatus(NetEq::Mode::kCodecInternalCng, 0); 205 status.next_packet = std::nullopt; 206 status.generated_noise_samples = kSamplesPerMs * 500; 207 bool reset_decoder = false; 208 EXPECT_EQ(decision_logic_->GetDecision(status, &reset_decoder), 209 NetEq::Operation::kCodecInternalCng); 210 status.generated_noise_samples = kSamplesPerMs * 1010; 211 EXPECT_EQ(decision_logic_->GetDecision(status, &reset_decoder), 212 NetEq::Operation::kExpand); 213 } 214 215 } // namespace webrtc