Home | History | Annotate | Download | only in neteq
      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 
     16 namespace webrtc {
     17 namespace test {
     18 
     19 using ::testing::_;
     20 using ::testing::SetArgPointee;
     21 using ::testing::Return;
     22 
     23 class 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 
     81 class 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 
     87 enum logic {
     88   IGNORE,
     89   EQUAL,
     90   SMALLER_THAN,
     91   LARGER_THAN,
     92 };
     93 
     94 struct 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 
    274 TEST(NetEqNetworkStatsTest, DecodeFec) {
    275   MockAudioDecoder decoder(1);
    276   NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, &decoder);
    277   test.DecodeFecTest();
    278   EXPECT_CALL(decoder, Die()).Times(1);
    279 }
    280 
    281 TEST(NetEqNetworkStatsTest, StereoDecodeFec) {
    282   MockAudioDecoder decoder(2);
    283   NetEqNetworkStatsTest test(NetEqDecoder::kDecoderOpus, &decoder);
    284   test.DecodeFecTest();
    285   EXPECT_CALL(decoder, Die()).Times(1);
    286 }
    287 
    288 TEST(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