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/event_log_writer.h"
12 
13 #include <memory>
14 
15 #include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
16 #include "logging/rtc_event_log/mock/mock_rtc_event_log.h"
17 #include "rtc_base/checks.h"
18 #include "test/gtest.h"
19 
20 namespace webrtc {
21 
22 namespace {
23 
24 constexpr int kMinBitrateChangeBps = 5000;
25 constexpr float kMinPacketLossChangeFraction = 0.5;
26 constexpr float kMinBitrateChangeFraction = 0.25;
27 
28 constexpr int kHighBitrateBps = 70000;
29 constexpr int kLowBitrateBps = 10000;
30 constexpr int kFrameLengthMs = 60;
31 constexpr bool kEnableFec = true;
32 constexpr bool kEnableDtx = true;
33 constexpr float kPacketLossFraction = 0.05f;
34 constexpr size_t kNumChannels = 1;
35 
36 MATCHER_P(IsRtcEventAnaConfigEqualTo, config, "") {
37   if (arg->GetType() != RtcEvent::Type::AudioNetworkAdaptation) {
38     return false;
39   }
40   auto ana_event = static_cast<RtcEventAudioNetworkAdaptation*>(arg);
41   return ana_event->config() == config;
42 }
43 
44 struct EventLogWriterStates {
45   std::unique_ptr<EventLogWriter> event_log_writer;
46   std::unique_ptr<testing::StrictMock<MockRtcEventLog>> event_log;
47   AudioEncoderRuntimeConfig runtime_config;
48 };
49 
CreateEventLogWriter()50 EventLogWriterStates CreateEventLogWriter() {
51   EventLogWriterStates state;
52   state.event_log.reset(new ::testing::StrictMock<MockRtcEventLog>());
53   state.event_log_writer.reset(new EventLogWriter(
54       state.event_log.get(), kMinBitrateChangeBps, kMinBitrateChangeFraction,
55       kMinPacketLossChangeFraction));
56   state.runtime_config.bitrate_bps = kHighBitrateBps;
57   state.runtime_config.frame_length_ms = kFrameLengthMs;
58   state.runtime_config.uplink_packet_loss_fraction = kPacketLossFraction;
59   state.runtime_config.enable_fec = kEnableFec;
60   state.runtime_config.enable_dtx = kEnableDtx;
61   state.runtime_config.num_channels = kNumChannels;
62   return state;
63 }
64 }  // namespace
65 
TEST(EventLogWriterTest,FirstConfigIsLogged)66 TEST(EventLogWriterTest, FirstConfigIsLogged) {
67   auto state = CreateEventLogWriter();
68   EXPECT_CALL(*state.event_log,
69               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
70       .Times(1);
71   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
72 }
73 
TEST(EventLogWriterTest,SameConfigIsNotLogged)74 TEST(EventLogWriterTest, SameConfigIsNotLogged) {
75   auto state = CreateEventLogWriter();
76   EXPECT_CALL(*state.event_log,
77               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
78       .Times(1);
79   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
80   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
81 }
82 
TEST(EventLogWriterTest,LogFecStateChange)83 TEST(EventLogWriterTest, LogFecStateChange) {
84   auto state = CreateEventLogWriter();
85   EXPECT_CALL(*state.event_log,
86               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
87       .Times(1);
88   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
89 
90   state.runtime_config.enable_fec = !kEnableFec;
91   EXPECT_CALL(*state.event_log,
92               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
93       .Times(1);
94   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
95 }
96 
TEST(EventLogWriterTest,LogDtxStateChange)97 TEST(EventLogWriterTest, LogDtxStateChange) {
98   auto state = CreateEventLogWriter();
99   EXPECT_CALL(*state.event_log,
100               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
101       .Times(1);
102   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
103 
104   state.runtime_config.enable_dtx = !kEnableDtx;
105   EXPECT_CALL(*state.event_log,
106               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
107       .Times(1);
108   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
109 }
110 
TEST(EventLogWriterTest,LogChannelChange)111 TEST(EventLogWriterTest, LogChannelChange) {
112   auto state = CreateEventLogWriter();
113   EXPECT_CALL(*state.event_log,
114               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
115       .Times(1);
116   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
117 
118   state.runtime_config.num_channels = kNumChannels + 1;
119   EXPECT_CALL(*state.event_log,
120               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
121       .Times(1);
122   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
123 }
124 
TEST(EventLogWriterTest,LogFrameLengthChange)125 TEST(EventLogWriterTest, LogFrameLengthChange) {
126   auto state = CreateEventLogWriter();
127   EXPECT_CALL(*state.event_log,
128               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
129       .Times(1);
130   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
131 
132   state.runtime_config.frame_length_ms = 20;
133   EXPECT_CALL(*state.event_log,
134               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
135       .Times(1);
136   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
137 }
138 
TEST(EventLogWriterTest,DoNotLogSmallBitrateChange)139 TEST(EventLogWriterTest, DoNotLogSmallBitrateChange) {
140   auto state = CreateEventLogWriter();
141   EXPECT_CALL(*state.event_log,
142               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
143       .Times(1);
144   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
145   state.runtime_config.bitrate_bps = kHighBitrateBps + kMinBitrateChangeBps - 1;
146   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
147 }
148 
TEST(EventLogWriterTest,LogLargeBitrateChange)149 TEST(EventLogWriterTest, LogLargeBitrateChange) {
150   auto state = CreateEventLogWriter();
151   EXPECT_CALL(*state.event_log,
152               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
153       .Times(1);
154   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
155   // At high bitrate, the min fraction rule requires a larger change than the
156   // min change rule. We make sure that the min change rule applies.
157   RTC_DCHECK_GT(kHighBitrateBps * kMinBitrateChangeFraction,
158                 kMinBitrateChangeBps);
159   state.runtime_config.bitrate_bps = kHighBitrateBps + kMinBitrateChangeBps;
160   EXPECT_CALL(*state.event_log,
161               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
162       .Times(1);
163   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
164 }
165 
TEST(EventLogWriterTest,LogMinBitrateChangeFractionOnLowBitrateChange)166 TEST(EventLogWriterTest, LogMinBitrateChangeFractionOnLowBitrateChange) {
167   auto state = CreateEventLogWriter();
168   state.runtime_config.bitrate_bps = kLowBitrateBps;
169   EXPECT_CALL(*state.event_log,
170               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
171       .Times(1);
172   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
173   // At high bitrate, the min change rule requires a larger change than the min
174   // fraction rule. We make sure that the min fraction rule applies.
175   state.runtime_config.bitrate_bps =
176       kLowBitrateBps + kLowBitrateBps * kMinBitrateChangeFraction;
177   EXPECT_CALL(*state.event_log,
178               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
179       .Times(1);
180   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
181 }
182 
TEST(EventLogWriterTest,DoNotLogSmallPacketLossFractionChange)183 TEST(EventLogWriterTest, DoNotLogSmallPacketLossFractionChange) {
184   auto state = CreateEventLogWriter();
185   EXPECT_CALL(*state.event_log,
186               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
187       .Times(1);
188   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
189   state.runtime_config.uplink_packet_loss_fraction =
190       kPacketLossFraction + kMinPacketLossChangeFraction * kPacketLossFraction -
191       0.001f;
192   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
193 }
194 
TEST(EventLogWriterTest,LogLargePacketLossFractionChange)195 TEST(EventLogWriterTest, LogLargePacketLossFractionChange) {
196   auto state = CreateEventLogWriter();
197   EXPECT_CALL(*state.event_log,
198               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
199       .Times(1);
200   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
201   state.runtime_config.uplink_packet_loss_fraction =
202       kPacketLossFraction + kMinPacketLossChangeFraction * kPacketLossFraction;
203   EXPECT_CALL(*state.event_log,
204               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
205       .Times(1);
206   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
207 }
208 
TEST(EventLogWriterTest,LogJustOnceOnMultipleChanges)209 TEST(EventLogWriterTest, LogJustOnceOnMultipleChanges) {
210   auto state = CreateEventLogWriter();
211   EXPECT_CALL(*state.event_log,
212               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
213       .Times(1);
214   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
215   state.runtime_config.uplink_packet_loss_fraction =
216       kPacketLossFraction + kMinPacketLossChangeFraction * kPacketLossFraction;
217   state.runtime_config.frame_length_ms = 20;
218   EXPECT_CALL(*state.event_log,
219               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
220       .Times(1);
221   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
222 }
223 
TEST(EventLogWriterTest,LogAfterGradualChange)224 TEST(EventLogWriterTest, LogAfterGradualChange) {
225   auto state = CreateEventLogWriter();
226   EXPECT_CALL(*state.event_log,
227               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
228       .Times(1);
229   state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
230   state.runtime_config.bitrate_bps = kHighBitrateBps + kMinBitrateChangeBps;
231   EXPECT_CALL(*state.event_log,
232               LogProxy(IsRtcEventAnaConfigEqualTo(state.runtime_config)))
233       .Times(1);
234   for (int bitrate_bps = kHighBitrateBps;
235        bitrate_bps <= kHighBitrateBps + kMinBitrateChangeBps; bitrate_bps++) {
236     state.runtime_config.bitrate_bps = bitrate_bps;
237     state.event_log_writer->MaybeLogEncoderConfig(state.runtime_config);
238   }
239 }
240 }  // namespace webrtc
241