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/neteq/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
CodecsEqual(const CodecInst & codec_a,const CodecInst & codec_b)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:
AcmReceiverTest()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
~AcmReceiverTest()55 ~AcmReceiverTest() {}
56
SetUp()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
TearDown()78 void TearDown() {
79 }
80
InsertOnePacketOfSilence(int codec_id)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(¤t_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.
AddSetOfCodecs(const int * id)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
SendData(FrameType frame_type,uint8_t payload_type,uint32_t timestamp,const uint8_t * payload_data,uint16_t payload_len_bytes,const RTPFragmentationHeader * fragmentation)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
TEST_F(AcmReceiverTest,DISABLED_ON_ANDROID (AddCodecGetCodec))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
TEST_F(AcmReceiverTest,DISABLED_ON_ANDROID (AddCodecChangePayloadType))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
TEST_F(AcmReceiverTest,DISABLED_ON_ANDROID (AddCodecRemoveCodec))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
TEST_F(AcmReceiverTest,DISABLED_ON_ANDROID (SampleRate))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.
TEST_F(AcmReceiverTest,DISABLED_ON_ANDROID (PlayoutModeAndBackgroundNoiseMode))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
TEST_F(AcmReceiverTest,DISABLED_ON_ANDROID (PostdecodingVad))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
TEST_F(AcmReceiverTest,DISABLED_ON_ANDROID (LastAudioCodec))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
380