blob: d70e3070f330ed1e1365015727b1e8dc10c0c3e4 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020013#include "modules/audio_coding/neteq/decision_logic.h"
Jonas Olssona4d87372019-07-05 19:08:33 +020014
Ivo Creusen3ce44a32019-10-31 14:38:11 +010015#include "api/neteq/neteq_controller.h"
16#include "api/neteq/tick_timer.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "modules/audio_coding/neteq/buffer_level_filter.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "modules/audio_coding/neteq/delay_manager.h"
Jakob Ivarsson609b0472020-10-19 09:19:34 +020019#include "modules/audio_coding/neteq/mock/mock_buffer_level_filter.h"
20#include "modules/audio_coding/neteq/mock/mock_delay_manager.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "test/gtest.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000022
23namespace webrtc {
24
Jakob Ivarsson609b0472020-10-19 09:19:34 +020025namespace {
26
27constexpr int kSampleRate = 8000;
28constexpr int kSamplesPerMs = kSampleRate / 1000;
29constexpr int kOutputSizeSamples = kSamplesPerMs * 10;
30constexpr int kMinTimescaleInterval = 5;
31
32NetEqController::NetEqStatus CreateNetEqStatus(NetEq::Mode last_mode,
33 int current_delay_ms) {
34 NetEqController::NetEqStatus status;
35 status.play_dtmf = false;
36 status.last_mode = last_mode;
37 status.target_timestamp = 1234;
38 status.generated_noise_samples = 0;
39 status.expand_mutefactor = 0;
40 status.packet_buffer_info.num_samples = current_delay_ms * kSamplesPerMs;
41 status.packet_buffer_info.span_samples = current_delay_ms * kSamplesPerMs;
42 status.packet_buffer_info.span_samples_no_dtx =
43 current_delay_ms * kSamplesPerMs;
44 status.packet_buffer_info.dtx_or_cng = false;
45 status.next_packet = {status.target_timestamp, false, false};
46 return status;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000047}
48
Jakob Ivarsson609b0472020-10-19 09:19:34 +020049using ::testing::Return;
50
51} // namespace
52
53class DecisionLogicTest : public ::testing::Test {
54 protected:
55 DecisionLogicTest() {
Jakob Ivarsson609b0472020-10-19 09:19:34 +020056 NetEqController::Config config;
57 config.tick_timer = &tick_timer_;
58 config.allow_time_stretching = true;
Jakob Ivarsson609b0472020-10-19 09:19:34 +020059 auto delay_manager = std::make_unique<MockDelayManager>(
Jakob Ivarsson74158ff2021-09-07 14:24:56 +020060 DelayManager::Config(), config.tick_timer);
Jakob Ivarsson609b0472020-10-19 09:19:34 +020061 mock_delay_manager_ = delay_manager.get();
62 auto buffer_level_filter = std::make_unique<MockBufferLevelFilter>();
63 mock_buffer_level_filter_ = buffer_level_filter.get();
64 decision_logic_ = std::make_unique<DecisionLogic>(
65 config, std::move(delay_manager), std::move(buffer_level_filter));
66 decision_logic_->SetSampleRate(kSampleRate, kOutputSizeSamples);
67 }
68
69 TickTimer tick_timer_;
70 std::unique_ptr<DecisionLogic> decision_logic_;
71 MockDelayManager* mock_delay_manager_;
72 MockBufferLevelFilter* mock_buffer_level_filter_;
73};
74
75TEST_F(DecisionLogicTest, NormalOperation) {
76 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
77 .WillRepeatedly(Return(100));
78 EXPECT_CALL(*mock_buffer_level_filter_, filtered_current_level())
79 .WillRepeatedly(Return(90 * kSamplesPerMs));
80
81 bool reset_decoder = false;
82 tick_timer_.Increment(kMinTimescaleInterval + 1);
83 EXPECT_EQ(decision_logic_->GetDecision(
84 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder),
85 NetEq::Operation::kNormal);
86 EXPECT_FALSE(reset_decoder);
87}
88
89TEST_F(DecisionLogicTest, Accelerate) {
90 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
91 .WillRepeatedly(Return(100));
92 EXPECT_CALL(*mock_buffer_level_filter_, filtered_current_level())
93 .WillRepeatedly(Return(110 * kSamplesPerMs));
94
95 bool reset_decoder = false;
96 tick_timer_.Increment(kMinTimescaleInterval + 1);
97 EXPECT_EQ(decision_logic_->GetDecision(
98 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder),
99 NetEq::Operation::kAccelerate);
100 EXPECT_FALSE(reset_decoder);
101}
102
103TEST_F(DecisionLogicTest, FastAccelerate) {
104 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
105 .WillRepeatedly(Return(100));
106 EXPECT_CALL(*mock_buffer_level_filter_, filtered_current_level())
107 .WillRepeatedly(Return(400 * kSamplesPerMs));
108
109 bool reset_decoder = false;
110 tick_timer_.Increment(kMinTimescaleInterval + 1);
111 EXPECT_EQ(decision_logic_->GetDecision(
112 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder),
113 NetEq::Operation::kFastAccelerate);
114 EXPECT_FALSE(reset_decoder);
115}
116
117TEST_F(DecisionLogicTest, PreemptiveExpand) {
118 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
119 .WillRepeatedly(Return(100));
120 EXPECT_CALL(*mock_buffer_level_filter_, filtered_current_level())
121 .WillRepeatedly(Return(50 * kSamplesPerMs));
122
123 bool reset_decoder = false;
124 tick_timer_.Increment(kMinTimescaleInterval + 1);
125 EXPECT_EQ(decision_logic_->GetDecision(
126 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder),
127 NetEq::Operation::kPreemptiveExpand);
128 EXPECT_FALSE(reset_decoder);
129}
130
131TEST_F(DecisionLogicTest, DecelerationTargetLevelOffset) {
132 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
133 .WillRepeatedly(Return(500));
134 EXPECT_CALL(*mock_buffer_level_filter_, filtered_current_level())
135 .WillRepeatedly(Return(400 * kSamplesPerMs));
136
137 bool reset_decoder = false;
138 tick_timer_.Increment(kMinTimescaleInterval + 1);
139 EXPECT_EQ(decision_logic_->GetDecision(
140 CreateNetEqStatus(NetEq::Mode::kNormal, 400), &reset_decoder),
141 NetEq::Operation::kPreemptiveExpand);
142 EXPECT_FALSE(reset_decoder);
143}
144
145TEST_F(DecisionLogicTest, PostponeDecodeAfterExpand) {
146 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
147 .WillRepeatedly(Return(500));
148
149 // Below 50% target delay threshold.
150 bool reset_decoder = false;
151 EXPECT_EQ(decision_logic_->GetDecision(
152 CreateNetEqStatus(NetEq::Mode::kExpand, 200), &reset_decoder),
153 NetEq::Operation::kExpand);
154 EXPECT_FALSE(reset_decoder);
155
156 // Above 50% target delay threshold.
157 EXPECT_EQ(decision_logic_->GetDecision(
158 CreateNetEqStatus(NetEq::Mode::kExpand, 250), &reset_decoder),
159 NetEq::Operation::kNormal);
160 EXPECT_FALSE(reset_decoder);
161}
162
163TEST_F(DecisionLogicTest, TimeStrechComfortNoise) {
164 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
165 .WillRepeatedly(Return(500));
166
167 {
168 bool reset_decoder = false;
169 // Below target window.
170 auto status = CreateNetEqStatus(NetEq::Mode::kCodecInternalCng, 400);
171 status.generated_noise_samples = 400 * kSamplesPerMs;
172 status.next_packet->timestamp =
173 status.target_timestamp + 400 * kSamplesPerMs;
174 EXPECT_EQ(decision_logic_->GetDecision(status, &reset_decoder),
175 NetEq::Operation::kCodecInternalCng);
176 EXPECT_FALSE(reset_decoder);
177 }
178
179 {
180 bool reset_decoder = false;
181 // Above target window.
182 auto status = CreateNetEqStatus(NetEq::Mode::kCodecInternalCng, 600);
183 status.generated_noise_samples = 200 * kSamplesPerMs;
184 status.next_packet->timestamp =
185 status.target_timestamp + 400 * kSamplesPerMs;
186 EXPECT_EQ(decision_logic_->GetDecision(status, &reset_decoder),
187 NetEq::Operation::kNormal);
188 EXPECT_FALSE(reset_decoder);
189
190 // The buffer level filter should be adjusted with the number of samples
191 // that was skipped.
192 int timestamp_leap = status.next_packet->timestamp -
193 status.target_timestamp -
194 status.generated_noise_samples;
195 EXPECT_CALL(*mock_buffer_level_filter_,
196 Update(400 * kSamplesPerMs, timestamp_leap));
197 EXPECT_EQ(decision_logic_->GetDecision(
198 CreateNetEqStatus(NetEq::Mode::kNormal, 400), &reset_decoder),
199 NetEq::Operation::kNormal);
200 EXPECT_FALSE(reset_decoder);
201 }
202}
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000203
204} // namespace webrtc