1 /*
2 * Copyright (c) 2015 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 <memory>
12
13 #include "absl/memory/memory.h"
14 #include "api/audio/audio_frame.h"
15 #include "api/audio_codecs/audio_decoder.h"
16 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
17 #include "api/neteq/neteq.h"
18 #include "modules/audio_coding/neteq/default_neteq_factory.h"
19 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
20 #include "rtc_base/ref_counted_object.h"
21 #include "system_wrappers/include/clock.h"
22 #include "test/audio_decoder_proxy_factory.h"
23 #include "test/gmock.h"
24
25 namespace webrtc {
26 namespace test {
27
28 namespace {
29
CreateNetEq(const NetEq::Config & config,Clock * clock,const rtc::scoped_refptr<AudioDecoderFactory> & decoder_factory)30 std::unique_ptr<NetEq> CreateNetEq(
31 const NetEq::Config& config,
32 Clock* clock,
33 const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory) {
34 return DefaultNetEqFactory().CreateNetEq(config, decoder_factory, clock);
35 }
36
37 } // namespace
38
39 using ::testing::_;
40 using ::testing::Return;
41 using ::testing::SetArgPointee;
42
43 class MockAudioDecoder final : public AudioDecoder {
44 public:
45 static const int kPacketDuration = 960; // 48 kHz * 20 ms
46
MockAudioDecoder(int sample_rate_hz,size_t num_channels)47 MockAudioDecoder(int sample_rate_hz, size_t num_channels)
48 : sample_rate_hz_(sample_rate_hz),
49 num_channels_(num_channels),
50 fec_enabled_(false) {}
~MockAudioDecoder()51 ~MockAudioDecoder() override { Die(); }
52 MOCK_METHOD(void, Die, ());
53
54 MOCK_METHOD(void, Reset, (), (override));
55
56 class MockFrame : public AudioDecoder::EncodedAudioFrame {
57 public:
MockFrame(size_t num_channels)58 MockFrame(size_t num_channels) : num_channels_(num_channels) {}
59
Duration() const60 size_t Duration() const override { return kPacketDuration; }
61
Decode(rtc::ArrayView<int16_t> decoded) const62 absl::optional<DecodeResult> Decode(
63 rtc::ArrayView<int16_t> decoded) const override {
64 const size_t output_size =
65 sizeof(int16_t) * kPacketDuration * num_channels_;
66 if (decoded.size() >= output_size) {
67 memset(decoded.data(), 0,
68 sizeof(int16_t) * kPacketDuration * num_channels_);
69 return DecodeResult{kPacketDuration * num_channels_, kSpeech};
70 } else {
71 ADD_FAILURE() << "Expected decoded.size() to be >= output_size ("
72 << decoded.size() << " vs. " << output_size << ")";
73 return absl::nullopt;
74 }
75 }
76
77 private:
78 const size_t num_channels_;
79 };
80
ParsePayload(rtc::Buffer && payload,uint32_t timestamp)81 std::vector<ParseResult> ParsePayload(rtc::Buffer&& payload,
82 uint32_t timestamp) override {
83 std::vector<ParseResult> results;
84 if (fec_enabled_) {
85 std::unique_ptr<MockFrame> fec_frame(new MockFrame(num_channels_));
86 results.emplace_back(timestamp - kPacketDuration, 1,
87 std::move(fec_frame));
88 }
89
90 std::unique_ptr<MockFrame> frame(new MockFrame(num_channels_));
91 results.emplace_back(timestamp, 0, std::move(frame));
92 return results;
93 }
94
PacketDuration(const uint8_t * encoded,size_t encoded_len) const95 int PacketDuration(const uint8_t* encoded,
96 size_t encoded_len) const override {
97 ADD_FAILURE() << "Since going through ParsePayload, PacketDuration should "
98 "never get called.";
99 return kPacketDuration;
100 }
101
PacketHasFec(const uint8_t * encoded,size_t encoded_len) const102 bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override {
103 ADD_FAILURE() << "Since going through ParsePayload, PacketHasFec should "
104 "never get called.";
105 return fec_enabled_;
106 }
107
SampleRateHz() const108 int SampleRateHz() const override { return sample_rate_hz_; }
109
Channels() const110 size_t Channels() const override { return num_channels_; }
111
set_fec_enabled(bool enable_fec)112 void set_fec_enabled(bool enable_fec) { fec_enabled_ = enable_fec; }
113
fec_enabled() const114 bool fec_enabled() const { return fec_enabled_; }
115
116 protected:
DecodeInternal(const uint8_t * encoded,size_t encoded_len,int sample_rate_hz,int16_t * decoded,SpeechType * speech_type)117 int DecodeInternal(const uint8_t* encoded,
118 size_t encoded_len,
119 int sample_rate_hz,
120 int16_t* decoded,
121 SpeechType* speech_type) override {
122 ADD_FAILURE() << "Since going through ParsePayload, DecodeInternal should "
123 "never get called.";
124 return -1;
125 }
126
127 private:
128 const int sample_rate_hz_;
129 const size_t num_channels_;
130 bool fec_enabled_;
131 };
132
133 class NetEqNetworkStatsTest {
134 public:
135 static const int kPayloadSizeByte = 30;
136 static const int kFrameSizeMs = 20;
137 static const uint8_t kPayloadType = 95;
138 static const int kOutputLengthMs = 10;
139
140 enum logic {
141 kIgnore,
142 kEqual,
143 kSmallerThan,
144 kLargerThan,
145 };
146
147 struct NetEqNetworkStatsCheck {
148 logic current_buffer_size_ms;
149 logic preferred_buffer_size_ms;
150 logic jitter_peaks_found;
151 logic packet_loss_rate;
152 logic expand_rate;
153 logic speech_expand_rate;
154 logic preemptive_rate;
155 logic accelerate_rate;
156 logic secondary_decoded_rate;
157 logic secondary_discarded_rate;
158 logic added_zero_samples;
159 NetEqNetworkStatistics stats_ref;
160 };
161
NetEqNetworkStatsTest(const SdpAudioFormat & format,MockAudioDecoder * decoder)162 NetEqNetworkStatsTest(const SdpAudioFormat& format, MockAudioDecoder* decoder)
163 : decoder_(decoder),
164 decoder_factory_(
165 new rtc::RefCountedObject<AudioDecoderProxyFactory>(decoder)),
166 samples_per_ms_(format.clockrate_hz / 1000),
167 frame_size_samples_(kFrameSizeMs * samples_per_ms_),
168 rtp_generator_(new RtpGenerator(samples_per_ms_)),
169 last_lost_time_(0),
170 packet_loss_interval_(0xffffffff) {
171 NetEq::Config config;
172 config.sample_rate_hz = format.clockrate_hz;
173 neteq_ = CreateNetEq(config, Clock::GetRealTimeClock(), decoder_factory_);
174 neteq_->RegisterPayloadType(kPayloadType, format);
175 }
176
Lost(uint32_t send_time)177 bool Lost(uint32_t send_time) {
178 if (send_time - last_lost_time_ >= packet_loss_interval_) {
179 last_lost_time_ = send_time;
180 return true;
181 }
182 return false;
183 }
184
SetPacketLossRate(double loss_rate)185 void SetPacketLossRate(double loss_rate) {
186 packet_loss_interval_ =
187 (loss_rate >= 1e-3 ? static_cast<double>(kFrameSizeMs) / loss_rate
188 : 0xffffffff);
189 }
190
191 // |stats_ref|
192 // expects.x = -1, do not care
193 // expects.x = 0, 'x' in current stats should equal 'x' in |stats_ref|
194 // expects.x = 1, 'x' in current stats should < 'x' in |stats_ref|
195 // expects.x = 2, 'x' in current stats should > 'x' in |stats_ref|
CheckNetworkStatistics(NetEqNetworkStatsCheck expects)196 void CheckNetworkStatistics(NetEqNetworkStatsCheck expects) {
197 NetEqNetworkStatistics stats;
198 neteq_->NetworkStatistics(&stats);
199
200 #define CHECK_NETEQ_NETWORK_STATS(x) \
201 switch (expects.x) { \
202 case kEqual: \
203 EXPECT_EQ(stats.x, expects.stats_ref.x); \
204 break; \
205 case kSmallerThan: \
206 EXPECT_LT(stats.x, expects.stats_ref.x); \
207 break; \
208 case kLargerThan: \
209 EXPECT_GT(stats.x, expects.stats_ref.x); \
210 break; \
211 default: \
212 break; \
213 }
214
215 CHECK_NETEQ_NETWORK_STATS(current_buffer_size_ms);
216 CHECK_NETEQ_NETWORK_STATS(preferred_buffer_size_ms);
217 CHECK_NETEQ_NETWORK_STATS(jitter_peaks_found);
218 CHECK_NETEQ_NETWORK_STATS(packet_loss_rate);
219 CHECK_NETEQ_NETWORK_STATS(expand_rate);
220 CHECK_NETEQ_NETWORK_STATS(speech_expand_rate);
221 CHECK_NETEQ_NETWORK_STATS(preemptive_rate);
222 CHECK_NETEQ_NETWORK_STATS(accelerate_rate);
223 CHECK_NETEQ_NETWORK_STATS(secondary_decoded_rate);
224 CHECK_NETEQ_NETWORK_STATS(secondary_discarded_rate);
225 CHECK_NETEQ_NETWORK_STATS(added_zero_samples);
226
227 #undef CHECK_NETEQ_NETWORK_STATS
228 }
229
RunTest(int num_loops,NetEqNetworkStatsCheck expects)230 void RunTest(int num_loops, NetEqNetworkStatsCheck expects) {
231 uint32_t time_now;
232 uint32_t next_send_time;
233
234 // Initiate |last_lost_time_|.
235 time_now = next_send_time = last_lost_time_ = rtp_generator_->GetRtpHeader(
236 kPayloadType, frame_size_samples_, &rtp_header_);
237 for (int k = 0; k < num_loops; ++k) {
238 // Delay by one frame such that the FEC can come in.
239 while (time_now + kFrameSizeMs >= next_send_time) {
240 next_send_time = rtp_generator_->GetRtpHeader(
241 kPayloadType, frame_size_samples_, &rtp_header_);
242 if (!Lost(next_send_time)) {
243 static const uint8_t payload[kPayloadSizeByte] = {0};
244 ASSERT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header_, payload));
245 }
246 }
247 bool muted = true;
248 EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output_frame_, &muted));
249 ASSERT_FALSE(muted);
250 EXPECT_EQ(decoder_->Channels(), output_frame_.num_channels_);
251 EXPECT_EQ(static_cast<size_t>(kOutputLengthMs * samples_per_ms_),
252 output_frame_.samples_per_channel_);
253 EXPECT_EQ(48000, neteq_->last_output_sample_rate_hz());
254
255 time_now += kOutputLengthMs;
256 }
257 CheckNetworkStatistics(expects);
258 neteq_->FlushBuffers();
259 }
260
DecodeFecTest()261 void DecodeFecTest() {
262 decoder_->set_fec_enabled(false);
263 NetEqNetworkStatsCheck expects = {kIgnore, // current_buffer_size_ms
264 kIgnore, // preferred_buffer_size_ms
265 kIgnore, // jitter_peaks_found
266 kEqual, // packet_loss_rate
267 kEqual, // expand_rate
268 kEqual, // voice_expand_rate
269 kIgnore, // preemptive_rate
270 kEqual, // accelerate_rate
271 kEqual, // decoded_fec_rate
272 kEqual, // discarded_fec_rate
273 kEqual, // added_zero_samples
274 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
275 RunTest(50, expects);
276
277 // Next we introduce packet losses.
278 SetPacketLossRate(0.1);
279 expects.stats_ref.packet_loss_rate = 1337;
280 expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 1065;
281 RunTest(50, expects);
282
283 // Next we enable FEC.
284 decoder_->set_fec_enabled(true);
285 // If FEC fills in the lost packets, no packet loss will be counted.
286 expects.stats_ref.packet_loss_rate = 0;
287 expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 0;
288 expects.stats_ref.secondary_decoded_rate = 2006;
289 expects.stats_ref.secondary_discarded_rate = 14336;
290 RunTest(50, expects);
291 }
292
NoiseExpansionTest()293 void NoiseExpansionTest() {
294 NetEqNetworkStatsCheck expects = {kIgnore, // current_buffer_size_ms
295 kIgnore, // preferred_buffer_size_ms
296 kIgnore, // jitter_peaks_found
297 kEqual, // packet_loss_rate
298 kEqual, // expand_rate
299 kEqual, // speech_expand_rate
300 kIgnore, // preemptive_rate
301 kEqual, // accelerate_rate
302 kEqual, // decoded_fec_rate
303 kEqual, // discard_fec_rate
304 kEqual, // added_zero_samples
305 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
306 RunTest(50, expects);
307
308 SetPacketLossRate(1);
309 expects.stats_ref.expand_rate = 16384;
310 expects.stats_ref.speech_expand_rate = 5324;
311 RunTest(10, expects); // Lost 10 * 20ms in a row.
312 }
313
314 private:
315 MockAudioDecoder* decoder_;
316 rtc::scoped_refptr<AudioDecoderProxyFactory> decoder_factory_;
317 std::unique_ptr<NetEq> neteq_;
318
319 const int samples_per_ms_;
320 const size_t frame_size_samples_;
321 std::unique_ptr<RtpGenerator> rtp_generator_;
322 RTPHeader rtp_header_;
323 uint32_t last_lost_time_;
324 uint32_t packet_loss_interval_;
325 AudioFrame output_frame_;
326 };
327
TEST(NetEqNetworkStatsTest,DecodeFec)328 TEST(NetEqNetworkStatsTest, DecodeFec) {
329 MockAudioDecoder decoder(48000, 1);
330 NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
331 test.DecodeFecTest();
332 EXPECT_CALL(decoder, Die()).Times(1);
333 }
334
TEST(NetEqNetworkStatsTest,StereoDecodeFec)335 TEST(NetEqNetworkStatsTest, StereoDecodeFec) {
336 MockAudioDecoder decoder(48000, 2);
337 NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
338 test.DecodeFecTest();
339 EXPECT_CALL(decoder, Die()).Times(1);
340 }
341
TEST(NetEqNetworkStatsTest,NoiseExpansionTest)342 TEST(NetEqNetworkStatsTest, NoiseExpansionTest) {
343 MockAudioDecoder decoder(48000, 1);
344 NetEqNetworkStatsTest test(SdpAudioFormat("opus", 48000, 2), &decoder);
345 test.NoiseExpansionTest();
346 EXPECT_CALL(decoder, Die()).Times(1);
347 }
348
349 } // namespace test
350 } // namespace webrtc
351