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 "testing/gmock/include/gmock/gmock.h"
12#include "webrtc/base/scoped_ptr.h"
13#include "webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h"
14#include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
15
16namespace webrtc {
17namespace test {
18
19using ::testing::_;
20using ::testing::SetArgPointee;
21using ::testing::Return;
22
23class MockAudioDecoder final : public AudioDecoder {
24 public:
25  static const int kPacketDuration = 960;  // 48 kHz * 20 ms
26
27  explicit MockAudioDecoder(size_t num_channels)
28      : num_channels_(num_channels), fec_enabled_(false) {
29  }
30  ~MockAudioDecoder() override { Die(); }
31  MOCK_METHOD0(Die, void());
32
33  MOCK_METHOD0(Reset, void());
34
35  int PacketDuration(const uint8_t* encoded,
36                     size_t encoded_len) const override {
37    return kPacketDuration;
38  }
39
40  int PacketDurationRedundant(const uint8_t* encoded,
41                              size_t encoded_len) const override {
42    return kPacketDuration;
43  }
44
45  bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override {
46    return fec_enabled_;
47  }
48
49  size_t Channels() const override { return num_channels_; }
50
51  void set_fec_enabled(bool enable_fec) { fec_enabled_ = enable_fec; }
52
53  bool fec_enabled() const { return fec_enabled_; }
54
55 protected:
56  // Override the following methods such that no actual payload is needed.
57  int DecodeInternal(const uint8_t* encoded,
58                     size_t encoded_len,
59                     int /*sample_rate_hz*/,
60                     int16_t* decoded,
61                     SpeechType* speech_type) override {
62    *speech_type = kSpeech;
63    memset(decoded, 0, sizeof(int16_t) * kPacketDuration * Channels());
64    return kPacketDuration * Channels();
65  }
66
67  int DecodeRedundantInternal(const uint8_t* encoded,
68                              size_t encoded_len,
69                              int sample_rate_hz,
70                              int16_t* decoded,
71                              SpeechType* speech_type) override {
72    return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,
73                          speech_type);
74  }
75
76 private:
77  const size_t num_channels_;
78  bool fec_enabled_;
79};
80
81class NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
82 public:
83  static const int kPayloadSizeByte = 30;
84  static const int kFrameSizeMs = 20;
85  static const int kMaxOutputSize = 960;  // 10 ms * 48 kHz * 2 channels.
86
87enum logic {
88  IGNORE,
89  EQUAL,
90  SMALLER_THAN,
91  LARGER_THAN,
92};
93
94struct NetEqNetworkStatsCheck {
95  logic current_buffer_size_ms;
96  logic preferred_buffer_size_ms;
97  logic jitter_peaks_found;
98  logic packet_loss_rate;
99  logic packet_discard_rate;
100  logic expand_rate;
101  logic speech_expand_rate;
102  logic preemptive_rate;
103  logic accelerate_rate;
104  logic secondary_decoded_rate;
105  logic clockdrift_ppm;
106  logic added_zero_samples;
107  NetEqNetworkStatistics stats_ref;
108};
109
110  NetEqNetworkStatsTest(NetEqDecoder codec,
111                        MockAudioDecoder* decoder)
112      : NetEqExternalDecoderTest(codec, decoder),
113        external_decoder_(decoder),
114        samples_per_ms_(CodecSampleRateHz(codec) / 1000),
115        frame_size_samples_(kFrameSizeMs * samples_per_ms_),
116        rtp_generator_(new test::RtpGenerator(samples_per_ms_)),
117        last_lost_time_(0),
118        packet_loss_interval_(0xffffffff) {
119    Init();
120  }
121
122  bool Lost(uint32_t send_time) {
123    if (send_time - last_lost_time_ >= packet_loss_interval_) {
124      last_lost_time_ = send_time;
125      return true;
126    }
127    return false;
128  }
129
130  void SetPacketLossRate(double loss_rate) {
131      packet_loss_interval_ = (loss_rate >= 1e-3 ?
132          static_cast<double>(kFrameSizeMs) / loss_rate : 0xffffffff);
133  }
134
135  // |stats_ref|
136  // expects.x = -1, do not care
137  // expects.x = 0, 'x' in current stats should equal 'x' in |stats_ref|
138  // expects.x = 1, 'x' in current stats should < 'x' in |stats_ref|
139  // expects.x = 2, 'x' in current stats should > 'x' in |stats_ref|
140  void CheckNetworkStatistics(NetEqNetworkStatsCheck expects) {
141    NetEqNetworkStatistics stats;
142    neteq()->NetworkStatistics(&stats);
143
144#define CHECK_NETEQ_NETWORK_STATS(x)\
145  switch (expects.x) {\
146    case EQUAL:\
147      EXPECT_EQ(stats.x, expects.stats_ref.x);\
148      break;\
149    case SMALLER_THAN:\
150      EXPECT_LT(stats.x, expects.stats_ref.x);\
151      break;\
152    case LARGER_THAN:\
153      EXPECT_GT(stats.x, expects.stats_ref.x);\
154      break;\
155    default:\
156      break;\
157  }
158
159    CHECK_NETEQ_NETWORK_STATS(current_buffer_size_ms);
160    CHECK_NETEQ_NETWORK_STATS(preferred_buffer_size_ms);
161    CHECK_NETEQ_NETWORK_STATS(jitter_peaks_found);
162    CHECK_NETEQ_NETWORK_STATS(packet_loss_rate);
163    CHECK_NETEQ_NETWORK_STATS(packet_discard_rate);
164    CHECK_NETEQ_NETWORK_STATS(expand_rate);
165    CHECK_NETEQ_NETWORK_STATS(speech_expand_rate);
166    CHECK_NETEQ_NETWORK_STATS(preemptive_rate);
167    CHECK_NETEQ_NETWORK_STATS(accelerate_rate);
168    CHECK_NETEQ_NETWORK_STATS(secondary_decoded_rate);
169    CHECK_NETEQ_NETWORK_STATS(clockdrift_ppm);
170    CHECK_NETEQ_NETWORK_STATS(added_zero_samples);
171
172#undef CHECK_NETEQ_NETWORK_STATS
173
174    // Compare with CurrentDelay, which should be identical.
175    EXPECT_EQ(stats.current_buffer_size_ms, neteq()->CurrentDelayMs());
176  }
177
178  void RunTest(int num_loops, NetEqNetworkStatsCheck expects) {
179    NetEqOutputType output_type;
180    uint32_t time_now;
181    uint32_t next_send_time;
182
183    // Initiate |last_lost_time_|.
184    time_now = next_send_time = last_lost_time_ =
185        rtp_generator_->GetRtpHeader(kPayloadType, frame_size_samples_,
186                                     &rtp_header_);
187    for (int k = 0; k < num_loops; ++k) {
188      // Delay by one frame such that the FEC can come in.
189      while (time_now + kFrameSizeMs >= next_send_time) {
190        next_send_time = rtp_generator_->GetRtpHeader(kPayloadType,
191                                                      frame_size_samples_,
192                                                      &rtp_header_);
193        if (!Lost(next_send_time)) {
194          InsertPacket(rtp_header_, payload_, next_send_time);
195        }
196      }
197      GetOutputAudio(kMaxOutputSize, output_, &output_type);
198      time_now += kOutputLengthMs;
199    }
200    CheckNetworkStatistics(expects);
201    neteq()->FlushBuffers();
202  }
203
204  void DecodeFecTest() {
205    external_decoder_->set_fec_enabled(false);
206    NetEqNetworkStatsCheck expects = {
207      IGNORE,  // current_buffer_size_ms
208      IGNORE,  // preferred_buffer_size_ms
209      IGNORE,  // jitter_peaks_found
210      EQUAL,  // packet_loss_rate
211      EQUAL,  // packet_discard_rate
212      EQUAL,  // expand_rate
213      EQUAL,  // voice_expand_rate
214      IGNORE,  // preemptive_rate
215      EQUAL,  // accelerate_rate
216      EQUAL,  // decoded_fec_rate
217      IGNORE,  // clockdrift_ppm
218      EQUAL,  // added_zero_samples
219      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
220    };
221    RunTest(50, expects);
222
223    // Next we introduce packet losses.
224    SetPacketLossRate(0.1);
225    expects.stats_ref.packet_loss_rate = 1337;
226    expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 1065;
227    RunTest(50, expects);
228
229    // Next we enable FEC.
230    external_decoder_->set_fec_enabled(true);
231    // If FEC fills in the lost packets, no packet loss will be counted.
232    expects.stats_ref.packet_loss_rate = 0;
233    expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 0;
234    expects.stats_ref.secondary_decoded_rate = 2006;
235    RunTest(50, expects);
236  }
237
238  void NoiseExpansionTest() {
239    NetEqNetworkStatsCheck expects = {
240      IGNORE,  // current_buffer_size_ms
241      IGNORE,  // preferred_buffer_size_ms
242      IGNORE,  // jitter_peaks_found
243      EQUAL,  // packet_loss_rate
244      EQUAL,  // packet_discard_rate
245      EQUAL,  // expand_rate
246      EQUAL,  // speech_expand_rate
247      IGNORE,  // preemptive_rate
248      EQUAL,  // accelerate_rate
249      EQUAL,  // decoded_fec_rate
250      IGNORE,  // clockdrift_ppm
251      EQUAL,  // added_zero_samples
252      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
253    };
254    RunTest(50, expects);
255
256    SetPacketLossRate(1);
257    expects.stats_ref.expand_rate = 16384;
258    expects.stats_ref.speech_expand_rate = 5324;
259    RunTest(10, expects);  // Lost 10 * 20ms in a row.
260  }
261
262 private:
263  MockAudioDecoder* external_decoder_;
264  const int samples_per_ms_;
265  const size_t frame_size_samples_;
266  rtc::scoped_ptr<test::RtpGenerator> rtp_generator_;
267  WebRtcRTPHeader rtp_header_;
268  uint32_t last_lost_time_;
269  uint32_t packet_loss_interval_;
270  uint8_t payload_[kPayloadSizeByte];
271  int16_t output_[kMaxOutputSize];
272};
273
274TEST(NetEqNetworkStatsTest, DecodeFec) {
275  MockAudioDecoder decoder(1);
276  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, &decoder);
277  test.DecodeFecTest();
278  EXPECT_CALL(decoder, Die()).Times(1);
279}
280
281TEST(NetEqNetworkStatsTest, StereoDecodeFec) {
282  MockAudioDecoder decoder(2);
283  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, &decoder);
284  test.DecodeFecTest();
285  EXPECT_CALL(decoder, Die()).Times(1);
286}
287
288TEST(NetEqNetworkStatsTest, NoiseExpansionTest) {
289  MockAudioDecoder decoder(1);
290  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, &decoder);
291  test.NoiseExpansionTest();
292  EXPECT_CALL(decoder, Die()).Times(1);
293}
294
295}  // namespace test
296}  // namespace webrtc
297
298
299
300
301