2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/audio_coding/main/acm2/acm_receiver.h"
13 #include <algorithm> // std::min
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"
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)
41 class AcmReceiverTest : public AudioPacketizationCallback,
42 public ::testing::Test {
45 : receiver_(new AcmReceiver),
46 acm_(new AudioCodingModuleImpl(0)),
49 last_packet_send_timestamp_(timestamp_),
50 last_frame_type_(kFrameEmpty) {}
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]));
61 acm_->InitializeReceiver();
62 acm_->InitializeSender();
63 acm_->RegisterTransportCallback(this);
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;
78 void InsertOnePacketOfSilence(int codec_id) {
80 ACMCodecDB::Codec(codec_id, &codec);
81 if (timestamp_ == 0) { // This is the first time inserting audio.
82 ASSERT_EQ(0, acm_->RegisterSendCodec(codec));
84 CodecInst current_codec;
85 ASSERT_EQ(0, acm_->SendCodec(¤t_codec));
86 if (!CodecsEqual(codec, current_codec))
87 ASSERT_EQ(0, acm_->RegisterSendCodec(codec));
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_ *
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);
106 ASSERT_TRUE(packet_sent_); // Sanity check.
109 // Last element of id should be negative.
110 void AddSetOfCodecs(const int* id) {
113 ASSERT_EQ(0, receiver_->AddCodec(id[n], codecs_[id[n]].pltype,
114 codecs_[id[n]].channels, NULL));
119 virtual int SendData(
120 FrameType frame_type,
121 uint8_t payload_type,
123 const uint8_t* payload_data,
124 uint16_t payload_len_bytes,
125 const RTPFragmentationHeader* fragmentation) {
126 if (frame_type == kFrameEmpty)
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;
134 rtp_header_.type.Audio.isCNG = true;
135 rtp_header_.header.timestamp = timestamp;
137 int ret_val = receiver_->InsertPacket(rtp_header_, payload_data,
143 rtp_header_.header.sequenceNumber++;
145 last_frame_type_ = frame_type;
149 scoped_ptr<AcmReceiver> receiver_;
150 CodecInst codecs_[ACMCodecDB::kMaxNumCodecs];
151 scoped_ptr<AudioCodingModule> acm_;
152 WebRtcRTPHeader rtp_header_;
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_;
159 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecGetCodec)) {
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));
166 // Get codec and compare.
167 for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) {
170 // Codecs with odd index should match the reference.
171 EXPECT_EQ(0, receiver_->DecoderByPayloadType(codecs_[n].pltype,
173 EXPECT_TRUE(CodecsEqual(codecs_[n], my_codec));
175 // Codecs with even index are not registered.
176 EXPECT_EQ(-1, receiver_->DecoderByPayloadType(codecs_[n].pltype,
182 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecChangePayloadType)) {
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));
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));
198 // Payload type |payload_type| should not exist.
199 EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &test_codec));
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));
206 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecRemoveCodec)) {
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));
214 // Remove non-existing codec should not fail. ACM1 legacy.
215 EXPECT_EQ(0, receiver_->RemoveCodec(payload_type + 1));
217 // Remove an existing codec.
218 EXPECT_EQ(0, receiver_->RemoveCodec(payload_type));
220 // Ask for the removed codec, must fail.
221 EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &codec));
224 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(SampleRate)) {
225 const int kCodecId[] = {
226 ACMCodecDB::kISAC, ACMCodecDB::kISACSWB, ACMCodecDB::kISACFB,
229 AddSetOfCodecs(kCodecId);
232 const int kOutSampleRateHz = 8000; // Different than codec sample rate.
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));
241 EXPECT_EQ(std::min(32000, codecs_[kCodecId[n]].plfreq),
242 receiver_->current_sample_rate_hz());
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
252 receiver_->SetPlayoutMode(voice);
253 EXPECT_EQ(voice, receiver_->PlayoutMode());
254 EXPECT_EQ(kBgnOn, receiver_->BackgroundNoiseModeForTest());
256 receiver_->SetPlayoutMode(streaming);
257 EXPECT_EQ(streaming, receiver_->PlayoutMode());
258 EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest());
260 receiver_->SetPlayoutMode(fax);
261 EXPECT_EQ(fax, receiver_->PlayoutMode());
262 EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest());
264 receiver_->SetPlayoutMode(off);
265 EXPECT_EQ(off, receiver_->PlayoutMode());
266 EXPECT_EQ(kBgnOff, receiver_->BackgroundNoiseModeForTest());
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());
277 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(PostdecodingVad)) {
278 receiver_->EnableVad();
279 EXPECT_TRUE(receiver_->vad_enabled());
281 const int id = ACMCodecDB::kPCM16Bwb;
282 ASSERT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels,
284 const int kNumPackets = 5;
285 const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100);
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));
292 EXPECT_EQ(AudioFrame::kVadPassive, frame.vad_activity_);
294 receiver_->DisableVad();
295 EXPECT_FALSE(receiver_->vad_enabled());
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));
302 EXPECT_EQ(AudioFrame::kVadUnknown, frame.vad_activity_);
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,
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);
317 receiver_->FlushBuffers();
318 receiver_->NetworkStatistics(&statistics);
319 ASSERT_EQ(0, statistics.currentBufferSize);
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,
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;
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;
346 EXPECT_EQ(expected_timestamp + ts_offset,
347 receiver_->PlayoutTimestamp());
349 expected_timestamp += codecs_[id].plfreq / 100; // Increment by 10 ms.
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,
360 AddSetOfCodecs(kCodecId);
362 const int kCngId[] = { // Not including full-band.
363 ACMCodecDB::kCNNB, ACMCodecDB::kCNWB, ACMCodecDB::kCNSWB,
366 AddSetOfCodecs(kCngId);
368 // Register CNG at sender side.
370 while (kCngId[n] > 0) {
371 ASSERT_EQ(0, acm_->RegisterSendCodec(codecs_[kCngId[n]]));
376 // No audio payload is received.
377 EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec));
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_);
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());
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]);
398 // Sanity check if Actually an audio payload received, and it should be
400 ASSERT_TRUE(packet_sent_);
401 ASSERT_EQ(kAudioFrameSpeech, last_frame_type_);
402 EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id());
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);
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_);
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));
425 } // namespace webrtc