Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / neteq4 / 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 "gmock/gmock.h"
17 #include "gtest/gtest.h"
18 #include "webrtc/modules/audio_coding/neteq4/interface/neteq.h"
19 #include "webrtc/modules/audio_coding/neteq4/mock/mock_external_decoder_pcm16b.h"
20 #include "webrtc/modules/audio_coding/neteq4/tools/input_audio_file.h"
21 #include "webrtc/modules/audio_coding/neteq4/tools/rtp_generator.h"
22 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
23 #include "webrtc/test/testsupport/fileutils.h"
24 #include "webrtc/test/testsupport/gtest_disable.h"
25
26 namespace webrtc {
27
28 using ::testing::_;
29
30 // This test encodes a few packets of PCM16b 32 kHz data and inserts it into two
31 // different NetEq instances. The first instance uses the internal version of
32 // the decoder object, while the second one uses an externally created decoder
33 // object (ExternalPcm16B wrapped in MockExternalPcm16B, both defined above).
34 // The test verifies that the output from both instances match.
35 class NetEqExternalDecoderTest : public ::testing::Test {
36  protected:
37   static const int kTimeStepMs = 10;
38   static const int kMaxBlockSize = 480;  // 10 ms @ 48 kHz.
39   static const uint8_t kPayloadType = 95;
40   static const int kSampleRateHz = 32000;
41
42   NetEqExternalDecoderTest()
43       : sample_rate_hz_(kSampleRateHz),
44         samples_per_ms_(sample_rate_hz_ / 1000),
45         frame_size_ms_(10),
46         frame_size_samples_(frame_size_ms_ * samples_per_ms_),
47         output_size_samples_(frame_size_ms_ * samples_per_ms_),
48         external_decoder_(new MockExternalPcm16B(kDecoderPCM16Bswb32kHz)),
49         rtp_generator_(samples_per_ms_),
50         payload_size_bytes_(0),
51         last_send_time_(0),
52         last_arrival_time_(0) {
53     NetEq::Config config;
54     config.sample_rate_hz = sample_rate_hz_;
55     neteq_external_ = NetEq::Create(config);
56     neteq_ = NetEq::Create(config);
57     input_ = new int16_t[frame_size_samples_];
58     encoded_ = new uint8_t[2 * frame_size_samples_];
59   }
60
61   ~NetEqExternalDecoderTest() {
62     delete neteq_external_;
63     delete neteq_;
64     // We will now delete the decoder ourselves, so expecting Die to be called.
65     EXPECT_CALL(*external_decoder_, Die()).Times(1);
66     delete external_decoder_;
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(external_decoder_,
82                                                        decoder,
83                                                        kPayloadType));
84     ASSERT_EQ(NetEq::kOK,
85               neteq_->RegisterPayloadType(decoder, kPayloadType));
86   }
87
88   virtual void TearDown() {}
89
90   int GetNewPackets() {
91     if (!input_file_->Read(frame_size_samples_, input_)) {
92       return -1;
93     }
94     payload_size_bytes_ = WebRtcPcm16b_Encode(input_, frame_size_samples_,
95                                              encoded_);
96     if (frame_size_samples_ * 2 != payload_size_bytes_) {
97       return -1;
98     }
99     int next_send_time = rtp_generator_.GetRtpHeader(kPayloadType,
100                                                      frame_size_samples_,
101                                                      &rtp_header_);
102     return next_send_time;
103   }
104
105   void VerifyOutput(size_t num_samples) {
106     for (size_t i = 0; i < num_samples; ++i) {
107       ASSERT_EQ(output_[i], output_external_[i]) <<
108           "Diff in sample " << i << ".";
109     }
110   }
111
112   virtual int GetArrivalTime(int send_time) {
113     int arrival_time = last_arrival_time_ + (send_time - last_send_time_);
114     last_send_time_ = send_time;
115     last_arrival_time_ = arrival_time;
116     return arrival_time;
117   }
118
119   virtual bool Lost() { return false; }
120
121   void RunTest(int num_loops) {
122     // Get next input packets (mono and multi-channel).
123     int next_send_time;
124     int next_arrival_time;
125     do {
126       next_send_time = GetNewPackets();
127       ASSERT_NE(-1, next_send_time);
128       next_arrival_time = GetArrivalTime(next_send_time);
129     } while (Lost());  // If lost, immediately read the next packet.
130
131     EXPECT_CALL(*external_decoder_, Decode(_, payload_size_bytes_, _, _))
132         .Times(num_loops);
133
134     int time_now = 0;
135     for (int k = 0; k < num_loops; ++k) {
136       while (time_now >= next_arrival_time) {
137         // Insert packet in regular instance.
138         ASSERT_EQ(NetEq::kOK,
139                   neteq_->InsertPacket(rtp_header_, encoded_,
140                                        payload_size_bytes_,
141                                        next_arrival_time));
142         // Insert packet in external decoder instance.
143         EXPECT_CALL(*external_decoder_,
144                     IncomingPacket(_, payload_size_bytes_,
145                                    rtp_header_.header.sequenceNumber,
146                                    rtp_header_.header.timestamp,
147                                    next_arrival_time));
148         ASSERT_EQ(NetEq::kOK,
149                   neteq_external_->InsertPacket(rtp_header_, encoded_,
150                                                 payload_size_bytes_,
151                                                 next_arrival_time));
152         // Get next input packet.
153         do {
154           next_send_time = GetNewPackets();
155           ASSERT_NE(-1, next_send_time);
156           next_arrival_time = GetArrivalTime(next_send_time);
157         } while (Lost());  // If lost, immediately read the next packet.
158       }
159       NetEqOutputType output_type;
160       // Get audio from regular instance.
161       int samples_per_channel;
162       int num_channels;
163       EXPECT_EQ(NetEq::kOK,
164                 neteq_->GetAudio(kMaxBlockSize, output_,
165                                  &samples_per_channel, &num_channels,
166                                  &output_type));
167       EXPECT_EQ(1, num_channels);
168       EXPECT_EQ(output_size_samples_, samples_per_channel);
169       // Get audio from external decoder instance.
170       ASSERT_EQ(NetEq::kOK,
171                 neteq_external_->GetAudio(kMaxBlockSize, output_external_,
172                                           &samples_per_channel, &num_channels,
173                                           &output_type));
174       EXPECT_EQ(1, num_channels);
175       EXPECT_EQ(output_size_samples_, samples_per_channel);
176       std::ostringstream ss;
177       ss << "Lap number " << k << ".";
178       SCOPED_TRACE(ss.str());  // Print out the parameter values on failure.
179       // Compare mono and multi-channel.
180       ASSERT_NO_FATAL_FAILURE(VerifyOutput(output_size_samples_));
181
182       time_now += kTimeStepMs;
183     }
184   }
185
186   const int sample_rate_hz_;
187   const int samples_per_ms_;
188   const int frame_size_ms_;
189   const int frame_size_samples_;
190   const int output_size_samples_;
191   NetEq* neteq_external_;
192   NetEq* neteq_;
193   MockExternalPcm16B* external_decoder_;
194   test::RtpGenerator rtp_generator_;
195   int16_t* input_;
196   uint8_t* encoded_;
197   int16_t output_[kMaxBlockSize];
198   int16_t output_external_[kMaxBlockSize];
199   WebRtcRTPHeader rtp_header_;
200   int payload_size_bytes_;
201   int last_send_time_;
202   int last_arrival_time_;
203   scoped_ptr<test::InputAudioFile> input_file_;
204 };
205
206 TEST_F(NetEqExternalDecoderTest, DISABLED_ON_ANDROID(RunTest)) {
207   RunTest(100);  // Run 100 laps @ 10 ms each in the test loop.
208 }
209
210 }  // namespace webrtc