blob: fc580350d28372c0903ce88a4a2860d7d639695f [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"
21#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "test/gtest.h"
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000023
24namespace webrtc {
25
Jakob Ivarsson609b0472020-10-19 09:19:34 +020026namespace {
27
28constexpr int kSampleRate = 8000;
29constexpr int kSamplesPerMs = kSampleRate / 1000;
30constexpr int kOutputSizeSamples = kSamplesPerMs * 10;
31constexpr int kMinTimescaleInterval = 5;
32
33NetEqController::NetEqStatus CreateNetEqStatus(NetEq::Mode last_mode,
34 int current_delay_ms) {
35 NetEqController::NetEqStatus status;
36 status.play_dtmf = false;
37 status.last_mode = last_mode;
38 status.target_timestamp = 1234;
39 status.generated_noise_samples = 0;
40 status.expand_mutefactor = 0;
41 status.packet_buffer_info.num_samples = current_delay_ms * kSamplesPerMs;
42 status.packet_buffer_info.span_samples = current_delay_ms * kSamplesPerMs;
43 status.packet_buffer_info.span_samples_no_dtx =
44 current_delay_ms * kSamplesPerMs;
45 status.packet_buffer_info.dtx_or_cng = false;
46 status.next_packet = {status.target_timestamp, false, false};
47 return status;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000048}
49
Jakob Ivarsson609b0472020-10-19 09:19:34 +020050using ::testing::Return;
51
52} // namespace
53
54class DecisionLogicTest : public ::testing::Test {
55 protected:
56 DecisionLogicTest() {
57 test::ScopedFieldTrials field_trial(
58 "WebRTC-Audio-NetEqDecisionLogicSettings/"
59 "estimate_dtx_delay:true,time_stretch_cn:true/");
60
61 NetEqController::Config config;
62 config.tick_timer = &tick_timer_;
63 config.allow_time_stretching = true;
64 std::unique_ptr<Histogram> histogram =
65 std::make_unique<Histogram>(200, 12345, 2);
66 auto delay_manager = std::make_unique<MockDelayManager>(
Jakob Ivarsson7dff9f32020-11-11 15:26:10 +010067 200, 0, 12300, absl::nullopt, 2000, config.tick_timer,
68 std::move(histogram));
Jakob Ivarsson609b0472020-10-19 09:19:34 +020069 mock_delay_manager_ = delay_manager.get();
70 auto buffer_level_filter = std::make_unique<MockBufferLevelFilter>();
71 mock_buffer_level_filter_ = buffer_level_filter.get();
72 decision_logic_ = std::make_unique<DecisionLogic>(
73 config, std::move(delay_manager), std::move(buffer_level_filter));
74 decision_logic_->SetSampleRate(kSampleRate, kOutputSizeSamples);
75 }
76
77 TickTimer tick_timer_;
78 std::unique_ptr<DecisionLogic> decision_logic_;
79 MockDelayManager* mock_delay_manager_;
80 MockBufferLevelFilter* mock_buffer_level_filter_;
81};
82
83TEST_F(DecisionLogicTest, NormalOperation) {
84 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
85 .WillRepeatedly(Return(100));
86 EXPECT_CALL(*mock_buffer_level_filter_, filtered_current_level())
87 .WillRepeatedly(Return(90 * kSamplesPerMs));
88
89 bool reset_decoder = false;
90 tick_timer_.Increment(kMinTimescaleInterval + 1);
91 EXPECT_EQ(decision_logic_->GetDecision(
92 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder),
93 NetEq::Operation::kNormal);
94 EXPECT_FALSE(reset_decoder);
95}
96
97TEST_F(DecisionLogicTest, Accelerate) {
98 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
99 .WillRepeatedly(Return(100));
100 EXPECT_CALL(*mock_buffer_level_filter_, filtered_current_level())
101 .WillRepeatedly(Return(110 * kSamplesPerMs));
102
103 bool reset_decoder = false;
104 tick_timer_.Increment(kMinTimescaleInterval + 1);
105 EXPECT_EQ(decision_logic_->GetDecision(
106 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder),
107 NetEq::Operation::kAccelerate);
108 EXPECT_FALSE(reset_decoder);
109}
110
111TEST_F(DecisionLogicTest, FastAccelerate) {
112 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
113 .WillRepeatedly(Return(100));
114 EXPECT_CALL(*mock_buffer_level_filter_, filtered_current_level())
115 .WillRepeatedly(Return(400 * kSamplesPerMs));
116
117 bool reset_decoder = false;
118 tick_timer_.Increment(kMinTimescaleInterval + 1);
119 EXPECT_EQ(decision_logic_->GetDecision(
120 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder),
121 NetEq::Operation::kFastAccelerate);
122 EXPECT_FALSE(reset_decoder);
123}
124
125TEST_F(DecisionLogicTest, PreemptiveExpand) {
126 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
127 .WillRepeatedly(Return(100));
128 EXPECT_CALL(*mock_buffer_level_filter_, filtered_current_level())
129 .WillRepeatedly(Return(50 * kSamplesPerMs));
130
131 bool reset_decoder = false;
132 tick_timer_.Increment(kMinTimescaleInterval + 1);
133 EXPECT_EQ(decision_logic_->GetDecision(
134 CreateNetEqStatus(NetEq::Mode::kNormal, 100), &reset_decoder),
135 NetEq::Operation::kPreemptiveExpand);
136 EXPECT_FALSE(reset_decoder);
137}
138
139TEST_F(DecisionLogicTest, DecelerationTargetLevelOffset) {
140 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
141 .WillRepeatedly(Return(500));
142 EXPECT_CALL(*mock_buffer_level_filter_, filtered_current_level())
143 .WillRepeatedly(Return(400 * kSamplesPerMs));
144
145 bool reset_decoder = false;
146 tick_timer_.Increment(kMinTimescaleInterval + 1);
147 EXPECT_EQ(decision_logic_->GetDecision(
148 CreateNetEqStatus(NetEq::Mode::kNormal, 400), &reset_decoder),
149 NetEq::Operation::kPreemptiveExpand);
150 EXPECT_FALSE(reset_decoder);
151}
152
153TEST_F(DecisionLogicTest, PostponeDecodeAfterExpand) {
154 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
155 .WillRepeatedly(Return(500));
156
157 // Below 50% target delay threshold.
158 bool reset_decoder = false;
159 EXPECT_EQ(decision_logic_->GetDecision(
160 CreateNetEqStatus(NetEq::Mode::kExpand, 200), &reset_decoder),
161 NetEq::Operation::kExpand);
162 EXPECT_FALSE(reset_decoder);
163
164 // Above 50% target delay threshold.
165 EXPECT_EQ(decision_logic_->GetDecision(
166 CreateNetEqStatus(NetEq::Mode::kExpand, 250), &reset_decoder),
167 NetEq::Operation::kNormal);
168 EXPECT_FALSE(reset_decoder);
169}
170
171TEST_F(DecisionLogicTest, TimeStrechComfortNoise) {
172 EXPECT_CALL(*mock_delay_manager_, TargetDelayMs())
173 .WillRepeatedly(Return(500));
174
175 {
176 bool reset_decoder = false;
177 // Below target window.
178 auto status = CreateNetEqStatus(NetEq::Mode::kCodecInternalCng, 400);
179 status.generated_noise_samples = 400 * kSamplesPerMs;
180 status.next_packet->timestamp =
181 status.target_timestamp + 400 * kSamplesPerMs;
182 EXPECT_EQ(decision_logic_->GetDecision(status, &reset_decoder),
183 NetEq::Operation::kCodecInternalCng);
184 EXPECT_FALSE(reset_decoder);
185 }
186
187 {
188 bool reset_decoder = false;
189 // Above target window.
190 auto status = CreateNetEqStatus(NetEq::Mode::kCodecInternalCng, 600);
191 status.generated_noise_samples = 200 * kSamplesPerMs;
192 status.next_packet->timestamp =
193 status.target_timestamp + 400 * kSamplesPerMs;
194 EXPECT_EQ(decision_logic_->GetDecision(status, &reset_decoder),
195 NetEq::Operation::kNormal);
196 EXPECT_FALSE(reset_decoder);
197
198 // The buffer level filter should be adjusted with the number of samples
199 // that was skipped.
200 int timestamp_leap = status.next_packet->timestamp -
201 status.target_timestamp -
202 status.generated_noise_samples;
203 EXPECT_CALL(*mock_buffer_level_filter_,
204 Update(400 * kSamplesPerMs, timestamp_leap));
205 EXPECT_EQ(decision_logic_->GetDecision(
206 CreateNetEqStatus(NetEq::Mode::kNormal, 400), &reset_decoder),
207 NetEq::Operation::kNormal);
208 EXPECT_FALSE(reset_decoder);
209 }
210}
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000211
212} // namespace webrtc