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