• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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