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 "testing/gtest/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 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 AudioCoding::Config config; 51 config.transport = this; 52 acm_.reset(new AudioCodingImpl(config)); 53 receiver_.reset(new AcmReceiver(config.ToOldConfig())); 54 } 55 56 ~AcmReceiverTest() {} 57 58 virtual void SetUp() OVERRIDE { 59 ASSERT_TRUE(receiver_.get() != NULL); 60 ASSERT_TRUE(acm_.get() != NULL); 61 for (int n = 0; n < ACMCodecDB::kNumCodecs; n++) { 62 ASSERT_EQ(0, ACMCodecDB::Codec(n, &codecs_[n])); 63 } 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 virtual void TearDown() OVERRIDE { 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_TRUE(acm_->RegisterSendCodec(codec_id, codec.pltype)); 83 } else { 84 const CodecInst* current_codec = acm_->GetSenderCodecInst(); 85 ASSERT_TRUE(current_codec); 86 if (!CodecsEqual(codec, *current_codec)) 87 ASSERT_TRUE(acm_->RegisterSendCodec(codec_id, codec.pltype)); 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 num_bytes = acm_->Add10MsAudio(frame); 103 ASSERT_GE(num_bytes, 0); 104 } 105 ASSERT_TRUE(packet_sent_); // Sanity check. 106 } 107 108 // Last element of id should be negative. 109 void AddSetOfCodecs(const int* id) { 110 int n = 0; 111 while (id[n] >= 0) { 112 ASSERT_EQ(0, receiver_->AddCodec(id[n], codecs_[id[n]].pltype, 113 codecs_[id[n]].channels, NULL)); 114 ++n; 115 } 116 } 117 118 virtual int SendData( 119 FrameType frame_type, 120 uint8_t payload_type, 121 uint32_t timestamp, 122 const uint8_t* payload_data, 123 uint16_t payload_len_bytes, 124 const RTPFragmentationHeader* fragmentation) OVERRIDE { 125 if (frame_type == kFrameEmpty) 126 return 0; 127 128 rtp_header_.header.payloadType = payload_type; 129 rtp_header_.frameType = frame_type; 130 if (frame_type == kAudioFrameSpeech) 131 rtp_header_.type.Audio.isCNG = false; 132 else 133 rtp_header_.type.Audio.isCNG = true; 134 rtp_header_.header.timestamp = timestamp; 135 136 int ret_val = receiver_->InsertPacket(rtp_header_, payload_data, 137 payload_len_bytes); 138 if (ret_val < 0) { 139 assert(false); 140 return -1; 141 } 142 rtp_header_.header.sequenceNumber++; 143 packet_sent_ = true; 144 last_frame_type_ = frame_type; 145 return 0; 146 } 147 148 scoped_ptr<AcmReceiver> receiver_; 149 CodecInst codecs_[ACMCodecDB::kMaxNumCodecs]; 150 scoped_ptr<AudioCoding> acm_; 151 WebRtcRTPHeader rtp_header_; 152 uint32_t timestamp_; 153 bool packet_sent_; // Set when SendData is called reset when inserting audio. 154 uint32_t last_packet_send_timestamp_; 155 FrameType last_frame_type_; 156 }; 157 158 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecGetCodec)) { 159 // Add codec. 160 for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) { 161 if (n & 0x1) // Just add codecs with odd index. 162 EXPECT_EQ(0, receiver_->AddCodec(n, codecs_[n].pltype, 163 codecs_[n].channels, NULL)); 164 } 165 // Get codec and compare. 166 for (int n = 0; n < ACMCodecDB::kNumCodecs; ++n) { 167 CodecInst my_codec; 168 if (n & 0x1) { 169 // Codecs with odd index should match the reference. 170 EXPECT_EQ(0, receiver_->DecoderByPayloadType(codecs_[n].pltype, 171 &my_codec)); 172 EXPECT_TRUE(CodecsEqual(codecs_[n], my_codec)); 173 } else { 174 // Codecs with even index are not registered. 175 EXPECT_EQ(-1, receiver_->DecoderByPayloadType(codecs_[n].pltype, 176 &my_codec)); 177 } 178 } 179 } 180 181 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecChangePayloadType)) { 182 CodecInst ref_codec; 183 const int codec_id = ACMCodecDB::kPCMA; 184 EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &ref_codec)); 185 const int payload_type = ref_codec.pltype; 186 EXPECT_EQ(0, receiver_->AddCodec(codec_id, ref_codec.pltype, 187 ref_codec.channels, NULL)); 188 CodecInst test_codec; 189 EXPECT_EQ(0, receiver_->DecoderByPayloadType(payload_type, &test_codec)); 190 EXPECT_EQ(true, CodecsEqual(ref_codec, test_codec)); 191 192 // Re-register the same codec with different payload. 193 ref_codec.pltype = payload_type + 1; 194 EXPECT_EQ(0, receiver_->AddCodec(codec_id, ref_codec.pltype, 195 ref_codec.channels, NULL)); 196 197 // Payload type |payload_type| should not exist. 198 EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &test_codec)); 199 200 // Payload type |payload_type + 1| should exist. 201 EXPECT_EQ(0, receiver_->DecoderByPayloadType(payload_type + 1, &test_codec)); 202 EXPECT_TRUE(CodecsEqual(test_codec, ref_codec)); 203 } 204 205 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(AddCodecRemoveCodec)) { 206 CodecInst codec; 207 const int codec_id = ACMCodecDB::kPCMA; 208 EXPECT_EQ(0, ACMCodecDB::Codec(codec_id, &codec)); 209 const int payload_type = codec.pltype; 210 EXPECT_EQ(0, receiver_->AddCodec(codec_id, codec.pltype, 211 codec.channels, NULL)); 212 213 // Remove non-existing codec should not fail. ACM1 legacy. 214 EXPECT_EQ(0, receiver_->RemoveCodec(payload_type + 1)); 215 216 // Remove an existing codec. 217 EXPECT_EQ(0, receiver_->RemoveCodec(payload_type)); 218 219 // Ask for the removed codec, must fail. 220 EXPECT_EQ(-1, receiver_->DecoderByPayloadType(payload_type, &codec)); 221 } 222 223 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(SampleRate)) { 224 const int kCodecId[] = { 225 ACMCodecDB::kISAC, ACMCodecDB::kISACSWB, ACMCodecDB::kISACFB, 226 -1 // Terminator. 227 }; 228 AddSetOfCodecs(kCodecId); 229 230 AudioFrame frame; 231 const int kOutSampleRateHz = 8000; // Different than codec sample rate. 232 int n = 0; 233 while (kCodecId[n] >= 0) { 234 const int num_10ms_frames = codecs_[kCodecId[n]].pacsize / 235 (codecs_[kCodecId[n]].plfreq / 100); 236 InsertOnePacketOfSilence(kCodecId[n]); 237 for (int k = 0; k < num_10ms_frames; ++k) { 238 EXPECT_EQ(0, receiver_->GetAudio(kOutSampleRateHz, &frame)); 239 } 240 EXPECT_EQ(std::min(32000, codecs_[kCodecId[n]].plfreq), 241 receiver_->current_sample_rate_hz()); 242 ++n; 243 } 244 } 245 246 // Verify that the playout mode is set correctly. 247 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(PlayoutMode)) { 248 receiver_->SetPlayoutMode(voice); 249 EXPECT_EQ(voice, receiver_->PlayoutMode()); 250 251 receiver_->SetPlayoutMode(streaming); 252 EXPECT_EQ(streaming, receiver_->PlayoutMode()); 253 254 receiver_->SetPlayoutMode(fax); 255 EXPECT_EQ(fax, receiver_->PlayoutMode()); 256 257 receiver_->SetPlayoutMode(off); 258 EXPECT_EQ(off, receiver_->PlayoutMode()); 259 } 260 261 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(PostdecodingVad)) { 262 receiver_->EnableVad(); 263 EXPECT_TRUE(receiver_->vad_enabled()); 264 265 const int id = ACMCodecDB::kPCM16Bwb; 266 ASSERT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels, 267 NULL)); 268 const int kNumPackets = 5; 269 const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100); 270 AudioFrame frame; 271 for (int n = 0; n < kNumPackets; ++n) { 272 InsertOnePacketOfSilence(id); 273 for (int k = 0; k < num_10ms_frames; ++k) 274 ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame)); 275 } 276 EXPECT_EQ(AudioFrame::kVadPassive, frame.vad_activity_); 277 278 receiver_->DisableVad(); 279 EXPECT_FALSE(receiver_->vad_enabled()); 280 281 for (int n = 0; n < kNumPackets; ++n) { 282 InsertOnePacketOfSilence(id); 283 for (int k = 0; k < num_10ms_frames; ++k) 284 ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame)); 285 } 286 EXPECT_EQ(AudioFrame::kVadUnknown, frame.vad_activity_); 287 } 288 289 TEST_F(AcmReceiverTest, DISABLED_ON_ANDROID(LastAudioCodec)) { 290 const int kCodecId[] = { 291 ACMCodecDB::kISAC, ACMCodecDB::kPCMA, ACMCodecDB::kISACSWB, 292 ACMCodecDB::kPCM16Bswb32kHz, ACMCodecDB::kG722_1C_48, 293 -1 // Terminator. 294 }; 295 AddSetOfCodecs(kCodecId); 296 297 const int kCngId[] = { // Not including full-band. 298 ACMCodecDB::kCNNB, ACMCodecDB::kCNWB, ACMCodecDB::kCNSWB, 299 -1 // Terminator. 300 }; 301 AddSetOfCodecs(kCngId); 302 303 // Register CNG at sender side. 304 int n = 0; 305 while (kCngId[n] > 0) { 306 ASSERT_TRUE(acm_->RegisterSendCodec(kCngId[n], codecs_[kCngId[n]].pltype)); 307 ++n; 308 } 309 310 CodecInst codec; 311 // No audio payload is received. 312 EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec)); 313 314 // Start with sending DTX. 315 ASSERT_TRUE(acm_->SetVad(true, true, VADVeryAggr)); 316 packet_sent_ = false; 317 InsertOnePacketOfSilence(kCodecId[0]); // Enough to test with one codec. 318 ASSERT_TRUE(packet_sent_); 319 EXPECT_EQ(kAudioFrameCN, last_frame_type_); 320 321 // Has received, only, DTX. Last Audio codec is undefined. 322 EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec)); 323 EXPECT_EQ(-1, receiver_->last_audio_codec_id()); 324 EXPECT_EQ(-1, receiver_->last_audio_payload_type()); 325 326 n = 0; 327 while (kCodecId[n] >= 0) { // Loop over codecs. 328 // Set DTX off to send audio payload. 329 acm_->SetVad(false, false, VADAggr); 330 packet_sent_ = false; 331 InsertOnePacketOfSilence(kCodecId[n]); 332 333 // Sanity check if Actually an audio payload received, and it should be 334 // of type "speech." 335 ASSERT_TRUE(packet_sent_); 336 ASSERT_EQ(kAudioFrameSpeech, last_frame_type_); 337 EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id()); 338 339 // Set VAD on to send DTX. Then check if the "Last Audio codec" returns 340 // the expected codec. 341 acm_->SetVad(true, true, VADAggr); 342 343 // Do as many encoding until a DTX is sent. 344 while (last_frame_type_ != kAudioFrameCN) { 345 packet_sent_ = false; 346 InsertOnePacketOfSilence(kCodecId[n]); 347 ASSERT_TRUE(packet_sent_); 348 } 349 EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id()); 350 EXPECT_EQ(codecs_[kCodecId[n]].pltype, 351 receiver_->last_audio_payload_type()); 352 EXPECT_EQ(0, receiver_->LastAudioCodec(&codec)); 353 EXPECT_TRUE(CodecsEqual(codecs_[kCodecId[n]], codec)); 354 ++n; 355 } 356 } 357 358 } // namespace acm2 359 360 } // namespace webrtc 361