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
MockAudioDecoder(size_t num_channels)27 explicit MockAudioDecoder(size_t num_channels)
28 : num_channels_(num_channels), fec_enabled_(false) {
29 }
~MockAudioDecoder()30 ~MockAudioDecoder() override { Die(); }
31 MOCK_METHOD0(Die, void());
32
33 MOCK_METHOD0(Reset, void());
34
PacketDuration(const uint8_t * encoded,size_t encoded_len) const35 int PacketDuration(const uint8_t* encoded,
36 size_t encoded_len) const override {
37 return kPacketDuration;
38 }
39
PacketDurationRedundant(const uint8_t * encoded,size_t encoded_len) const40 int PacketDurationRedundant(const uint8_t* encoded,
41 size_t encoded_len) const override {
42 return kPacketDuration;
43 }
44
PacketHasFec(const uint8_t * encoded,size_t encoded_len) const45 bool PacketHasFec(const uint8_t* encoded, size_t encoded_len) const override {
46 return fec_enabled_;
47 }
48
Channels() const49 size_t Channels() const override { return num_channels_; }
50
set_fec_enabled(bool enable_fec)51 void set_fec_enabled(bool enable_fec) { fec_enabled_ = enable_fec; }
52
fec_enabled() const53 bool fec_enabled() const { return fec_enabled_; }
54
55 protected:
56 // Override the following methods such that no actual payload is needed.
DecodeInternal(const uint8_t * encoded,size_t encoded_len,int,int16_t * decoded,SpeechType * speech_type)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
DecodeRedundantInternal(const uint8_t * encoded,size_t encoded_len,int sample_rate_hz,int16_t * decoded,SpeechType * speech_type)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
NetEqNetworkStatsTest(NetEqDecoder codec,MockAudioDecoder * decoder)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
Lost(uint32_t send_time)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
SetPacketLossRate(double loss_rate)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|
CheckNetworkStatistics(NetEqNetworkStatsCheck expects)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
RunTest(int num_loops,NetEqNetworkStatsCheck expects)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
DecodeFecTest()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
NoiseExpansionTest()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
TEST(NetEqNetworkStatsTest,DecodeFec)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
TEST(NetEqNetworkStatsTest,StereoDecodeFec)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
TEST(NetEqNetworkStatsTest,NoiseExpansionTest)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