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 AcmReceiverTestOldApi : public AudioPacketizationCallback, 43 public ::testing::Test { 44 protected: 45 AcmReceiverTestOldApi() 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 ~AcmReceiverTestOldApi() {} 56 57 virtual void SetUp() OVERRIDE { 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 virtual void TearDown() OVERRIDE { 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(¤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. 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) OVERRIDE { 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(AcmReceiverTestOldApi, 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(AcmReceiverTestOldApi, 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(AcmReceiverTestOldApi, 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(AcmReceiverTestOldApi, 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 // Verify that the playout mode is set correctly. 251 TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(PlayoutMode)) { 252 receiver_->SetPlayoutMode(voice); 253 EXPECT_EQ(voice, receiver_->PlayoutMode()); 254 255 receiver_->SetPlayoutMode(streaming); 256 EXPECT_EQ(streaming, receiver_->PlayoutMode()); 257 258 receiver_->SetPlayoutMode(fax); 259 EXPECT_EQ(fax, receiver_->PlayoutMode()); 260 261 receiver_->SetPlayoutMode(off); 262 EXPECT_EQ(off, receiver_->PlayoutMode()); 263 } 264 265 TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(PostdecodingVad)) { 266 receiver_->EnableVad(); 267 EXPECT_TRUE(receiver_->vad_enabled()); 268 269 const int id = ACMCodecDB::kPCM16Bwb; 270 ASSERT_EQ(0, receiver_->AddCodec(id, codecs_[id].pltype, codecs_[id].channels, 271 NULL)); 272 const int kNumPackets = 5; 273 const int num_10ms_frames = codecs_[id].pacsize / (codecs_[id].plfreq / 100); 274 AudioFrame frame; 275 for (int n = 0; n < kNumPackets; ++n) { 276 InsertOnePacketOfSilence(id); 277 for (int k = 0; k < num_10ms_frames; ++k) 278 ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame)); 279 } 280 EXPECT_EQ(AudioFrame::kVadPassive, frame.vad_activity_); 281 282 receiver_->DisableVad(); 283 EXPECT_FALSE(receiver_->vad_enabled()); 284 285 for (int n = 0; n < kNumPackets; ++n) { 286 InsertOnePacketOfSilence(id); 287 for (int k = 0; k < num_10ms_frames; ++k) 288 ASSERT_EQ(0, receiver_->GetAudio(codecs_[id].plfreq, &frame)); 289 } 290 EXPECT_EQ(AudioFrame::kVadUnknown, frame.vad_activity_); 291 } 292 293 TEST_F(AcmReceiverTestOldApi, DISABLED_ON_ANDROID(LastAudioCodec)) { 294 const int kCodecId[] = { 295 ACMCodecDB::kISAC, ACMCodecDB::kPCMA, ACMCodecDB::kISACSWB, 296 ACMCodecDB::kPCM16Bswb32kHz, ACMCodecDB::kG722_1C_48, 297 -1 // Terminator. 298 }; 299 AddSetOfCodecs(kCodecId); 300 301 const int kCngId[] = { // Not including full-band. 302 ACMCodecDB::kCNNB, ACMCodecDB::kCNWB, ACMCodecDB::kCNSWB, 303 -1 // Terminator. 304 }; 305 AddSetOfCodecs(kCngId); 306 307 // Register CNG at sender side. 308 int n = 0; 309 while (kCngId[n] > 0) { 310 ASSERT_EQ(0, acm_->RegisterSendCodec(codecs_[kCngId[n]])); 311 ++n; 312 } 313 314 CodecInst codec; 315 // No audio payload is received. 316 EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec)); 317 318 // Start with sending DTX. 319 ASSERT_EQ(0, acm_->SetVAD(true, true, VADVeryAggr)); 320 packet_sent_ = false; 321 InsertOnePacketOfSilence(kCodecId[0]); // Enough to test with one codec. 322 ASSERT_TRUE(packet_sent_); 323 EXPECT_EQ(kAudioFrameCN, last_frame_type_); 324 325 // Has received, only, DTX. Last Audio codec is undefined. 326 EXPECT_EQ(-1, receiver_->LastAudioCodec(&codec)); 327 EXPECT_EQ(-1, receiver_->last_audio_codec_id()); 328 EXPECT_EQ(-1, receiver_->last_audio_payload_type()); 329 330 n = 0; 331 while (kCodecId[n] >= 0) { // Loop over codecs. 332 // Set DTX off to send audio payload. 333 acm_->SetVAD(false, false, VADAggr); 334 packet_sent_ = false; 335 InsertOnePacketOfSilence(kCodecId[n]); 336 337 // Sanity check if Actually an audio payload received, and it should be 338 // of type "speech." 339 ASSERT_TRUE(packet_sent_); 340 ASSERT_EQ(kAudioFrameSpeech, last_frame_type_); 341 EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id()); 342 343 // Set VAD on to send DTX. Then check if the "Last Audio codec" returns 344 // the expected codec. 345 acm_->SetVAD(true, true, VADAggr); 346 347 // Do as many encoding until a DTX is sent. 348 while (last_frame_type_ != kAudioFrameCN) { 349 packet_sent_ = false; 350 InsertOnePacketOfSilence(kCodecId[n]); 351 ASSERT_TRUE(packet_sent_); 352 } 353 EXPECT_EQ(kCodecId[n], receiver_->last_audio_codec_id()); 354 EXPECT_EQ(codecs_[kCodecId[n]].pltype, 355 receiver_->last_audio_payload_type()); 356 EXPECT_EQ(0, receiver_->LastAudioCodec(&codec)); 357 EXPECT_TRUE(CodecsEqual(codecs_[kCodecId[n]], codec)); 358 ++n; 359 } 360 } 361 362 } // namespace acm2 363 364 } // namespace webrtc 365