blob: 606237d3039f1e8036de65446d1e055043512ec7 [file] [log] [blame]
minyuecaa9cb22016-09-13 13:34:15 -07001/*
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
Jonas Olssona4d87372019-07-05 19:08:33 +020011#include "modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
12
minyuecaa9cb22016-09-13 13:34:15 -070013#include <utility>
14#include <vector>
15
Danil Chapovalov16cb1f62019-09-05 11:29:59 +020016#include "api/rtc_event_log/rtc_event.h"
Elad Alon4a87e1c2017-10-03 16:11:34 +020017#include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#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"
Steve Anton10542f22019-01-11 09:11:00 -080022#include "rtc_base/fake_clock.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "test/field_trial.h"
24#include "test/gtest.h"
minyuecaa9cb22016-09-13 13:34:15 -070025
26namespace webrtc {
27
28using ::testing::_;
29using ::testing::NiceMock;
30using ::testing::Return;
minyue25f6a392016-09-22 22:23:20 -070031using ::testing::SetArgPointee;
minyuecaa9cb22016-09-13 13:34:15 -070032
33namespace {
34
35constexpr size_t kNumControllers = 2;
36
minyue25f6a392016-09-22 22:23:20 -070037constexpr int64_t kClockInitialTimeMs = 12345678;
38
minyuecaa9cb22016-09-13 13:34:15 -070039MATCHER_P(NetworkMetricsIs, metric, "") {
40 return arg.uplink_bandwidth_bps == metric.uplink_bandwidth_bps &&
minyue4aec1d42016-09-21 23:01:26 -070041 arg.target_audio_bitrate_bps == metric.target_audio_bitrate_bps &&
minyue25f6a392016-09-22 22:23:20 -070042 arg.rtt_ms == metric.rtt_ms &&
minyuec9e80ee2016-11-29 13:00:28 -080043 arg.overhead_bytes_per_packet == metric.overhead_bytes_per_packet &&
Sebastian Janssoncd2a92f2019-10-31 13:53:53 +010044 arg.uplink_packet_loss_fraction == metric.uplink_packet_loss_fraction;
minyuecaa9cb22016-09-13 13:34:15 -070045}
46
Elad Alon4a87e1c2017-10-03 16:11:34 +020047MATCHER_P(IsRtcEventAnaConfigEqualTo, config, "") {
48 if (arg->GetType() != RtcEvent::Type::AudioNetworkAdaptation) {
49 return false;
50 }
51 auto ana_event = static_cast<RtcEventAudioNetworkAdaptation*>(arg);
Elad Alon0b1b5c12018-11-09 21:50:14 +010052 return ana_event->config() == config;
Elad Alon4a87e1c2017-10-03 16:11:34 +020053}
54
minyue25f6a392016-09-22 22:23:20 -070055MATCHER_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
minyuecaa9cb22016-09-13 13:34:15 -070065struct AudioNetworkAdaptorStates {
66 std::unique_ptr<AudioNetworkAdaptorImpl> audio_network_adaptor;
67 std::vector<std::unique_ptr<MockController>> mock_controllers;
minyue4b7c9522017-01-24 04:54:59 -080068 std::unique_ptr<MockRtcEventLog> event_log;
minyue25f6a392016-09-22 22:23:20 -070069 MockDebugDumpWriter* mock_debug_dump_writer;
minyuecaa9cb22016-09-13 13:34:15 -070070};
71
72AudioNetworkAdaptorStates 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
minyue4b7c9522017-01-24 04:54:59 -080092 states.event_log.reset(new NiceMock<MockRtcEventLog>());
minyue25f6a392016-09-22 22:23:20 -070093
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;
minyue4b7c9522017-01-24 04:54:59 -0800100 config.event_log = states.event_log.get();
minyuecaa9cb22016-09-13 13:34:15 -0700101 // AudioNetworkAdaptorImpl governs the lifetime of controller manager.
102 states.audio_network_adaptor.reset(new AudioNetworkAdaptorImpl(
Yves Gerey665174f2018-06-19 15:03:05 +0200103 config, std::move(controller_manager), std::move(debug_dump_writer)));
minyuecaa9cb22016-09-13 13:34:15 -0700104
105 return states;
106}
107
minyuea6a6d652017-01-30 10:50:00 -0800108void 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
minyuecaa9cb22016-09-13 13:34:15 -0700117} // namespace
118
119TEST(AudioNetworkAdaptorImplTest,
minyuea6a6d652017-01-30 10:50:00 -0800120 UpdateNetworkMetricsIsCalledOnSetUplinkBandwidth) {
121 auto states = CreateAudioNetworkAdaptor();
122 constexpr int kBandwidth = 16000;
123 Controller::NetworkMetrics check;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100124 check.uplink_bandwidth_bps = kBandwidth;
minyuea6a6d652017-01-30 10:50:00 -0800125 SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
126 states.audio_network_adaptor->SetUplinkBandwidth(kBandwidth);
127}
128
129TEST(AudioNetworkAdaptorImplTest,
130 UpdateNetworkMetricsIsCalledOnSetUplinkPacketLossFraction) {
131 auto states = CreateAudioNetworkAdaptor();
132 constexpr float kPacketLoss = 0.7f;
133 Controller::NetworkMetrics check;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100134 check.uplink_packet_loss_fraction = kPacketLoss;
minyuea6a6d652017-01-30 10:50:00 -0800135 SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
136 states.audio_network_adaptor->SetUplinkPacketLossFraction(kPacketLoss);
137}
138
139TEST(AudioNetworkAdaptorImplTest, UpdateNetworkMetricsIsCalledOnSetRtt) {
140 auto states = CreateAudioNetworkAdaptor();
141 constexpr int kRtt = 100;
142 Controller::NetworkMetrics check;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100143 check.rtt_ms = kRtt;
minyuea6a6d652017-01-30 10:50:00 -0800144 SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
145 states.audio_network_adaptor->SetRtt(kRtt);
146}
147
148TEST(AudioNetworkAdaptorImplTest,
149 UpdateNetworkMetricsIsCalledOnSetTargetAudioBitrate) {
150 auto states = CreateAudioNetworkAdaptor();
151 constexpr int kTargetAudioBitrate = 15000;
152 Controller::NetworkMetrics check;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100153 check.target_audio_bitrate_bps = kTargetAudioBitrate;
minyuea6a6d652017-01-30 10:50:00 -0800154 SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
155 states.audio_network_adaptor->SetTargetAudioBitrate(kTargetAudioBitrate);
156}
157
158TEST(AudioNetworkAdaptorImplTest, UpdateNetworkMetricsIsCalledOnSetOverhead) {
159 auto states = CreateAudioNetworkAdaptor();
160 constexpr size_t kOverhead = 64;
161 Controller::NetworkMetrics check;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100162 check.overhead_bytes_per_packet = kOverhead;
minyuea6a6d652017-01-30 10:50:00 -0800163 SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
164 states.audio_network_adaptor->SetOverhead(kOverhead);
165}
166
167TEST(AudioNetworkAdaptorImplTest,
minyuecaa9cb22016-09-13 13:34:15 -0700168 MakeDecisionIsCalledOnGetEncoderRuntimeConfig) {
169 auto states = CreateAudioNetworkAdaptor();
minyuea6a6d652017-01-30 10:50:00 -0800170 for (auto& mock_controller : states.mock_controllers)
171 EXPECT_CALL(*mock_controller, MakeDecision(_));
minyuec9e80ee2016-11-29 13:00:28 -0800172 states.audio_network_adaptor->GetEncoderRuntimeConfig();
minyuecaa9cb22016-09-13 13:34:15 -0700173}
174
minyue25f6a392016-09-22 22:23:20 -0700175TEST(AudioNetworkAdaptorImplTest,
176 DumpEncoderRuntimeConfigIsCalledOnGetEncoderRuntimeConfig) {
ivoc17289092017-09-09 08:45:40 -0700177 test::ScopedFieldTrials override_field_trials(
178 "WebRTC-Audio-BitrateAdaptation/Enabled/WebRTC-Audio-FecAdaptation/"
179 "Enabled/");
michaelt92aef172017-04-18 00:11:48 -0700180 rtc::ScopedFakeClock fake_clock;
Sebastian Jansson5f83cf02018-05-08 14:52:22 +0200181 fake_clock.AdvanceTime(TimeDelta::ms(kClockInitialTimeMs));
minyue25f6a392016-09-22 22:23:20 -0700182 auto states = CreateAudioNetworkAdaptor();
michaeltcde46b72017-04-06 05:59:10 -0700183 AudioEncoderRuntimeConfig config;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100184 config.bitrate_bps = 32000;
185 config.enable_fec = true;
minyue25f6a392016-09-22 22:23:20 -0700186
minyuea6a6d652017-01-30 10:50:00 -0800187 EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
188 .WillOnce(SetArgPointee<0>(config));
minyue25f6a392016-09-22 22:23:20 -0700189
190 EXPECT_CALL(*states.mock_debug_dump_writer,
191 DumpEncoderRuntimeConfig(EncoderRuntimeConfigIs(config),
192 kClockInitialTimeMs));
193 states.audio_network_adaptor->GetEncoderRuntimeConfig();
194}
195
196TEST(AudioNetworkAdaptorImplTest,
197 DumpNetworkMetricsIsCalledOnSetNetworkMetrics) {
michaelt92aef172017-04-18 00:11:48 -0700198 rtc::ScopedFakeClock fake_clock;
Sebastian Jansson5f83cf02018-05-08 14:52:22 +0200199 fake_clock.AdvanceTime(TimeDelta::ms(kClockInitialTimeMs));
michaelt92aef172017-04-18 00:11:48 -0700200
minyue25f6a392016-09-22 22:23:20 -0700201 auto states = CreateAudioNetworkAdaptor();
202
203 constexpr int kBandwidth = 16000;
204 constexpr float kPacketLoss = 0.7f;
205 constexpr int kRtt = 100;
minyuee5e632f2016-09-27 12:54:19 -0700206 constexpr int kTargetAudioBitrate = 15000;
minyuec9e80ee2016-11-29 13:00:28 -0800207 constexpr size_t kOverhead = 64;
minyue25f6a392016-09-22 22:23:20 -0700208
209 Controller::NetworkMetrics check;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100210 check.uplink_bandwidth_bps = kBandwidth;
minyue25f6a392016-09-22 22:23:20 -0700211 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
Sebastian Jansson5f83cf02018-05-08 14:52:22 +0200217 fake_clock.AdvanceTime(TimeDelta::ms(100));
minyue25f6a392016-09-22 22:23:20 -0700218 timestamp_check += 100;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100219 check.uplink_packet_loss_fraction = kPacketLoss;
minyue25f6a392016-09-22 22:23:20 -0700220 EXPECT_CALL(*states.mock_debug_dump_writer,
221 DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
222 states.audio_network_adaptor->SetUplinkPacketLossFraction(kPacketLoss);
223
Sebastian Jansson5f83cf02018-05-08 14:52:22 +0200224 fake_clock.AdvanceTime(TimeDelta::ms(50));
elad.alondadb4dc2017-03-23 15:29:50 -0700225 timestamp_check += 50;
elad.alondadb4dc2017-03-23 15:29:50 -0700226
Sebastian Jansson5f83cf02018-05-08 14:52:22 +0200227 fake_clock.AdvanceTime(TimeDelta::ms(200));
minyue25f6a392016-09-22 22:23:20 -0700228 timestamp_check += 200;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100229 check.rtt_ms = kRtt;
minyue25f6a392016-09-22 22:23:20 -0700230 EXPECT_CALL(*states.mock_debug_dump_writer,
231 DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
232 states.audio_network_adaptor->SetRtt(kRtt);
minyuee5e632f2016-09-27 12:54:19 -0700233
Sebastian Jansson5f83cf02018-05-08 14:52:22 +0200234 fake_clock.AdvanceTime(TimeDelta::ms(150));
minyuee5e632f2016-09-27 12:54:19 -0700235 timestamp_check += 150;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100236 check.target_audio_bitrate_bps = kTargetAudioBitrate;
minyuee5e632f2016-09-27 12:54:19 -0700237 EXPECT_CALL(*states.mock_debug_dump_writer,
238 DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
239 states.audio_network_adaptor->SetTargetAudioBitrate(kTargetAudioBitrate);
minyuec9e80ee2016-11-29 13:00:28 -0800240
Sebastian Jansson5f83cf02018-05-08 14:52:22 +0200241 fake_clock.AdvanceTime(TimeDelta::ms(50));
minyuec9e80ee2016-11-29 13:00:28 -0800242 timestamp_check += 50;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100243 check.overhead_bytes_per_packet = kOverhead;
minyuec9e80ee2016-11-29 13:00:28 -0800244 EXPECT_CALL(*states.mock_debug_dump_writer,
245 DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
246 states.audio_network_adaptor->SetOverhead(kOverhead);
minyue25f6a392016-09-22 22:23:20 -0700247}
248
minyue4b7c9522017-01-24 04:54:59 -0800249TEST(AudioNetworkAdaptorImplTest, LogRuntimeConfigOnGetEncoderRuntimeConfig) {
ivoc17289092017-09-09 08:45:40 -0700250 test::ScopedFieldTrials override_field_trials(
251 "WebRTC-Audio-BitrateAdaptation/Enabled/WebRTC-Audio-FecAdaptation/"
252 "Enabled/");
minyue4b7c9522017-01-24 04:54:59 -0800253 auto states = CreateAudioNetworkAdaptor();
254
michaeltcde46b72017-04-06 05:59:10 -0700255 AudioEncoderRuntimeConfig config;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100256 config.bitrate_bps = 32000;
257 config.enable_fec = true;
minyue4b7c9522017-01-24 04:54:59 -0800258
minyuea6a6d652017-01-30 10:50:00 -0800259 EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
260 .WillOnce(SetArgPointee<0>(config));
minyue4b7c9522017-01-24 04:54:59 -0800261
Elad Alon4a87e1c2017-10-03 16:11:34 +0200262 EXPECT_CALL(*states.event_log, LogProxy(IsRtcEventAnaConfigEqualTo(config)))
minyue4b7c9522017-01-24 04:54:59 -0800263 .Times(1);
264 states.audio_network_adaptor->GetEncoderRuntimeConfig();
265}
266
ivoce1198e02017-09-08 08:13:19 -0700267TEST(AudioNetworkAdaptorImplTest, TestANAStats) {
268 auto states = CreateAudioNetworkAdaptor();
269
270 // Simulate some adaptation, otherwise the stats will not show anything.
271 AudioEncoderRuntimeConfig config1, config2;
Oskar Sundbom12ab00b2017-11-16 15:31:38 +0100272 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;
ivoce1198e02017-09-08 08:13:19 -0700284
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();
ivoc17289092017-09-09 08:45:40 -0700291 EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
292 .WillOnce(SetArgPointee<0>(config1));
293 states.audio_network_adaptor->GetEncoderRuntimeConfig();
ivoce1198e02017-09-08 08:13:19 -0700294
295 auto ana_stats = states.audio_network_adaptor->GetStats();
296
Danil Chapovalov4da18e82018-04-06 18:03:46 +0200297 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);
ivoc17289092017-09-09 08:45:40 -0700303 EXPECT_EQ(ana_stats.uplink_packet_loss_fraction, 0.1f);
ivoce1198e02017-09-08 08:13:19 -0700304}
305
minyuecaa9cb22016-09-13 13:34:15 -0700306} // namespace webrtc