12c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org/*
22c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
32c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org *
42c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org *  Use of this source code is governed by a BSD-style license
52c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org *  that can be found in the LICENSE file in the root of the source
62c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org *  tree. An additional intellectual property rights grant can be found
72c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org *  in the file PATENTS.  All contributing project authors may
82c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
92c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org */
102c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
112c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org#include "testing/gmock/include/gmock/gmock.h"
1200b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org#include "webrtc/base/scoped_ptr.h"
132c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org#include "webrtc/modules/audio_coding/neteq/tools/neteq_external_decoder_test.h"
142c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org#include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
152c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
162c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.orgnamespace webrtc {
172c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.orgnamespace test {
182c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
192c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.orgusing ::testing::_;
202c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.orgusing ::testing::SetArgPointee;
212c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.orgusing ::testing::Return;
222c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
238967183bf79322c5cb3cbd99e9b7aa298228d0a2kwibergclass MockAudioDecoder final : public AudioDecoder {
242c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org public:
252c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  static const int kPacketDuration = 960;  // 48 kHz * 20 ms
262c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
278967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg  explicit MockAudioDecoder(size_t num_channels)
288967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg      : num_channels_(num_channels), fec_enabled_(false) {
292c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  }
308967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg  ~MockAudioDecoder() override { Die(); }
312c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  MOCK_METHOD0(Die, void());
322c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
334376648df021fd82f25a38694e33678f802d06eaKarl Wiberg  MOCK_METHOD0(Reset, void());
342c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
352c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  int PacketDuration(const uint8_t* encoded,
362c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org                     size_t encoded_len) const override {
372c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    return kPacketDuration;
382c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  }
392c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
402c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  int PacketDurationRedundant(const uint8_t* encoded,
412c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org                              size_t encoded_len) const override {
422c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    return kPacketDuration;
432c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  }
442c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
452c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override {
462c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    return fec_enabled_;
472c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  }
482c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
498967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg  size_t Channels() const override { return num_channels_; }
508967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg
512c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  void set_fec_enabled(bool enable_fec) { fec_enabled_ = enable_fec; }
522c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
532c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  bool fec_enabled() const { return fec_enabled_; }
542c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
557f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org protected:
567f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org  // Override the following methods such that no actual payload is needed.
577f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org  int DecodeInternal(const uint8_t* encoded,
587f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org                     size_t encoded_len,
597f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org                     int /*sample_rate_hz*/,
607f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org                     int16_t* decoded,
617f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org                     SpeechType* speech_type) override {
627f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org    *speech_type = kSpeech;
636dba1ebd14d8cd96e6e56adad868b33fdedecc53henrik.lundin@webrtc.org    memset(decoded, 0, sizeof(int16_t) * kPacketDuration * Channels());
646dba1ebd14d8cd96e6e56adad868b33fdedecc53henrik.lundin@webrtc.org    return kPacketDuration * Channels();
657f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org  }
667f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org
677f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org  int DecodeRedundantInternal(const uint8_t* encoded,
687f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org                              size_t encoded_len,
697f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org                              int sample_rate_hz,
707f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org                              int16_t* decoded,
717f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org                              SpeechType* speech_type) override {
727f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org    return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,
737f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org                          speech_type);
747f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org  }
757f7d7e3427cc70e1b8b050283ef031e28c83699aminyue@webrtc.org
762c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org private:
778967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg  const size_t num_channels_;
782c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  bool fec_enabled_;
792c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org};
802c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
812c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.orgclass NetEqNetworkStatsTest : public NetEqExternalDecoderTest {
822c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org public:
832c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  static const int kPayloadSizeByte = 30;
848967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg  static const int kFrameSizeMs = 20;
852c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  static const int kMaxOutputSize = 960;  // 10 ms * 48 kHz * 2 channels.
862c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
872c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.orgenum logic {
882c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  IGNORE,
892c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  EQUAL,
902c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  SMALLER_THAN,
912c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  LARGER_THAN,
922c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org};
932c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
942c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.orgstruct NetEqNetworkStatsCheck {
952c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  logic current_buffer_size_ms;
962c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  logic preferred_buffer_size_ms;
972c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  logic jitter_peaks_found;
982c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  logic packet_loss_rate;
992c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  logic packet_discard_rate;
1002c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  logic expand_rate;
1017d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org  logic speech_expand_rate;
1022c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  logic preemptive_rate;
1032c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  logic accelerate_rate;
1042c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  logic secondary_decoded_rate;
1052c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  logic clockdrift_ppm;
1062c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  logic added_zero_samples;
1072c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  NetEqNetworkStatistics stats_ref;
1082c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org};
1092c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
1102c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  NetEqNetworkStatsTest(NetEqDecoder codec,
1118967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg                        MockAudioDecoder* decoder)
1122c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      : NetEqExternalDecoderTest(codec, decoder),
1132c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org        external_decoder_(decoder),
1142c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org        samples_per_ms_(CodecSampleRateHz(codec) / 1000),
1152c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org        frame_size_samples_(kFrameSizeMs * samples_per_ms_),
1162c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org        rtp_generator_(new test::RtpGenerator(samples_per_ms_)),
1172c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org        last_lost_time_(0),
1182c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org        packet_loss_interval_(0xffffffff) {
1192c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    Init();
1202c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  }
1212c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
1222c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  bool Lost(uint32_t send_time) {
1232c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    if (send_time - last_lost_time_ >= packet_loss_interval_) {
1242c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      last_lost_time_ = send_time;
1252c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      return true;
1262c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    }
1272c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    return false;
1282c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  }
1292c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
1302c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  void SetPacketLossRate(double loss_rate) {
1312c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      packet_loss_interval_ = (loss_rate >= 1e-3 ?
1322c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org          static_cast<double>(kFrameSizeMs) / loss_rate : 0xffffffff);
1332c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  }
1342c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
1352c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  // |stats_ref|
1362c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  // expects.x = -1, do not care
1372c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  // expects.x = 0, 'x' in current stats should equal 'x' in |stats_ref|
1382c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  // expects.x = 1, 'x' in current stats should < 'x' in |stats_ref|
1392c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  // expects.x = 2, 'x' in current stats should > 'x' in |stats_ref|
1402c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  void CheckNetworkStatistics(NetEqNetworkStatsCheck expects) {
1412c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    NetEqNetworkStatistics stats;
1422c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    neteq()->NetworkStatistics(&stats);
1432c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
1442c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org#define CHECK_NETEQ_NETWORK_STATS(x)\
1452c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  switch (expects.x) {\
1462c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    case EQUAL:\
1472c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      EXPECT_EQ(stats.x, expects.stats_ref.x);\
1482c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      break;\
1492c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    case SMALLER_THAN:\
1502c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      EXPECT_LT(stats.x, expects.stats_ref.x);\
1512c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      break;\
1522c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    case LARGER_THAN:\
1532c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      EXPECT_GT(stats.x, expects.stats_ref.x);\
1542c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      break;\
1552c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    default:\
1562c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      break;\
1572c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  }
1582c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
1592c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(current_buffer_size_ms);
1602c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(preferred_buffer_size_ms);
1612c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(jitter_peaks_found);
1622c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(packet_loss_rate);
1632c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(packet_discard_rate);
1642c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(expand_rate);
1657d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(speech_expand_rate);
1662c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(preemptive_rate);
1672c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(accelerate_rate);
1682c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(secondary_decoded_rate);
1692c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(clockdrift_ppm);
1702c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CHECK_NETEQ_NETWORK_STATS(added_zero_samples);
1712c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
1722c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org#undef CHECK_NETEQ_NETWORK_STATS
1739c3efd00523a81d0f2b582799fbe67afe44139b2henrik.lundin
1749c3efd00523a81d0f2b582799fbe67afe44139b2henrik.lundin    // Compare with CurrentDelay, which should be identical.
1759c3efd00523a81d0f2b582799fbe67afe44139b2henrik.lundin    EXPECT_EQ(stats.current_buffer_size_ms, neteq()->CurrentDelayMs());
1762c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  }
1772c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
1782c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  void RunTest(int num_loops, NetEqNetworkStatsCheck expects) {
1792c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    NetEqOutputType output_type;
1802c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    uint32_t time_now;
1812c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    uint32_t next_send_time;
1822c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
1832c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    // Initiate |last_lost_time_|.
1842c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    time_now = next_send_time = last_lost_time_ =
1852c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org        rtp_generator_->GetRtpHeader(kPayloadType, frame_size_samples_,
1862c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org                                     &rtp_header_);
1872c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    for (int k = 0; k < num_loops; ++k) {
1882c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      // Delay by one frame such that the FEC can come in.
1892c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      while (time_now + kFrameSizeMs >= next_send_time) {
1902c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org        next_send_time = rtp_generator_->GetRtpHeader(kPayloadType,
1912c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org                                                      frame_size_samples_,
1922c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org                                                      &rtp_header_);
1932c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org        if (!Lost(next_send_time)) {
194ee2bac26dd3eb4463126098f87701ff66098b288kwiberg          InsertPacket(rtp_header_, payload_, next_send_time);
1952c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org        }
1962c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      }
1972c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      GetOutputAudio(kMaxOutputSize, output_, &output_type);
1982c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      time_now += kOutputLengthMs;
1992c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    }
2002c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    CheckNetworkStatistics(expects);
2012c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    neteq()->FlushBuffers();
2022c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  }
2032c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
2042c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  void DecodeFecTest() {
2052c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    external_decoder_->set_fec_enabled(false);
2062c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    NetEqNetworkStatsCheck expects = {
2072c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      IGNORE,  // current_buffer_size_ms
2082c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      IGNORE,  // preferred_buffer_size_ms
2092c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      IGNORE,  // jitter_peaks_found
2102c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      EQUAL,  // packet_loss_rate
2112c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      EQUAL,  // packet_discard_rate
2122c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      EQUAL,  // expand_rate
2137d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      EQUAL,  // voice_expand_rate
2142c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      IGNORE,  // preemptive_rate
2152c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      EQUAL,  // accelerate_rate
2162c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      EQUAL,  // decoded_fec_rate
2172c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      IGNORE,  // clockdrift_ppm
2182c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org      EQUAL,  // added_zero_samples
2197d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
2202c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    };
2212c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    RunTest(50, expects);
2222c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
2232c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    // Next we introduce packet losses.
2242c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    SetPacketLossRate(0.1);
2252c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    expects.stats_ref.packet_loss_rate = 1337;
2267d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org    expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 1065;
2272c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    RunTest(50, expects);
2282c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
2298967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg    // Next we enable FEC.
2302c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    external_decoder_->set_fec_enabled(true);
2312c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    // If FEC fills in the lost packets, no packet loss will be counted.
2322c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    expects.stats_ref.packet_loss_rate = 0;
2337d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org    expects.stats_ref.expand_rate = expects.stats_ref.speech_expand_rate = 0;
2342c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    expects.stats_ref.secondary_decoded_rate = 2006;
2352c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org    RunTest(50, expects);
2362c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  }
2372c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
2387d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org  void NoiseExpansionTest() {
2397d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org    NetEqNetworkStatsCheck expects = {
2407d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      IGNORE,  // current_buffer_size_ms
2417d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      IGNORE,  // preferred_buffer_size_ms
2427d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      IGNORE,  // jitter_peaks_found
2437d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      EQUAL,  // packet_loss_rate
2447d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      EQUAL,  // packet_discard_rate
2457d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      EQUAL,  // expand_rate
2467d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      EQUAL,  // speech_expand_rate
2477d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      IGNORE,  // preemptive_rate
2487d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      EQUAL,  // accelerate_rate
2497d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      EQUAL,  // decoded_fec_rate
2507d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      IGNORE,  // clockdrift_ppm
2517d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      EQUAL,  // added_zero_samples
2527d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
2537d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org    };
2547d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org    RunTest(50, expects);
2557d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org
2567d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org    SetPacketLossRate(1);
2577d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org    expects.stats_ref.expand_rate = 16384;
2587d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org    expects.stats_ref.speech_expand_rate = 5324;
2597d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org    RunTest(10, expects);  // Lost 10 * 20ms in a row.
2607d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org  }
2617d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org
2622c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org private:
2638967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg  MockAudioDecoder* external_decoder_;
2642c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  const int samples_per_ms_;
2652c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  const size_t frame_size_samples_;
26600b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<test::RtpGenerator> rtp_generator_;
2672c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  WebRtcRTPHeader rtp_header_;
2682c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  uint32_t last_lost_time_;
2692c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  uint32_t packet_loss_interval_;
2702c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  uint8_t payload_[kPayloadSizeByte];
2712c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  int16_t output_[kMaxOutputSize];
2722c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org};
2732c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
2748967183bf79322c5cb3cbd99e9b7aa298228d0a2kwibergTEST(NetEqNetworkStatsTest, DecodeFec) {
2758967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg  MockAudioDecoder decoder(1);
276ee1879ca40ffe4af9bb9613e03eacc5c2c4881fckwiberg  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, &decoder);
2772c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  test.DecodeFecTest();
2782c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  EXPECT_CALL(decoder, Die()).Times(1);
2792c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org}
2802c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
2818967183bf79322c5cb3cbd99e9b7aa298228d0a2kwibergTEST(NetEqNetworkStatsTest, StereoDecodeFec) {
2828967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg  MockAudioDecoder decoder(2);
283ee1879ca40ffe4af9bb9613e03eacc5c2c4881fckwiberg  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, &decoder);
2842c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  test.DecodeFecTest();
2852c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org  EXPECT_CALL(decoder, Die()).Times(1);
2862c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org}
2872c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
2887d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.orgTEST(NetEqNetworkStatsTest, NoiseExpansionTest) {
2898967183bf79322c5cb3cbd99e9b7aa298228d0a2kwiberg  MockAudioDecoder decoder(1);
290ee1879ca40ffe4af9bb9613e03eacc5c2c4881fckwiberg  NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, &decoder);
2917d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org  test.NoiseExpansionTest();
2927d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org  EXPECT_CALL(decoder, Die()).Times(1);
2937d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org}
2947d721eea14341db4a75660b4fc42617b65960301minyue@webrtc.org
2952c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org}  // namespace test
2962c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org}  // namespace webrtc
2972c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
2982c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
2992c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
3002c1bcf2cb4a9e19a337e52fd576242e04168d5e9minyue@webrtc.org
301