6a8eafa106cf86f7de940da6186ba369f2aad333
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / neteq / neteq_external_decoder_unittest.cc
1 /*
2  *  Copyright (c) 2013 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 // Test to verify correct operation for externally created decoders.
12
13 #include <string>
14 #include <list>
15
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "webrtc/modules/audio_coding/neteq/interface/neteq.h"
19 #include "webrtc/modules/audio_coding/neteq/mock/mock_external_decoder_pcm16b.h"
20 #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
21 #include "webrtc/modules/audio_coding/neteq/tools/rtp_generator.h"
22 #include "webrtc/system_wrappers/interface/compile_assert.h"
23 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
24 #include "webrtc/test/testsupport/fileutils.h"
25 #include "webrtc/test/testsupport/gtest_disable.h"
26
27 namespace webrtc {
28
29 using ::testing::_;
30 using ::testing::Return;
31
32 // This test encodes a few packets of PCM16b 32 kHz data and inserts it into two
33 // different NetEq instances. The first instance uses the internal version of
34 // the decoder object, while the second one uses an externally created decoder
35 // object (ExternalPcm16B wrapped in MockExternalPcm16B, both defined above).
36 // The test verifies that the output from both instances match.
37 class NetEqExternalDecoderTest : public ::testing::Test {
38  protected:
39   static const int kTimeStepMs = 10;
40   static const int kMaxBlockSize = 480;  // 10 ms @ 48 kHz.
41   static const uint8_t kPayloadType = 95;
42   static const int kSampleRateHz = 32000;
43
44   NetEqExternalDecoderTest()
45       : sample_rate_hz_(kSampleRateHz),
46         samples_per_ms_(sample_rate_hz_ / 1000),
47         frame_size_ms_(10),
48         frame_size_samples_(frame_size_ms_ * samples_per_ms_),
49         output_size_samples_(frame_size_ms_ * samples_per_ms_),
50         external_decoder_(new MockExternalPcm16B(kDecoderPCM16Bswb32kHz)),
51         rtp_generator_(new test::RtpGenerator(samples_per_ms_)),
52         payload_size_bytes_(0),
53         last_send_time_(0),
54         last_arrival_time_(0) {
55     config_.sample_rate_hz = sample_rate_hz_;
56     neteq_external_ = NetEq::Create(config_);
57     neteq_ = NetEq::Create(config_);
58     input_ = new int16_t[frame_size_samples_];
59     encoded_ = new uint8_t[2 * frame_size_samples_];
60   }
61
62   ~NetEqExternalDecoderTest() {
63     delete neteq_external_;
64     delete neteq_;
65     // We will now delete the decoder ourselves, so expecting Die to be called.
66     EXPECT_CALL(*external_decoder_, Die()).Times(1);
67     delete [] input_;
68     delete [] encoded_;
69   }
70
71   virtual void SetUp() {
72     const std::string file_name =
73         webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
74     input_file_.reset(new test::InputAudioFile(file_name));
75     assert(sample_rate_hz_ == 32000);
76     NetEqDecoder decoder = kDecoderPCM16Bswb32kHz;
77     EXPECT_CALL(*external_decoder_, Init());
78     // NetEq is not allowed to delete the external decoder (hence Times(0)).
79     EXPECT_CALL(*external_decoder_, Die()).Times(0);
80     ASSERT_EQ(NetEq::kOK,
81               neteq_external_->RegisterExternalDecoder(
82                   external_decoder_.get(), decoder, kPayloadType));
83     ASSERT_EQ(NetEq::kOK,
84               neteq_->RegisterPayloadType(decoder, kPayloadType));
85   }
86
87   virtual void TearDown() {}
88
89   int GetNewPackets() {
90     if (!input_file_->Read(frame_size_samples_, input_)) {
91       return -1;
92     }
93     payload_size_bytes_ = WebRtcPcm16b_Encode(input_, frame_size_samples_,
94                                              encoded_);
95     if (frame_size_samples_ * 2 != payload_size_bytes_) {
96       return -1;
97     }
98     int next_send_time = rtp_generator_->GetRtpHeader(
99         kPayloadType, frame_size_samples_, &rtp_header_);
100     return next_send_time;
101   }
102
103   virtual void VerifyOutput(size_t num_samples) const {
104     for (size_t i = 0; i < num_samples; ++i) {
105       ASSERT_EQ(output_[i], output_external_[i]) <<
106           "Diff in sample " << i << ".";
107     }
108   }
109
110   virtual int GetArrivalTime(int send_time) {
111     int arrival_time = last_arrival_time_ + (send_time - last_send_time_);
112     last_send_time_ = send_time;
113     last_arrival_time_ = arrival_time;
114     return arrival_time;
115   }
116
117   virtual bool Lost() { return false; }
118
119   virtual void InsertPackets(int next_arrival_time) {
120     // Insert packet in regular instance.
121     ASSERT_EQ(
122         NetEq::kOK,
123         neteq_->InsertPacket(
124             rtp_header_, encoded_, payload_size_bytes_, next_arrival_time));
125     // Insert packet in external decoder instance.
126     EXPECT_CALL(*external_decoder_,
127                 IncomingPacket(_,
128                                payload_size_bytes_,
129                                rtp_header_.header.sequenceNumber,
130                                rtp_header_.header.timestamp,
131                                next_arrival_time));
132     ASSERT_EQ(
133         NetEq::kOK,
134         neteq_external_->InsertPacket(
135             rtp_header_, encoded_, payload_size_bytes_, next_arrival_time));
136   }
137
138   virtual void GetOutputAudio() {
139     NetEqOutputType output_type;
140     // Get audio from regular instance.
141     int samples_per_channel;
142     int num_channels;
143     EXPECT_EQ(NetEq::kOK,
144               neteq_->GetAudio(kMaxBlockSize,
145                                output_,
146                                &samples_per_channel,
147                                &num_channels,
148                                &output_type));
149     EXPECT_EQ(1, num_channels);
150     EXPECT_EQ(output_size_samples_, samples_per_channel);
151     // Get audio from external decoder instance.
152     ASSERT_EQ(NetEq::kOK,
153               neteq_external_->GetAudio(kMaxBlockSize,
154                                         output_external_,
155                                         &samples_per_channel,
156                                         &num_channels,
157                                         &output_type));
158     EXPECT_EQ(1, num_channels);
159     EXPECT_EQ(output_size_samples_, samples_per_channel);
160   }
161
162   virtual int NumExpectedDecodeCalls(int num_loops) const { return num_loops; }
163
164   void RunTest(int num_loops) {
165     // Get next input packets (mono and multi-channel).
166     int next_send_time;
167     int next_arrival_time;
168     do {
169       next_send_time = GetNewPackets();
170       ASSERT_NE(-1, next_send_time);
171       next_arrival_time = GetArrivalTime(next_send_time);
172     } while (Lost());  // If lost, immediately read the next packet.
173
174     EXPECT_CALL(*external_decoder_, Decode(_, payload_size_bytes_, _, _))
175         .Times(NumExpectedDecodeCalls(num_loops));
176
177     int time_now = 0;
178     for (int k = 0; k < num_loops; ++k) {
179       while (time_now >= next_arrival_time) {
180         InsertPackets(next_arrival_time);
181
182         // Get next input packet.
183         do {
184           next_send_time = GetNewPackets();
185           ASSERT_NE(-1, next_send_time);
186           next_arrival_time = GetArrivalTime(next_send_time);
187         } while (Lost());  // If lost, immediately read the next packet.
188       }
189
190       GetOutputAudio();
191
192       std::ostringstream ss;
193       ss << "Lap number " << k << ".";
194       SCOPED_TRACE(ss.str());  // Print out the parameter values on failure.
195       // Compare mono and multi-channel.
196       ASSERT_NO_FATAL_FAILURE(VerifyOutput(output_size_samples_));
197
198       time_now += kTimeStepMs;
199     }
200   }
201
202   NetEq::Config config_;
203   int sample_rate_hz_;
204   int samples_per_ms_;
205   const int frame_size_ms_;
206   int frame_size_samples_;
207   int output_size_samples_;
208   NetEq* neteq_external_;
209   NetEq* neteq_;
210   scoped_ptr<MockExternalPcm16B> external_decoder_;
211   scoped_ptr<test::RtpGenerator> rtp_generator_;
212   int16_t* input_;
213   uint8_t* encoded_;
214   int16_t output_[kMaxBlockSize];
215   int16_t output_external_[kMaxBlockSize];
216   WebRtcRTPHeader rtp_header_;
217   int payload_size_bytes_;
218   int last_send_time_;
219   int last_arrival_time_;
220   scoped_ptr<test::InputAudioFile> input_file_;
221 };
222
223 TEST_F(NetEqExternalDecoderTest, RunTest) {
224   RunTest(100);  // Run 100 laps @ 10 ms each in the test loop.
225 }
226
227 class LargeTimestampJumpTest : public NetEqExternalDecoderTest {
228  protected:
229   enum TestStates {
230     kInitialPhase,
231     kNormalPhase,
232     kExpandPhase,
233     kFadedExpandPhase,
234     kRecovered
235   };
236
237   LargeTimestampJumpTest()
238       : NetEqExternalDecoderTest(), test_state_(kInitialPhase) {
239     sample_rate_hz_ = 8000;
240     samples_per_ms_ = sample_rate_hz_ / 1000;
241     frame_size_samples_ = frame_size_ms_ * samples_per_ms_;
242     output_size_samples_ = frame_size_ms_ * samples_per_ms_;
243     EXPECT_CALL(*external_decoder_, Die()).Times(1);
244     external_decoder_.reset(new MockExternalPcm16B(kDecoderPCM16B));
245   }
246
247   void SetUp() OVERRIDE {
248     const std::string file_name =
249         webrtc::test::ResourcePath("audio_coding/testfile32kHz", "pcm");
250     input_file_.reset(new test::InputAudioFile(file_name));
251     assert(sample_rate_hz_ == 8000);
252     NetEqDecoder decoder = kDecoderPCM16B;
253     EXPECT_CALL(*external_decoder_, Init());
254     EXPECT_CALL(*external_decoder_, HasDecodePlc())
255         .WillRepeatedly(Return(false));
256     // NetEq is not allowed to delete the external decoder (hence Times(0)).
257     EXPECT_CALL(*external_decoder_, Die()).Times(0);
258     ASSERT_EQ(NetEq::kOK,
259               neteq_external_->RegisterExternalDecoder(
260                   external_decoder_.get(), decoder, kPayloadType));
261     ASSERT_EQ(NetEq::kOK, neteq_->RegisterPayloadType(decoder, kPayloadType));
262   }
263
264   void InsertPackets(int next_arrival_time) OVERRIDE {
265     // Insert packet in external decoder instance.
266     EXPECT_CALL(*external_decoder_,
267                 IncomingPacket(_,
268                                payload_size_bytes_,
269                                rtp_header_.header.sequenceNumber,
270                                rtp_header_.header.timestamp,
271                                next_arrival_time));
272     ASSERT_EQ(
273         NetEq::kOK,
274         neteq_external_->InsertPacket(
275             rtp_header_, encoded_, payload_size_bytes_, next_arrival_time));
276   }
277
278   void GetOutputAudio() OVERRIDE {
279     NetEqOutputType output_type;
280     int samples_per_channel;
281     int num_channels;
282     // Get audio from external decoder instance.
283     ASSERT_EQ(NetEq::kOK,
284               neteq_external_->GetAudio(kMaxBlockSize,
285                                         output_external_,
286                                         &samples_per_channel,
287                                         &num_channels,
288                                         &output_type));
289     EXPECT_EQ(1, num_channels);
290     EXPECT_EQ(output_size_samples_, samples_per_channel);
291     UpdateState(output_type);
292   }
293
294   virtual void UpdateState(NetEqOutputType output_type) {
295     switch (test_state_) {
296       case kInitialPhase: {
297         if (output_type == kOutputNormal) {
298           test_state_ = kNormalPhase;
299         }
300         break;
301       }
302       case kNormalPhase: {
303         if (output_type == kOutputPLC) {
304           test_state_ = kExpandPhase;
305         }
306         break;
307       }
308       case kExpandPhase: {
309         if (output_type == kOutputPLCtoCNG) {
310           test_state_ = kFadedExpandPhase;
311         }
312         break;
313       }
314       case kFadedExpandPhase: {
315         if (output_type == kOutputNormal) {
316           test_state_ = kRecovered;
317         }
318         break;
319       }
320       case kRecovered: {
321         break;
322       }
323     }
324   }
325
326   void VerifyOutput(size_t num_samples) const OVERRIDE {
327     if (test_state_ == kExpandPhase || test_state_ == kFadedExpandPhase) {
328       // Don't verify the output in this phase of the test.
329       return;
330     }
331     for (size_t i = 0; i < num_samples; ++i) {
332       if (output_external_[i] != 0)
333         return;
334     }
335     EXPECT_TRUE(false)
336         << "Expected at least one non-zero sample in each output block.";
337   }
338
339   int NumExpectedDecodeCalls(int num_loops) const OVERRIDE {
340     // Some packets won't be decoded because of the buffer being flushed after
341     // the timestamp jump.
342     return num_loops - (config_.max_packets_in_buffer + 1);
343   }
344
345   TestStates test_state_;
346 };
347
348 TEST_F(LargeTimestampJumpTest, JumpLongerThanHalfRange) {
349   // Set the timestamp series to start at 2880, increase to 7200, then jump to
350   // 2869342376. The sequence numbers start at 42076 and increase by 1 for each
351   // packet, also when the timestamp jumps.
352   static const uint16_t kStartSeqeunceNumber = 42076;
353   static const uint32_t kStartTimestamp = 2880;
354   static const uint32_t kJumpFromTimestamp = 7200;
355   static const uint32_t kJumpToTimestamp = 2869342376;
356   COMPILE_ASSERT(kJumpFromTimestamp < kJumpToTimestamp,
357                  timestamp_jump_should_not_result_in_wrap);
358   COMPILE_ASSERT(
359       static_cast<uint32_t>(kJumpToTimestamp - kJumpFromTimestamp) > 0x7FFFFFFF,
360       jump_should_be_larger_than_half_range);
361   // Replace the default RTP generator with one that jumps in timestamp.
362   rtp_generator_.reset(new test::TimestampJumpRtpGenerator(samples_per_ms_,
363                                                            kStartSeqeunceNumber,
364                                                            kStartTimestamp,
365                                                            kJumpFromTimestamp,
366                                                            kJumpToTimestamp));
367
368   RunTest(130);  // Run 130 laps @ 10 ms each in the test loop.
369   EXPECT_EQ(kRecovered, test_state_);
370 }
371
372 TEST_F(LargeTimestampJumpTest, JumpLongerThanHalfRangeAndWrap) {
373   // Make a jump larger than half the 32-bit timestamp range. Set the start
374   // timestamp such that the jump will result in a wrap around.
375   static const uint16_t kStartSeqeunceNumber = 42076;
376   // Set the jump length slightly larger than 2^31.
377   static const uint32_t kStartTimestamp = 3221223116;
378   static const uint32_t kJumpFromTimestamp = 3221223216;
379   static const uint32_t kJumpToTimestamp = 1073744278;
380   COMPILE_ASSERT(kJumpToTimestamp < kJumpFromTimestamp,
381                  timestamp_jump_should_result_in_wrap);
382   COMPILE_ASSERT(
383       static_cast<uint32_t>(kJumpToTimestamp - kJumpFromTimestamp) > 0x7FFFFFFF,
384       jump_should_be_larger_than_half_range);
385   // Replace the default RTP generator with one that jumps in timestamp.
386   rtp_generator_.reset(new test::TimestampJumpRtpGenerator(samples_per_ms_,
387                                                            kStartSeqeunceNumber,
388                                                            kStartTimestamp,
389                                                            kJumpFromTimestamp,
390                                                            kJumpToTimestamp));
391
392   RunTest(130);  // Run 130 laps @ 10 ms each in the test loop.
393   EXPECT_EQ(kRecovered, test_state_);
394 }
395
396 class ShortTimestampJumpTest : public LargeTimestampJumpTest {
397  protected:
398   void UpdateState(NetEqOutputType output_type) OVERRIDE {
399     switch (test_state_) {
400       case kInitialPhase: {
401         if (output_type == kOutputNormal) {
402           test_state_ = kNormalPhase;
403         }
404         break;
405       }
406       case kNormalPhase: {
407         if (output_type == kOutputPLC) {
408           test_state_ = kExpandPhase;
409         }
410         break;
411       }
412       case kExpandPhase: {
413         if (output_type == kOutputNormal) {
414           test_state_ = kRecovered;
415         }
416         break;
417       }
418       case kRecovered: {
419         break;
420       }
421       default: { FAIL(); }
422     }
423   }
424
425   int NumExpectedDecodeCalls(int num_loops) const OVERRIDE {
426     // Some packets won't be decoded because of the timestamp jump.
427     return num_loops - 2;
428   }
429 };
430
431 TEST_F(ShortTimestampJumpTest, JumpShorterThanHalfRange) {
432   // Make a jump shorter than half the 32-bit timestamp range. Set the start
433   // timestamp such that the jump will not result in a wrap around.
434   static const uint16_t kStartSeqeunceNumber = 42076;
435   // Set the jump length slightly smaller than 2^31.
436   static const uint32_t kStartTimestamp = 4711;
437   static const uint32_t kJumpFromTimestamp = 4811;
438   static const uint32_t kJumpToTimestamp = 2147483747;
439   COMPILE_ASSERT(kJumpFromTimestamp < kJumpToTimestamp,
440                  timestamp_jump_should_not_result_in_wrap);
441   COMPILE_ASSERT(
442       static_cast<uint32_t>(kJumpToTimestamp - kJumpFromTimestamp) < 0x7FFFFFFF,
443       jump_should_be_smaller_than_half_range);
444   // Replace the default RTP generator with one that jumps in timestamp.
445   rtp_generator_.reset(new test::TimestampJumpRtpGenerator(samples_per_ms_,
446                                                            kStartSeqeunceNumber,
447                                                            kStartTimestamp,
448                                                            kJumpFromTimestamp,
449                                                            kJumpToTimestamp));
450
451   RunTest(130);  // Run 130 laps @ 10 ms each in the test loop.
452   EXPECT_EQ(kRecovered, test_state_);
453 }
454
455 TEST_F(ShortTimestampJumpTest, JumpShorterThanHalfRangeAndWrap) {
456   // Make a jump shorter than half the 32-bit timestamp range. Set the start
457   // timestamp such that the jump will result in a wrap around.
458   static const uint16_t kStartSeqeunceNumber = 42076;
459   // Set the jump length slightly smaller than 2^31.
460   static const uint32_t kStartTimestamp = 3221227827;
461   static const uint32_t kJumpFromTimestamp = 3221227927;
462   static const uint32_t kJumpToTimestamp = 1073739567;
463   COMPILE_ASSERT(kJumpToTimestamp < kJumpFromTimestamp,
464                  timestamp_jump_should_result_in_wrap);
465   COMPILE_ASSERT(
466       static_cast<uint32_t>(kJumpToTimestamp - kJumpFromTimestamp) < 0x7FFFFFFF,
467       jump_should_be_smaller_than_half_range);
468   // Replace the default RTP generator with one that jumps in timestamp.
469   rtp_generator_.reset(new test::TimestampJumpRtpGenerator(samples_per_ms_,
470                                                            kStartSeqeunceNumber,
471                                                            kStartTimestamp,
472                                                            kJumpFromTimestamp,
473                                                            kJumpToTimestamp));
474
475   RunTest(130);  // Run 130 laps @ 10 ms each in the test loop.
476   EXPECT_EQ(kRecovered, test_state_);
477 }
478
479 }  // namespace webrtc