712eeb268772e6ce56c3fafd01352cc81b30d41f
[platform/framework/web/crosswalk.git] / src / third_party / webrtc / modules / audio_coding / main / acm2 / acm_receiver_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 #include "webrtc/modules/audio_coding/main/acm2/acm_receiver.h"
12
13 #include <algorithm>  // std::min
14
15 #include "gtest/gtest.h"
16 #include "webrtc/modules/audio_coding/main/interface/audio_coding_module.h"
17 #include "webrtc/modules/audio_coding/main/acm2/audio_coding_module_impl.h"
18 #include "webrtc/modules/audio_coding/main/acm2/acm_codec_database.h"
19 #include "webrtc/modules/audio_coding/neteq4/tools/rtp_generator.h"
20 #include "webrtc/system_wrappers/interface/scoped_ptr.h"
21 #include "webrtc/test/test_suite.h"
22 #include "webrtc/test/testsupport/fileutils.h"
23 #include "webrtc/test/testsupport/gtest_disable.h"
24
25 namespace webrtc {
26
27 namespace acm2 {
28 namespace {
29
30 bool CodecsEqual(const CodecInst& codec_a, const CodecInst& codec_b) {
31     if (strcmp(codec_a.plname, codec_b.plname) != 0 ||
32         codec_a.plfreq != codec_b.plfreq ||
33         codec_a.pltype != codec_b.pltype ||
34         codec_b.channels != codec_a.channels)
35       return false;
36     return true;
37 }
38
39 }  // namespace
40
41 class AcmReceiverTest : public AudioPacketizationCallback,
42                         public ::testing::Test {
43  protected:
44   AcmReceiverTest()
45       : receiver_(new AcmReceiver),
46         acm_(new AudioCodingModuleImpl(0)),
47         timestamp_(0),
48         packet_sent_(false),
49         last_packet_send_timestamp_(timestamp_),
50         last_frame_type_(kFrameEmpty) {}
51
52   ~AcmReceiverTest() {}
53
54   void SetUp() {
55     ASSERT_TRUE(receiver_.get() != NULL);
56     ASSERT_TRUE(acm_.get() != NULL);
57     for (int n = 0; n < ACMCodecDB::kNumCodecs; n++) {
58       ASSERT_EQ(0, ACMCodecDB::Codec(n, &codecs_[n]));
59     }
60
61     acm_->InitializeReceiver();
62     acm_->InitializeSender();
63     acm_->RegisterTransportCallback(this);
64
65     rtp_header_.header.sequenceNumber = 0;
66     rtp_header_.header.timestamp = 0;
67     rtp_header_.header.markerBit = false;
68     rtp_header_.header.ssrc = 0x12345678;  // Arbitrary.
69     rtp_header_.header.numCSRCs = 0;
70     rtp_header_.header.payloadType = 0;
71     rtp_header_.frameType = kAudioFrameSpeech;
72     rtp_header_.type.Audio.isCNG = false;
73   }
74
75   void TearDown() {
76   }
77
78   void InsertOnePacketOfSilence(int codec_id) {
79     CodecInst codec;
80     ACMCodecDB::Codec(codec_id, &codec);
81     if (timestamp_ == 0) {  // This is the first time inserting audio.
82       ASSERT_EQ(0, acm_->RegisterSendCodec(codec));
83     } else {
84       CodecInst current_codec;
85       ASSERT_EQ(0, acm_->SendCodec(&current_codec));
86       if (!CodecsEqual(codec, current_codec))
87         ASSERT_EQ(0, acm_->RegisterSendCodec(codec));
88     }
89     AudioFrame frame;
90     // Frame setup according to the codec.
91     frame.sample_rate_hz_ = codec.plfreq;
92     frame.samples_per_channel_ = codec.plfreq / 100;  // 10 ms.
93     frame.num_channels_ = codec.channels;
94     memset(frame.data_, 0, frame.samples_per_channel_ * frame.num_channels_ *
95            sizeof(int16_t));
96     int num_bytes = 0;
97     packet_sent_ = false;
98     last_packet_send_timestamp_ = timestamp_;
99     while (num_bytes == 0) {
100       frame.timestamp_ = timestamp_;
101       timestamp_ += frame.samples_per_channel_;
102       ASSERT_EQ(0, acm_->Add10MsData(frame));
103       num_bytes = acm_->Process();
104       ASSERT_GE(num_bytes, 0);
105     }
106     ASSERT_TRUE(packet_sent_);  // Sanity check.
107   }
108
109   // Last element of id should be negative.
110   void AddSetOfCodecs(const int* id) {
111     int n = 0;
112     while (id[n] >= 0) {
113       ASSERT_EQ(0, receiver_->AddCodec(id[n], codecs_[id[n]].pltype,
114                                        codecs_[id[n]].channels, NULL));
115       ++n;
116     }
117   }
118
119   virtual int SendData(
120       FrameType frame_type,
121       uint8_t payload_type,
122       uint32_t timestamp,
123       const uint8_t* payload_data,
124       uint16_t payload_len_bytes,
125       const RTPFragmentationHeader* fragmentation) {
126     if (frame_type == kFrameEmpty)
127       return 0;
128
129     rtp_header_.header.payloadType = payload_type;
130     rtp_header_.frameType = frame_type;
131     if (frame_type == kAudioFrameSpeech)
132       rtp_header_.type.Audio.isCNG = false;
133     else
134       rtp_header_.type.Audio.isCNG = true;
135     rtp_header_.header.timestamp = timestamp;
136
137     int ret_val = receiver_->InsertPacket(rtp_header_, payload_data,
138                                           payload_len_bytes);
139     if (ret_val < 0) {
140       assert(false);
141       return -1;
142     }
143     rtp_header_.header.sequenceNumber++;
144     packet_sent_ = true;
145     last_frame_type_ = frame_type;
146     return 0;
147   }
148
149   scoped_ptr<AcmReceiver> receiver_;
150   CodecInst codecs_[ACMCodecDB::kMaxNumCodecs];
151   scoped_ptr<AudioCodingModule> acm_;
152   WebRtcRTPHeader rtp_header_;
153   uint32_t timestamp_;
154   bool packet_sent_;  // Set when SendData is called reset when inserting audio.
155   uint32_t last_packet_send_timestamp_;
156   FrameType last_frame_type_;
157 };
158
159 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecGetCodec)) {
160   // Add codec.
161   for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) {
162     if (n & 0x1)  // Just add codecs with odd index.
163       EXPECT_EQ(0, receiver_->AddCodec(n, codecs_[n].pltype,
164                                        codecs_[n].channels, NULL));
165   }
166   // Get codec and compare.
167   for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) {
168     CodecInst my_codec;
169     if (n & 0x1) {
170       // Codecs with odd index should match the reference.
171       EXPECT_EQ(0, receiver_->DecoderByPayloadType(codecs_[n].pltype,
172                                                    &my_codec));
173       EXPECT_TRUE(CodecsEqual(codecs_[n], my_codec));
174     } else {
175       // Codecs with even index are not registered.
176       EXPECT_EQ(-1, receiver_->DecoderByPayloadType(codecs_[n].pltype,
177                                                     &my_codec));
178     }
179   }
180 }
181
182 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecChangePayloadType)) {
183   CodecInst ref_codec;
184   const int codec_id = ACMCodecDB::kPCMA;
185   EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &ref_codec));
186   const int payload_type = ref_codec.pltype;
187   EXPECT_EQ(0, receiver_->AddCodec(codec_id, ref_codec.pltype,
188                                    ref_codec.channels, NULL));
189   CodecInst test_codec;
190   EXPECT_EQ(0, receiver_->DecoderByPayloadType(payload_type, &test_codec));
191   EXPECT_EQ(true, CodecsEqual(ref_codec, test_codec));
192
193   // Re-register the same codec with different payload.
194   ref_codec.pltype = payload_type + 1;
195   EXPECT_EQ(0, receiver_->AddCodec(codec_id, ref_codec.pltype,
196                                    ref_codec.channels, NULL));
197
198   // Payload type |payload_type| should not exist.
199   EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &test_codec));
200
201   // Payload type |payload_type + 1| should exist.
202   EXPECT_EQ(0, receiver_->DecoderByPayloadType(payload_type + 1, &test_codec));
203   EXPECT_TRUE(CodecsEqual(test_codec, ref_codec));
204 }
205
206 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecRemoveCodec)) {
207   CodecInst codec;
208   const int codec_id = ACMCodecDB::kPCMA;
209   EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &codec));
210   const int payload_type = codec.pltype;
211   EXPECT_EQ(0, receiver_->AddCodec(codec_id, codec.pltype,
212                                    codec.channels, NULL));
213
214   // Remove non-existing codec should not fail. ACM1 legacy.
215   EXPECT_EQ(0, receiver_->RemoveCodec(payload_type + 1));
216
217   // Remove an existing codec.
218   EXPECT_EQ(0, receiver_->RemoveCodec(payload_type));
219
220   // Ask for the removed codec, must fail.
221   EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &codec));
222 }
223
224 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(SampleRate)) {
225   const int kCodecId[] = {
226       ACMCodecDB::kISAC, ACMCodecDB::kISACSWB, ACMCodecDB::kISACFB,
227       -1  // Terminator.
228   };
229   AddSetOfCodecs(kCodecId);
230
231   AudioFrame frame;
232   const int kOutSampleRateHz = 8000;  // Different than codec sample rate.
233   int n = 0;
234   while (kCodecId[n] >= 0) {
235     const int num_10ms_frames = codecs_[kCodecId[n]].pacsize /
236         (codecs_[kCodecId[n]].plfreq / 100);
237     InsertOnePacketOfSilence(kCodecId[n]);
238     for (int k = 0; k < num_10ms_frames; ++k) {
239       EXPECT_EQ(0, receiver_->GetAudio(kOutSampleRateHz, &frame));
240     }
241     EXPECT_EQ(std::min(32000, codecs_[kCodecId[n]].plfreq),
242               receiver_->current_sample_rate_hz());
243     ++n;
244   }
245 }
246
247 // Changing playout mode to FAX should not change the background noise mode.
248 TEST_F(AcmReceiverTest,
249        DISABLED_ON_ANDROID(PlayoutModeAndBackgroundNoiseMode)) {
250   EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest());  // Default
251
252   receiver_->SetPlayoutMode(voice);
253   EXPECT_EQ(voice, receiver_->PlayoutMode());
254   EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest());
255
256   receiver_->SetPlayoutMode(streaming);
257   EXPECT_EQ(streaming, receiver_->PlayoutMode());
258   EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest());
259
260   receiver_->SetPlayoutMode(fax);
261   EXPECT_EQ(fax, receiver_->PlayoutMode());
262   EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest());
263
264   receiver_->SetPlayoutMode(off);
265   EXPECT_EQ(off, receiver_->PlayoutMode());
266   EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest());
267
268   // Change to voice then to FAX.
269   receiver_->SetPlayoutMode(voice);
270   EXPECT_EQ(voice, receiver_->PlayoutMode());
271   EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest());
272   receiver_->SetPlayoutMode(fax);
273   EXPECT_EQ(fax, receiver_->PlayoutMode());
274   EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest());
275 }
276
277 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(PostdecodingVad)) {
278   receiver_->EnableVad();
279   EXPECT_TRUE(receiver_->vad_enabled());
280
281   const int id = ACMCodecDB::kPCM16Bwb;
282   ASSERT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels,
283                                    NULL));
284   const int kNumPackets = 5;
285   const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100);
286   AudioFrame frame;
287   for (int n = 0; n < kNumPackets; ++n) {
288     InsertOnePacketOfSilence(id);
289     for (int k = 0; k < num_10ms_frames; ++k)
290       ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
291   }
292   EXPECT_EQ(AudioFrame::kVadPassive, frame.vad_activity_);
293
294   receiver_->DisableVad();
295   EXPECT_FALSE(receiver_->vad_enabled());
296
297   for (int n = 0; n < kNumPackets; ++n) {
298     InsertOnePacketOfSilence(id);
299     for (int k = 0; k < num_10ms_frames; ++k)
300       ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
301   }
302   EXPECT_EQ(AudioFrame::kVadUnknown, frame.vad_activity_);
303 }
304
305 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(FlushBuffer)) {
306   const int id = ACMCodecDB::kISAC;
307   EXPECT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels,
308                                    NULL));
309   const int kNumPackets = 5;
310   const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100);
311   for (int n = 0; n < kNumPackets; ++n)
312      InsertOnePacketOfSilence(id);
313   ACMNetworkStatistics statistics;
314   receiver_->NetworkStatistics(&statistics);
315   ASSERT_EQ(num_10ms_frames * kNumPackets * 10, statistics.currentBufferSize);
316
317   receiver_->FlushBuffers();
318   receiver_->NetworkStatistics(&statistics);
319   ASSERT_EQ(0, statistics.currentBufferSize);
320 }
321
322 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(PlayoutTimestamp)) {
323   const int id = ACMCodecDB::kPCM16Bwb;
324   EXPECT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels,
325                                    NULL));
326   receiver_->SetPlayoutMode(fax);
327   const int kNumPackets = 5;
328   const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100);
329   uint32_t expected_timestamp;
330   AudioFrame frame;
331   int ts_offset = 0;
332   bool first_audio_frame = true;
333   for (int n = 0; n < kNumPackets; ++n) {
334     packet_sent_ = false;
335     InsertOnePacketOfSilence(id);
336     ASSERT_TRUE(packet_sent_);
337     expected_timestamp = last_packet_send_timestamp_;
338     for (int k = 0; k < num_10ms_frames; ++k) {
339       ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame));
340       if (first_audio_frame) {
341         // There is an offset in playout timestamps. Perhaps, it is related to
342         // initial delay that NetEq applies
343         ts_offset =  receiver_->PlayoutTimestamp() - expected_timestamp;
344         first_audio_frame = false;
345       } else {
346         EXPECT_EQ(expected_timestamp + ts_offset,
347                   receiver_->PlayoutTimestamp());
348       }
349       expected_timestamp += codecs_[id].plfreq / 100;  // Increment by 10 ms.
350     }
351   }
352 }
353
354 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(LastAudioCodec)) {
355   const int kCodecId[] = {
356       ACMCodecDB::kISAC, ACMCodecDB::kPCMA, ACMCodecDB::kISACSWB,
357       ACMCodecDB::kPCM16Bswb32kHz, ACMCodecDB::kG722_1C_48,
358       -1  // Terminator.
359   };
360   AddSetOfCodecs(kCodecId);
361
362   const int kCngId[] = {  // Not including full-band.
363       ACMCodecDB::kCNNB, ACMCodecDB::kCNWB, ACMCodecDB::kCNSWB,
364       -1  // Terminator.
365   };
366   AddSetOfCodecs(kCngId);
367
368   // Register CNG at sender side.
369   int n = 0;
370   while (kCngId[n] > 0) {
371     ASSERT_EQ(0, acm_->RegisterSendCodec(codecs_[kCngId[n]]));
372     ++n;
373   }
374
375   CodecInst codec;
376   // No audio payload is received.
377   EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
378
379   // Start with sending DTX.
380   ASSERT_EQ(0, acm_->SetVAD(true, true, VADVeryAggr));
381   packet_sent_ = false;
382   InsertOnePacketOfSilence(kCodecId[0]);  // Enough to test with one codec.
383   ASSERT_TRUE(packet_sent_);
384   EXPECT_EQ(kAudioFrameCN, last_frame_type_);
385
386   // Has received, only, DTX. Last Audio codec is undefined.
387   EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
388   EXPECT_EQ(-1, receiver_->last_audio_codec_id());
389   EXPECT_EQ(-1, receiver_->last_audio_payload_type());
390
391   n = 0;
392   while (kCodecId[n] >= 0) {  // Loop over codecs.
393     // Set DTX off to send audio payload.
394     acm_->SetVAD(false, false, VADAggr);
395     packet_sent_ = false;
396     InsertOnePacketOfSilence(kCodecId[n]);
397
398     // Sanity check if Actually an audio payload received, and it should be
399     // of type "speech."
400     ASSERT_TRUE(packet_sent_);
401     ASSERT_EQ(kAudioFrameSpeech, last_frame_type_);
402     EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
403
404     // Set VAD on to send DTX. Then check if the "Last Audio codec" returns
405     // the expected codec.
406     acm_->SetVAD(true, true, VADAggr);
407
408     // Do as many encoding until a DTX is sent.
409     while (last_frame_type_ != kAudioFrameCN) {
410       packet_sent_ = false;
411       InsertOnePacketOfSilence(kCodecId[n]);
412       ASSERT_TRUE(packet_sent_);
413     }
414     EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
415     EXPECT_EQ(codecs_[kCodecId[n]].pltype,
416               receiver_->last_audio_payload_type());
417     EXPECT_EQ(0, receiver_->LastAudioCodec(&codec));
418     EXPECT_TRUE(CodecsEqual(codecs_[kCodecId[n]], codec));
419     ++n;
420   }
421 }
422
423 }  // namespace acm2
424
425 }  // namespace webrtc