1 /*
2 * Copyright (c) 2016 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 #include "modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
12
13 #include <utility>
14 #include <vector>
15
16 #include "api/rtc_event_log/rtc_event.h"
17 #include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
18 #include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
19 #include "modules/audio_coding/audio_network_adaptor/mock/mock_controller.h"
20 #include "modules/audio_coding/audio_network_adaptor/mock/mock_controller_manager.h"
21 #include "modules/audio_coding/audio_network_adaptor/mock/mock_debug_dump_writer.h"
22 #include "rtc_base/fake_clock.h"
23 #include "test/field_trial.h"
24 #include "test/gtest.h"
25
26 namespace webrtc {
27
28 using ::testing::_;
29 using ::testing::NiceMock;
30 using ::testing::Return;
31 using ::testing::SetArgPointee;
32
33 namespace {
34
35 constexpr size_t kNumControllers = 2;
36
37 constexpr int64_t kClockInitialTimeMs = 12345678;
38
39 MATCHER_P(NetworkMetricsIs, metric, "") {
40 return arg.uplink_bandwidth_bps == metric.uplink_bandwidth_bps &&
41 arg.target_audio_bitrate_bps == metric.target_audio_bitrate_bps &&
42 arg.rtt_ms == metric.rtt_ms &&
43 arg.overhead_bytes_per_packet == metric.overhead_bytes_per_packet &&
44 arg.uplink_packet_loss_fraction == metric.uplink_packet_loss_fraction;
45 }
46
47 MATCHER_P(IsRtcEventAnaConfigEqualTo, config, "") {
48 if (arg->GetType() != RtcEvent::Type::AudioNetworkAdaptation) {
49 return false;
50 }
51 auto ana_event = static_cast<RtcEventAudioNetworkAdaptation*>(arg);
52 return ana_event->config() == config;
53 }
54
55 MATCHER_P(EncoderRuntimeConfigIs, config, "") {
56 return arg.bitrate_bps == config.bitrate_bps &&
57 arg.frame_length_ms == config.frame_length_ms &&
58 arg.uplink_packet_loss_fraction ==
59 config.uplink_packet_loss_fraction &&
60 arg.enable_fec == config.enable_fec &&
61 arg.enable_dtx == config.enable_dtx &&
62 arg.num_channels == config.num_channels;
63 }
64
65 struct AudioNetworkAdaptorStates {
66 std::unique_ptr<AudioNetworkAdaptorImpl> audio_network_adaptor;
67 std::vector<std::unique_ptr<MockController>> mock_controllers;
68 std::unique_ptr<MockRtcEventLog> event_log;
69 MockDebugDumpWriter* mock_debug_dump_writer;
70 };
71
CreateAudioNetworkAdaptor()72 AudioNetworkAdaptorStates CreateAudioNetworkAdaptor() {
73 AudioNetworkAdaptorStates states;
74 std::vector<Controller*> controllers;
75 for (size_t i = 0; i < kNumControllers; ++i) {
76 auto controller =
77 std::unique_ptr<MockController>(new NiceMock<MockController>());
78 EXPECT_CALL(*controller, Die());
79 controllers.push_back(controller.get());
80 states.mock_controllers.push_back(std::move(controller));
81 }
82
83 auto controller_manager = std::unique_ptr<MockControllerManager>(
84 new NiceMock<MockControllerManager>());
85
86 EXPECT_CALL(*controller_manager, Die());
87 EXPECT_CALL(*controller_manager, GetControllers())
88 .WillRepeatedly(Return(controllers));
89 EXPECT_CALL(*controller_manager, GetSortedControllers(_))
90 .WillRepeatedly(Return(controllers));
91
92 states.event_log.reset(new NiceMock<MockRtcEventLog>());
93
94 auto debug_dump_writer =
95 std::unique_ptr<MockDebugDumpWriter>(new NiceMock<MockDebugDumpWriter>());
96 EXPECT_CALL(*debug_dump_writer, Die());
97 states.mock_debug_dump_writer = debug_dump_writer.get();
98
99 AudioNetworkAdaptorImpl::Config config;
100 config.event_log = states.event_log.get();
101 // AudioNetworkAdaptorImpl governs the lifetime of controller manager.
102 states.audio_network_adaptor.reset(new AudioNetworkAdaptorImpl(
103 config, std::move(controller_manager), std::move(debug_dump_writer)));
104
105 return states;
106 }
107
SetExpectCallToUpdateNetworkMetrics(const std::vector<std::unique_ptr<MockController>> & controllers,const Controller::NetworkMetrics & check)108 void SetExpectCallToUpdateNetworkMetrics(
109 const std::vector<std::unique_ptr<MockController>>& controllers,
110 const Controller::NetworkMetrics& check) {
111 for (auto& mock_controller : controllers) {
112 EXPECT_CALL(*mock_controller,
113 UpdateNetworkMetrics(NetworkMetricsIs(check)));
114 }
115 }
116
117 } // namespace
118
TEST(AudioNetworkAdaptorImplTest,UpdateNetworkMetricsIsCalledOnSetUplinkBandwidth)119 TEST(AudioNetworkAdaptorImplTest,
120 UpdateNetworkMetricsIsCalledOnSetUplinkBandwidth) {
121 auto states = CreateAudioNetworkAdaptor();
122 constexpr int kBandwidth = 16000;
123 Controller::NetworkMetrics check;
124 check.uplink_bandwidth_bps = kBandwidth;
125 SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
126 states.audio_network_adaptor->SetUplinkBandwidth(kBandwidth);
127 }
128
TEST(AudioNetworkAdaptorImplTest,UpdateNetworkMetricsIsCalledOnSetUplinkPacketLossFraction)129 TEST(AudioNetworkAdaptorImplTest,
130 UpdateNetworkMetricsIsCalledOnSetUplinkPacketLossFraction) {
131 auto states = CreateAudioNetworkAdaptor();
132 constexpr float kPacketLoss = 0.7f;
133 Controller::NetworkMetrics check;
134 check.uplink_packet_loss_fraction = kPacketLoss;
135 SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
136 states.audio_network_adaptor->SetUplinkPacketLossFraction(kPacketLoss);
137 }
138
TEST(AudioNetworkAdaptorImplTest,UpdateNetworkMetricsIsCalledOnSetRtt)139 TEST(AudioNetworkAdaptorImplTest, UpdateNetworkMetricsIsCalledOnSetRtt) {
140 auto states = CreateAudioNetworkAdaptor();
141 constexpr int kRtt = 100;
142 Controller::NetworkMetrics check;
143 check.rtt_ms = kRtt;
144 SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
145 states.audio_network_adaptor->SetRtt(kRtt);
146 }
147
TEST(AudioNetworkAdaptorImplTest,UpdateNetworkMetricsIsCalledOnSetTargetAudioBitrate)148 TEST(AudioNetworkAdaptorImplTest,
149 UpdateNetworkMetricsIsCalledOnSetTargetAudioBitrate) {
150 auto states = CreateAudioNetworkAdaptor();
151 constexpr int kTargetAudioBitrate = 15000;
152 Controller::NetworkMetrics check;
153 check.target_audio_bitrate_bps = kTargetAudioBitrate;
154 SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
155 states.audio_network_adaptor->SetTargetAudioBitrate(kTargetAudioBitrate);
156 }
157
TEST(AudioNetworkAdaptorImplTest,UpdateNetworkMetricsIsCalledOnSetOverhead)158 TEST(AudioNetworkAdaptorImplTest, UpdateNetworkMetricsIsCalledOnSetOverhead) {
159 auto states = CreateAudioNetworkAdaptor();
160 constexpr size_t kOverhead = 64;
161 Controller::NetworkMetrics check;
162 check.overhead_bytes_per_packet = kOverhead;
163 SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
164 states.audio_network_adaptor->SetOverhead(kOverhead);
165 }
166
TEST(AudioNetworkAdaptorImplTest,MakeDecisionIsCalledOnGetEncoderRuntimeConfig)167 TEST(AudioNetworkAdaptorImplTest,
168 MakeDecisionIsCalledOnGetEncoderRuntimeConfig) {
169 auto states = CreateAudioNetworkAdaptor();
170 for (auto& mock_controller : states.mock_controllers)
171 EXPECT_CALL(*mock_controller, MakeDecision(_));
172 states.audio_network_adaptor->GetEncoderRuntimeConfig();
173 }
174
TEST(AudioNetworkAdaptorImplTest,DumpEncoderRuntimeConfigIsCalledOnGetEncoderRuntimeConfig)175 TEST(AudioNetworkAdaptorImplTest,
176 DumpEncoderRuntimeConfigIsCalledOnGetEncoderRuntimeConfig) {
177 test::ScopedFieldTrials override_field_trials(
178 "WebRTC-Audio-BitrateAdaptation/Enabled/WebRTC-Audio-FecAdaptation/"
179 "Enabled/");
180 rtc::ScopedFakeClock fake_clock;
181 fake_clock.AdvanceTime(TimeDelta::Millis(kClockInitialTimeMs));
182 auto states = CreateAudioNetworkAdaptor();
183 AudioEncoderRuntimeConfig config;
184 config.bitrate_bps = 32000;
185 config.enable_fec = true;
186
187 EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
188 .WillOnce(SetArgPointee<0>(config));
189
190 EXPECT_CALL(*states.mock_debug_dump_writer,
191 DumpEncoderRuntimeConfig(EncoderRuntimeConfigIs(config),
192 kClockInitialTimeMs));
193 states.audio_network_adaptor->GetEncoderRuntimeConfig();
194 }
195
TEST(AudioNetworkAdaptorImplTest,DumpNetworkMetricsIsCalledOnSetNetworkMetrics)196 TEST(AudioNetworkAdaptorImplTest,
197 DumpNetworkMetricsIsCalledOnSetNetworkMetrics) {
198 rtc::ScopedFakeClock fake_clock;
199 fake_clock.AdvanceTime(TimeDelta::Millis(kClockInitialTimeMs));
200
201 auto states = CreateAudioNetworkAdaptor();
202
203 constexpr int kBandwidth = 16000;
204 constexpr float kPacketLoss = 0.7f;
205 constexpr int kRtt = 100;
206 constexpr int kTargetAudioBitrate = 15000;
207 constexpr size_t kOverhead = 64;
208
209 Controller::NetworkMetrics check;
210 check.uplink_bandwidth_bps = kBandwidth;
211 int64_t timestamp_check = kClockInitialTimeMs;
212
213 EXPECT_CALL(*states.mock_debug_dump_writer,
214 DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
215 states.audio_network_adaptor->SetUplinkBandwidth(kBandwidth);
216
217 fake_clock.AdvanceTime(TimeDelta::Millis(100));
218 timestamp_check += 100;
219 check.uplink_packet_loss_fraction = kPacketLoss;
220 EXPECT_CALL(*states.mock_debug_dump_writer,
221 DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
222 states.audio_network_adaptor->SetUplinkPacketLossFraction(kPacketLoss);
223
224 fake_clock.AdvanceTime(TimeDelta::Millis(50));
225 timestamp_check += 50;
226
227 fake_clock.AdvanceTime(TimeDelta::Millis(200));
228 timestamp_check += 200;
229 check.rtt_ms = kRtt;
230 EXPECT_CALL(*states.mock_debug_dump_writer,
231 DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
232 states.audio_network_adaptor->SetRtt(kRtt);
233
234 fake_clock.AdvanceTime(TimeDelta::Millis(150));
235 timestamp_check += 150;
236 check.target_audio_bitrate_bps = kTargetAudioBitrate;
237 EXPECT_CALL(*states.mock_debug_dump_writer,
238 DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
239 states.audio_network_adaptor->SetTargetAudioBitrate(kTargetAudioBitrate);
240
241 fake_clock.AdvanceTime(TimeDelta::Millis(50));
242 timestamp_check += 50;
243 check.overhead_bytes_per_packet = kOverhead;
244 EXPECT_CALL(*states.mock_debug_dump_writer,
245 DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
246 states.audio_network_adaptor->SetOverhead(kOverhead);
247 }
248
TEST(AudioNetworkAdaptorImplTest,LogRuntimeConfigOnGetEncoderRuntimeConfig)249 TEST(AudioNetworkAdaptorImplTest, LogRuntimeConfigOnGetEncoderRuntimeConfig) {
250 test::ScopedFieldTrials override_field_trials(
251 "WebRTC-Audio-BitrateAdaptation/Enabled/WebRTC-Audio-FecAdaptation/"
252 "Enabled/");
253 auto states = CreateAudioNetworkAdaptor();
254
255 AudioEncoderRuntimeConfig config;
256 config.bitrate_bps = 32000;
257 config.enable_fec = true;
258
259 EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
260 .WillOnce(SetArgPointee<0>(config));
261
262 EXPECT_CALL(*states.event_log, LogProxy(IsRtcEventAnaConfigEqualTo(config)))
263 .Times(1);
264 states.audio_network_adaptor->GetEncoderRuntimeConfig();
265 }
266
TEST(AudioNetworkAdaptorImplTest,TestANAStats)267 TEST(AudioNetworkAdaptorImplTest, TestANAStats) {
268 auto states = CreateAudioNetworkAdaptor();
269
270 // Simulate some adaptation, otherwise the stats will not show anything.
271 AudioEncoderRuntimeConfig config1, config2;
272 config1.bitrate_bps = 32000;
273 config1.num_channels = 2;
274 config1.enable_fec = true;
275 config1.enable_dtx = true;
276 config1.frame_length_ms = 120;
277 config1.uplink_packet_loss_fraction = 0.1f;
278 config2.bitrate_bps = 16000;
279 config2.num_channels = 1;
280 config2.enable_fec = false;
281 config2.enable_dtx = false;
282 config2.frame_length_ms = 60;
283 config1.uplink_packet_loss_fraction = 0.1f;
284
285 EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
286 .WillOnce(SetArgPointee<0>(config1));
287 states.audio_network_adaptor->GetEncoderRuntimeConfig();
288 EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
289 .WillOnce(SetArgPointee<0>(config2));
290 states.audio_network_adaptor->GetEncoderRuntimeConfig();
291 EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
292 .WillOnce(SetArgPointee<0>(config1));
293 states.audio_network_adaptor->GetEncoderRuntimeConfig();
294
295 auto ana_stats = states.audio_network_adaptor->GetStats();
296
297 EXPECT_EQ(ana_stats.bitrate_action_counter, 2u);
298 EXPECT_EQ(ana_stats.channel_action_counter, 2u);
299 EXPECT_EQ(ana_stats.dtx_action_counter, 2u);
300 EXPECT_EQ(ana_stats.fec_action_counter, 2u);
301 EXPECT_EQ(ana_stats.frame_length_increase_counter, 1u);
302 EXPECT_EQ(ana_stats.frame_length_decrease_counter, 1u);
303 EXPECT_EQ(ana_stats.uplink_packet_loss_fraction, 0.1f);
304 }
305
306 } // namespace webrtc
307