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