audio_coding_module_unittest.cc (52585B)
1 /* 2 * Copyright (c) 2014 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 "modules/audio_coding/include/audio_coding_module.h" 12 13 #include <stdio.h> 14 15 #include <array> 16 #include <atomic> 17 #include <cstdint> 18 #include <cstdio> 19 #include <cstring> 20 #include <memory> 21 #include <optional> 22 #include <string> 23 #include <utility> 24 #include <vector> 25 26 #include "absl/strings/string_view.h" 27 #include "api/array_view.h" 28 #include "api/audio_codecs/audio_decoder_factory.h" 29 #include "api/audio_codecs/audio_encoder.h" 30 #include "api/audio_codecs/audio_encoder_factory.h" 31 #include "api/audio_codecs/audio_format.h" 32 #include "api/audio_codecs/builtin_audio_decoder_factory.h" 33 #include "api/audio_codecs/builtin_audio_encoder_factory.h" 34 #include "api/audio_codecs/opus/audio_decoder_multi_channel_opus.h" 35 #include "api/audio_codecs/opus/audio_encoder_multi_channel_opus.h" 36 #include "api/audio_codecs/opus/audio_encoder_opus.h" 37 #include "api/audio_codecs/opus/audio_encoder_opus_config.h" 38 #include "api/environment/environment.h" 39 #include "api/environment/environment_factory.h" 40 #include "api/make_ref_counted.h" 41 #include "api/neteq/default_neteq_factory.h" 42 #include "api/neteq/neteq.h" 43 #include "api/scoped_refptr.h" 44 #include "api/units/time_delta.h" 45 #include "api/units/timestamp.h" 46 #include "common_audio/vad/include/vad.h" 47 #include "modules/audio_coding/acm2/acm_receive_test.h" 48 #include "modules/audio_coding/acm2/acm_send_test.h" 49 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h" 50 #include "modules/audio_coding/codecs/g711/audio_encoder_pcm.h" 51 #include "modules/audio_coding/include/audio_coding_module_typedefs.h" 52 #include "modules/audio_coding/neteq/tools/audio_checksum.h" 53 #include "modules/audio_coding/neteq/tools/audio_sink.h" 54 #include "modules/audio_coding/neteq/tools/constant_pcm_packet_source.h" 55 #include "modules/audio_coding/neteq/tools/input_audio_file.h" 56 #include "modules/audio_coding/neteq/tools/output_audio_file.h" 57 #include "modules/audio_coding/neteq/tools/output_wav_file.h" 58 #include "modules/rtp_rtcp/source/rtp_packet_received.h" 59 #include "rtc_base/buffer.h" 60 #include "rtc_base/event.h" 61 #include "rtc_base/message_digest.h" 62 #include "rtc_base/numerics/safe_conversions.h" 63 #include "rtc_base/platform_thread.h" 64 #include "rtc_base/string_encode.h" 65 #include "rtc_base/synchronization/mutex.h" 66 #include "rtc_base/system/arch.h" 67 #include "rtc_base/thread.h" 68 #include "rtc_base/thread_annotations.h" 69 #include "system_wrappers/include/clock.h" 70 #include "test/audio_decoder_proxy_factory.h" 71 #include "test/gmock.h" 72 #include "test/gtest.h" 73 #include "test/mock_audio_encoder.h" 74 #include "test/testsupport/file_utils.h" 75 76 using ::testing::_; 77 using ::testing::AtLeast; 78 using ::testing::Invoke; 79 80 namespace webrtc { 81 82 class RtpData { 83 public: 84 RtpData(int samples_per_packet, uint8_t payload_type) 85 : samples_per_packet_(samples_per_packet), payload_type_(payload_type) {} 86 87 virtual ~RtpData() {} 88 89 void Populate(RTPHeader* rtp_header) { 90 rtp_header->sequenceNumber = 0xABCD; 91 rtp_header->timestamp = 0xABCDEF01; 92 rtp_header->payloadType = payload_type_; 93 rtp_header->markerBit = false; 94 rtp_header->ssrc = 0x1234; 95 rtp_header->numCSRCs = 0; 96 } 97 98 void Forward(RTPHeader* rtp_header) { 99 ++rtp_header->sequenceNumber; 100 rtp_header->timestamp += samples_per_packet_; 101 } 102 103 private: 104 int samples_per_packet_; 105 uint8_t payload_type_; 106 }; 107 108 class PacketizationCallbackStubOldApi : public AudioPacketizationCallback { 109 public: 110 PacketizationCallbackStubOldApi() 111 : num_calls_(0), 112 last_frame_type_(AudioFrameType::kEmptyFrame), 113 last_payload_type_(-1), 114 last_timestamp_(0) {} 115 116 int32_t SendData(AudioFrameType frame_type, 117 uint8_t payload_type, 118 uint32_t timestamp, 119 const uint8_t* payload_data, 120 size_t payload_len_bytes, 121 int64_t /* absolute_capture_timestamp_ms */) override { 122 MutexLock lock(&mutex_); 123 ++num_calls_; 124 last_frame_type_ = frame_type; 125 last_payload_type_ = payload_type; 126 last_timestamp_ = timestamp; 127 last_payload_vec_.assign(payload_data, payload_data + payload_len_bytes); 128 return 0; 129 } 130 131 int num_calls() const { 132 MutexLock lock(&mutex_); 133 return num_calls_; 134 } 135 136 int last_payload_len_bytes() const { 137 MutexLock lock(&mutex_); 138 return checked_cast<int>(last_payload_vec_.size()); 139 } 140 141 AudioFrameType last_frame_type() const { 142 MutexLock lock(&mutex_); 143 return last_frame_type_; 144 } 145 146 int last_payload_type() const { 147 MutexLock lock(&mutex_); 148 return last_payload_type_; 149 } 150 151 uint32_t last_timestamp() const { 152 MutexLock lock(&mutex_); 153 return last_timestamp_; 154 } 155 156 void SwapBuffers(std::vector<uint8_t>* payload) { 157 MutexLock lock(&mutex_); 158 last_payload_vec_.swap(*payload); 159 } 160 161 private: 162 int num_calls_ RTC_GUARDED_BY(mutex_); 163 AudioFrameType last_frame_type_ RTC_GUARDED_BY(mutex_); 164 int last_payload_type_ RTC_GUARDED_BY(mutex_); 165 uint32_t last_timestamp_ RTC_GUARDED_BY(mutex_); 166 std::vector<uint8_t> last_payload_vec_ RTC_GUARDED_BY(mutex_); 167 mutable Mutex mutex_; 168 }; 169 170 class AudioCodingModuleTestOldApi : public ::testing::Test { 171 protected: 172 static constexpr int kSampleRateHz = 16000; 173 static constexpr int kNumSamples10ms = kSampleRateHz / 100; 174 static constexpr int kFrameSizeMs = 10; // Multiple of 10. 175 static constexpr int kFrameSizeSamples = kFrameSizeMs / 10 * kNumSamples10ms; 176 static constexpr int kPayloadSizeBytes = kFrameSizeSamples * sizeof(int16_t); 177 static constexpr uint8_t kPayloadType = 111; 178 179 AudioCodingModuleTestOldApi() 180 : env_(CreateEnvironment()), 181 rtp_utility_(new RtpData(kFrameSizeSamples, kPayloadType)) {} 182 183 ~AudioCodingModuleTestOldApi() override {} 184 185 void TearDown() override {} 186 187 void SetUp() override { 188 acm_ = AudioCodingModule::Create(); 189 neteq_ = DefaultNetEqFactory().Create(env_, NetEq::Config(), 190 CreateBuiltinAudioDecoderFactory()); 191 192 rtp_utility_->Populate(&rtp_header_); 193 194 input_frame_.sample_rate_hz_ = kSampleRateHz; 195 input_frame_.num_channels_ = 1; 196 input_frame_.samples_per_channel_ = kSampleRateHz * 10 / 1000; // 10 ms. 197 static_assert(kSampleRateHz * 10 / 1000 <= AudioFrame::kMaxDataSizeSamples, 198 "audio frame too small"); 199 input_frame_.Mute(); 200 201 ASSERT_EQ(0, acm_->RegisterTransportCallback(&packet_cb_)); 202 203 SetUpL16Codec(); 204 } 205 206 // Set up L16 codec. 207 virtual void SetUpL16Codec() { 208 audio_format_ = SdpAudioFormat("L16", kSampleRateHz, 1); 209 pac_size_ = 160; 210 } 211 212 virtual void RegisterCodec() { 213 neteq_->SetCodecs({{kPayloadType, *audio_format_}}); 214 acm_->SetEncoder(CreateBuiltinAudioEncoderFactory()->Create( 215 env_, *audio_format_, {.payload_type = kPayloadType})); 216 } 217 218 virtual void InsertPacketAndPullAudio() { 219 InsertPacket(); 220 PullAudio(); 221 } 222 223 virtual void InsertPacket() { 224 const uint8_t kPayload[kPayloadSizeBytes] = {0}; 225 ASSERT_EQ(0, neteq_->InsertPacket( 226 rtp_header_, 227 ArrayView<const uint8_t>(kPayload, kPayloadSizeBytes), 228 /*receive_time=*/Timestamp::MinusInfinity())); 229 rtp_utility_->Forward(&rtp_header_); 230 } 231 232 virtual void PullAudio() { 233 AudioFrame audio_frame; 234 bool muted; 235 ASSERT_EQ(0, neteq_->GetAudio(&audio_frame, &muted)); 236 ASSERT_FALSE(muted); 237 } 238 239 virtual void InsertAudio() { 240 ASSERT_GE(acm_->Add10MsData(input_frame_), 0); 241 input_frame_.timestamp_ += kNumSamples10ms; 242 } 243 244 virtual void VerifyEncoding() { 245 int last_length = packet_cb_.last_payload_len_bytes(); 246 EXPECT_TRUE(last_length == 2 * pac_size_ || last_length == 0) 247 << "Last encoded packet was " << last_length << " bytes."; 248 } 249 250 virtual void InsertAudioAndVerifyEncoding() { 251 InsertAudio(); 252 VerifyEncoding(); 253 } 254 255 Environment env_; 256 std::unique_ptr<RtpData> rtp_utility_; 257 std::unique_ptr<AudioCodingModule> acm_; 258 std::unique_ptr<NetEq> neteq_; 259 PacketizationCallbackStubOldApi packet_cb_; 260 RTPHeader rtp_header_; 261 AudioFrame input_frame_; 262 263 std::optional<SdpAudioFormat> audio_format_; 264 int pac_size_ = -1; 265 }; 266 267 class AudioCodingModuleTestOldApiDeathTest 268 : public AudioCodingModuleTestOldApi {}; 269 270 // Checks that the transport callback is invoked once for each speech packet. 271 // Also checks that the frame type is kAudioFrameSpeech. 272 TEST_F(AudioCodingModuleTestOldApi, TransportCallbackIsInvokedForEachPacket) { 273 const int k10MsBlocksPerPacket = 3; 274 pac_size_ = k10MsBlocksPerPacket * kSampleRateHz / 100; 275 audio_format_->parameters["ptime"] = "30"; 276 RegisterCodec(); 277 const int kLoops = 10; 278 for (int i = 0; i < kLoops; ++i) { 279 EXPECT_EQ(i / k10MsBlocksPerPacket, packet_cb_.num_calls()); 280 if (packet_cb_.num_calls() > 0) 281 EXPECT_EQ(AudioFrameType::kAudioFrameSpeech, 282 packet_cb_.last_frame_type()); 283 InsertAudioAndVerifyEncoding(); 284 } 285 EXPECT_EQ(kLoops / k10MsBlocksPerPacket, packet_cb_.num_calls()); 286 EXPECT_EQ(AudioFrameType::kAudioFrameSpeech, packet_cb_.last_frame_type()); 287 } 288 289 // Introduce this class to set different expectations on the number of encoded 290 // bytes. This class expects all encoded packets to be 9 bytes (matching one 291 // CNG SID frame) or 0 bytes. This test depends on `input_frame_` containing 292 // (near-)zero values. It also introduces a way to register comfort noise with 293 // a custom payload type. 294 class AudioCodingModuleTestWithComfortNoiseOldApi 295 : public AudioCodingModuleTestOldApi { 296 protected: 297 void RegisterCngCodec(int rtp_payload_type) { 298 neteq_->SetCodecs({{kPayloadType, *audio_format_}, 299 {rtp_payload_type, {"cn", kSampleRateHz, 1}}}); 300 acm_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* enc) { 301 AudioEncoderCngConfig config; 302 config.speech_encoder = std::move(*enc); 303 config.num_channels = 1; 304 config.payload_type = rtp_payload_type; 305 config.vad_mode = Vad::kVadNormal; 306 *enc = CreateComfortNoiseEncoder(std::move(config)); 307 }); 308 } 309 310 void VerifyEncoding() override { 311 int last_length = packet_cb_.last_payload_len_bytes(); 312 EXPECT_TRUE(last_length == 9 || last_length == 0) 313 << "Last encoded packet was " << last_length << " bytes."; 314 } 315 316 void DoTest(int blocks_per_packet, int cng_pt) { 317 const int kLoops = 40; 318 // This array defines the expected frame types, and when they should arrive. 319 // We expect a frame to arrive each time the speech encoder would have 320 // produced a packet, and once every 100 ms the frame should be non-empty, 321 // that is contain comfort noise. 322 const struct { 323 int ix; 324 AudioFrameType type; 325 } expectation[] = {{.ix = 2, .type = AudioFrameType::kAudioFrameCN}, 326 {.ix = 5, .type = AudioFrameType::kEmptyFrame}, 327 {.ix = 8, .type = AudioFrameType::kEmptyFrame}, 328 {.ix = 11, .type = AudioFrameType::kAudioFrameCN}, 329 {.ix = 14, .type = AudioFrameType::kEmptyFrame}, 330 {.ix = 17, .type = AudioFrameType::kEmptyFrame}, 331 {.ix = 20, .type = AudioFrameType::kAudioFrameCN}, 332 {.ix = 23, .type = AudioFrameType::kEmptyFrame}, 333 {.ix = 26, .type = AudioFrameType::kEmptyFrame}, 334 {.ix = 29, .type = AudioFrameType::kEmptyFrame}, 335 {.ix = 32, .type = AudioFrameType::kAudioFrameCN}, 336 {.ix = 35, .type = AudioFrameType::kEmptyFrame}, 337 {.ix = 38, .type = AudioFrameType::kEmptyFrame}}; 338 for (int i = 0; i < kLoops; ++i) { 339 int num_calls_before = packet_cb_.num_calls(); 340 EXPECT_EQ(i / blocks_per_packet, num_calls_before); 341 InsertAudioAndVerifyEncoding(); 342 int num_calls = packet_cb_.num_calls(); 343 if (num_calls == num_calls_before + 1) { 344 EXPECT_EQ(expectation[num_calls - 1].ix, i); 345 EXPECT_EQ(expectation[num_calls - 1].type, packet_cb_.last_frame_type()) 346 << "Wrong frame type for lap " << i; 347 EXPECT_EQ(cng_pt, packet_cb_.last_payload_type()); 348 } else { 349 EXPECT_EQ(num_calls, num_calls_before); 350 } 351 } 352 } 353 }; 354 355 // Checks that the transport callback is invoked once per frame period of the 356 // underlying speech encoder, even when comfort noise is produced. 357 // Also checks that the frame type is kAudioFrameCN or kEmptyFrame. 358 TEST_F(AudioCodingModuleTestWithComfortNoiseOldApi, 359 TransportCallbackTestForComfortNoiseRegisterCngLast) { 360 const int k10MsBlocksPerPacket = 3; 361 pac_size_ = k10MsBlocksPerPacket * kSampleRateHz / 100; 362 audio_format_->parameters["ptime"] = "30"; 363 RegisterCodec(); 364 const int kCngPayloadType = 105; 365 RegisterCngCodec(kCngPayloadType); 366 DoTest(k10MsBlocksPerPacket, kCngPayloadType); 367 } 368 369 // A multi-threaded test for ACM that uses the PCM16b 16 kHz codec. 370 class AudioCodingModuleMtTestOldApi : public AudioCodingModuleTestOldApi { 371 protected: 372 static const int kNumPackets = 500; 373 static const int kNumPullCalls = 500; 374 375 AudioCodingModuleMtTestOldApi() 376 : AudioCodingModuleTestOldApi(), 377 send_count_(0), 378 insert_packet_count_(0), 379 pull_audio_count_(0), 380 next_insert_packet_time_ms_(0), 381 fake_clock_(new SimulatedClock(0)) { 382 EnvironmentFactory override_clock(env_); 383 override_clock.Set(fake_clock_.get()); 384 env_ = override_clock.Create(); 385 } 386 387 void SetUp() override { 388 AudioCodingModuleTestOldApi::SetUp(); 389 RegisterCodec(); // Must be called before the threads start below. 390 StartThreads(); 391 } 392 393 void StartThreads() { 394 quit_.store(false); 395 396 const auto attributes = 397 ThreadAttributes().SetPriority(ThreadPriority::kRealtime); 398 send_thread_ = PlatformThread::SpawnJoinable( 399 [this] { 400 while (!quit_.load()) { 401 CbSendImpl(); 402 } 403 }, 404 "send", attributes); 405 insert_packet_thread_ = PlatformThread::SpawnJoinable( 406 [this] { 407 while (!quit_.load()) { 408 CbInsertPacketImpl(); 409 } 410 }, 411 "insert_packet", attributes); 412 pull_audio_thread_ = PlatformThread::SpawnJoinable( 413 [this] { 414 while (!quit_.load()) { 415 CbPullAudioImpl(); 416 } 417 }, 418 "pull_audio", attributes); 419 } 420 421 void TearDown() override { 422 AudioCodingModuleTestOldApi::TearDown(); 423 quit_.store(true); 424 pull_audio_thread_.Finalize(); 425 send_thread_.Finalize(); 426 insert_packet_thread_.Finalize(); 427 } 428 429 bool RunTest() { return test_complete_.Wait(TimeDelta::Minutes(10)); } 430 431 virtual bool TestDone() { 432 if (packet_cb_.num_calls() > kNumPackets) { 433 MutexLock lock(&mutex_); 434 if (pull_audio_count_ > kNumPullCalls) { 435 // Both conditions for completion are met. End the test. 436 return true; 437 } 438 } 439 return false; 440 } 441 442 // The send thread doesn't have to care about the current simulated time, 443 // since only the AcmReceiver is using the clock. 444 void CbSendImpl() { 445 Thread::SleepMs(1); 446 if (HasFatalFailure()) { 447 // End the test early if a fatal failure (ASSERT_*) has occurred. 448 test_complete_.Set(); 449 } 450 ++send_count_; 451 InsertAudioAndVerifyEncoding(); 452 if (TestDone()) { 453 test_complete_.Set(); 454 } 455 } 456 457 void CbInsertPacketImpl() { 458 Thread::SleepMs(1); 459 { 460 MutexLock lock(&mutex_); 461 if (env_.clock().TimeInMilliseconds() < next_insert_packet_time_ms_) { 462 return; 463 } 464 next_insert_packet_time_ms_ += 10; 465 } 466 // Now we're not holding the crit sect when calling ACM. 467 ++insert_packet_count_; 468 InsertPacket(); 469 } 470 471 void CbPullAudioImpl() { 472 Thread::SleepMs(1); 473 { 474 MutexLock lock(&mutex_); 475 // Don't let the insert thread fall behind. 476 if (next_insert_packet_time_ms_ < env_.clock().TimeInMilliseconds()) { 477 return; 478 } 479 ++pull_audio_count_; 480 } 481 // Now we're not holding the crit sect when calling ACM. 482 PullAudio(); 483 fake_clock_->AdvanceTimeMilliseconds(10); 484 } 485 486 PlatformThread send_thread_; 487 PlatformThread insert_packet_thread_; 488 PlatformThread pull_audio_thread_; 489 // Used to force worker threads to stop looping. 490 std::atomic<bool> quit_; 491 492 Event test_complete_; 493 int send_count_; 494 int insert_packet_count_; 495 int pull_audio_count_ RTC_GUARDED_BY(mutex_); 496 Mutex mutex_; 497 int64_t next_insert_packet_time_ms_ RTC_GUARDED_BY(mutex_); 498 std::unique_ptr<SimulatedClock> fake_clock_; 499 }; 500 501 #if defined(WEBRTC_IOS) 502 #define MAYBE_DoTest DISABLED_DoTest 503 #else 504 #define MAYBE_DoTest DoTest 505 #endif 506 TEST_F(AudioCodingModuleMtTestOldApi, MAYBE_DoTest) { 507 EXPECT_TRUE(RunTest()); 508 } 509 510 class AudioPacketizationCallbackMock : public AudioPacketizationCallback { 511 public: 512 MOCK_METHOD(int32_t, 513 SendData, 514 (AudioFrameType frame_type, 515 uint8_t payload_type, 516 uint32_t timestamp, 517 const uint8_t* payload_data, 518 size_t payload_len_bytes, 519 int64_t absolute_capture_timestamp_ms), 520 (override)); 521 }; 522 523 TEST(AudioCodingModule, DoesResetEncoder) { 524 std::unique_ptr<AudioCodingModule> acm = AudioCodingModule::Create(); 525 auto encoder = std::make_unique<MockAudioEncoder>(); 526 MockAudioEncoder* encoder_mock = encoder.get(); 527 528 acm->SetEncoder(std::move(encoder)); 529 530 EXPECT_CALL(*encoder_mock, Reset()).Times(1); 531 acm->Reset(); 532 } 533 534 class AcmAbsoluteCaptureTimestamp : public ::testing::Test { 535 public: 536 AcmAbsoluteCaptureTimestamp() : audio_frame_(kSampleRateHz, kNumChannels) {} 537 538 protected: 539 static constexpr int kPTimeMs = 20; 540 static constexpr int kSampleRateHz = 48000; 541 static constexpr int kFrameSize = kSampleRateHz / 100; 542 static constexpr int kNumChannels = 2; 543 544 void SetUp() override { 545 scoped_refptr<AudioEncoderFactory> codec_factory = 546 CreateBuiltinAudioEncoderFactory(); 547 acm_ = AudioCodingModule::Create(); 548 std::unique_ptr<AudioEncoder> encoder = codec_factory->Create( 549 CreateEnvironment(), 550 SdpAudioFormat("OPUS", kSampleRateHz, kNumChannels), 551 {.payload_type = 111}); 552 encoder->SetDtx(true); 553 encoder->SetReceiverFrameLengthRange(kPTimeMs, kPTimeMs); 554 acm_->SetEncoder(std::move(encoder)); 555 acm_->RegisterTransportCallback(&transport_); 556 for (size_t k = 0; k < audio_.size(); ++k) { 557 audio_[k] = 10 * k; 558 } 559 } 560 561 const AudioFrame& GetAudioWithAbsoluteCaptureTimestamp( 562 int64_t absolute_capture_timestamp_ms) { 563 audio_frame_.ResetWithoutMuting(); 564 audio_frame_.UpdateFrame(timestamp_, audio_.data(), kFrameSize, 565 kSampleRateHz, 566 AudioFrame::SpeechType::kNormalSpeech, 567 AudioFrame::VADActivity::kVadActive, kNumChannels); 568 audio_frame_.set_absolute_capture_timestamp_ms( 569 absolute_capture_timestamp_ms); 570 timestamp_ += kFrameSize; 571 return audio_frame_; 572 } 573 574 std::unique_ptr<AudioCodingModule> acm_; 575 AudioPacketizationCallbackMock transport_; 576 AudioFrame audio_frame_; 577 std::array<int16_t, kFrameSize * kNumChannels> audio_; 578 uint32_t timestamp_ = 9873546; 579 }; 580 581 TEST_F(AcmAbsoluteCaptureTimestamp, HaveBeginningOfFrameCaptureTime) { 582 constexpr int64_t first_absolute_capture_timestamp_ms = 123456789; 583 584 int64_t absolute_capture_timestamp_ms = first_absolute_capture_timestamp_ms; 585 EXPECT_CALL(transport_, 586 SendData(_, _, _, _, _, first_absolute_capture_timestamp_ms)) 587 .Times(1); 588 EXPECT_CALL( 589 transport_, 590 SendData(_, _, _, _, _, first_absolute_capture_timestamp_ms + kPTimeMs)) 591 .Times(1); 592 for (int k = 0; k < 5; ++k) { 593 acm_->Add10MsData( 594 GetAudioWithAbsoluteCaptureTimestamp(absolute_capture_timestamp_ms)); 595 absolute_capture_timestamp_ms += 10; 596 } 597 } 598 599 TEST_F(AcmAbsoluteCaptureTimestamp, DoesResetWhenAudioCodingModuleDo) { 600 constexpr int64_t first_absolute_capture_timestamp_ms = 123456789; 601 602 int64_t absolute_capture_timestamp_ms = first_absolute_capture_timestamp_ms; 603 EXPECT_CALL(transport_, 604 SendData(_, _, _, _, _, first_absolute_capture_timestamp_ms)) 605 .Times(1); 606 EXPECT_CALL( 607 transport_, 608 SendData(_, _, _, _, _, first_absolute_capture_timestamp_ms + kPTimeMs)) 609 .Times(1); 610 for (int k = 0; k < 5; ++k) { 611 acm_->Add10MsData( 612 GetAudioWithAbsoluteCaptureTimestamp(absolute_capture_timestamp_ms)); 613 absolute_capture_timestamp_ms += 10; 614 } 615 616 acm_->Reset(); 617 constexpr int64_t after_reset_absolute_capture_timestamp_ms = 523456789; 618 EXPECT_CALL(transport_, SendData(_, _, _, _, _, 619 after_reset_absolute_capture_timestamp_ms)) 620 .Times(1); 621 EXPECT_CALL(transport_, 622 SendData(_, _, _, _, _, 623 after_reset_absolute_capture_timestamp_ms + kPTimeMs)) 624 .Times(1); 625 absolute_capture_timestamp_ms = after_reset_absolute_capture_timestamp_ms; 626 for (int k = 0; k < 5; ++k) { 627 acm_->Add10MsData( 628 GetAudioWithAbsoluteCaptureTimestamp(absolute_capture_timestamp_ms)); 629 absolute_capture_timestamp_ms += 10; 630 } 631 } 632 633 // Disabling all of these tests on iOS until file support has been added. 634 // See https://code.google.com/p/webrtc/issues/detail?id=4752 for details. 635 #if !defined(WEBRTC_IOS) 636 637 // This test verifies bit exactness for the send-side of ACM. The test setup is 638 // a chain of three different test classes: 639 // 640 // test::AcmSendTest -> AcmSenderBitExactness -> test::AcmReceiveTest 641 // 642 // The receiver side is driving the test by requesting new packets from 643 // AcmSenderBitExactness::NextPacket(). This method, in turn, asks for the 644 // packet from test::AcmSendTest::NextPacket, which inserts audio from the 645 // input file until one packet is produced. (The input file loops indefinitely.) 646 // Before passing the packet to the receiver, this test class verifies the 647 // packet header and updates a payload checksum with the new payload. The 648 // decoded output from the receiver is also verified with a (separate) checksum. 649 class AcmSenderBitExactnessOldApi : public ::testing::Test, 650 public test::PacketSource { 651 protected: 652 static const int kTestDurationMs = 1000; 653 654 AcmSenderBitExactnessOldApi() 655 : frame_size_rtp_timestamps_(0), 656 packet_count_(0), 657 payload_type_(0), 658 last_sequence_number_(0), 659 last_timestamp_(0), 660 payload_checksum_(MessageDigestFactory::Create(DIGEST_MD5)) {} 661 662 // Sets up the test::AcmSendTest object. Returns true on success, otherwise 663 // false. 664 bool SetUpSender(absl::string_view input_file_name, int source_rate) { 665 // Note that `audio_source_` will loop forever. The test duration is set 666 // explicitly by `kTestDurationMs`. 667 audio_source_.reset(new test::InputAudioFile(input_file_name)); 668 send_test_.reset(new test::AcmSendTestOldApi(audio_source_.get(), 669 source_rate, kTestDurationMs)); 670 return send_test_ != nullptr; 671 } 672 673 // Registers a send codec in the test::AcmSendTest object. Returns true on 674 // success, false on failure. 675 bool RegisterSendCodec(absl::string_view payload_name, 676 int sampling_freq_hz, 677 int channels, 678 int payload_type, 679 int frame_size_samples, 680 int frame_size_rtp_timestamps) { 681 payload_type_ = payload_type; 682 frame_size_rtp_timestamps_ = frame_size_rtp_timestamps; 683 return send_test_->RegisterCodec(payload_name, sampling_freq_hz, channels, 684 payload_type, frame_size_samples); 685 } 686 687 void RegisterExternalSendCodec( 688 std::unique_ptr<AudioEncoder> external_speech_encoder, 689 int payload_type) { 690 payload_type_ = payload_type; 691 frame_size_rtp_timestamps_ = checked_cast<uint32_t>( 692 external_speech_encoder->Num10MsFramesInNextPacket() * 693 external_speech_encoder->RtpTimestampRateHz() / 100); 694 send_test_->RegisterExternalCodec(std::move(external_speech_encoder)); 695 } 696 697 // Runs the test. SetUpSender() and RegisterSendCodec() must have been called 698 // before calling this method. 699 void Run(absl::string_view audio_checksum_ref, 700 absl::string_view payload_checksum_ref, 701 int expected_packets, 702 test::AcmReceiveTestOldApi::NumOutputChannels expected_channels, 703 scoped_refptr<AudioDecoderFactory> decoder_factory = nullptr) { 704 if (!decoder_factory) { 705 decoder_factory = CreateBuiltinAudioDecoderFactory(); 706 } 707 // Set up the receiver used to decode the packets and verify the decoded 708 // output. 709 test::AudioChecksum audio_checksum; 710 const std::string output_file_name = 711 test::OutputPath() + 712 ::testing::UnitTest::GetInstance() 713 ->current_test_info() 714 ->test_case_name() + 715 "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() + 716 "_output.wav"; 717 const int kOutputFreqHz = 8000; 718 test::OutputWavFile output_file(output_file_name, kOutputFreqHz, 719 expected_channels); 720 // Have the output audio sent both to file and to the checksum calculator. 721 test::AudioSinkFork output(&audio_checksum, &output_file); 722 test::AcmReceiveTestOldApi receive_test(this, &output, kOutputFreqHz, 723 expected_channels, decoder_factory); 724 ASSERT_NO_FATAL_FAILURE(receive_test.RegisterDefaultCodecs()); 725 726 // This is where the actual test is executed. 727 receive_test.Run(); 728 729 // Extract and verify the audio checksum. 730 std::string checksum_string = audio_checksum.Finish(); 731 ExpectChecksumEq(audio_checksum_ref, checksum_string); 732 733 // Extract and verify the payload checksum. 734 Buffer checksum_result(payload_checksum_->Size()); 735 payload_checksum_->Finish(checksum_result.data(), checksum_result.size()); 736 checksum_string = hex_encode(checksum_result); 737 ExpectChecksumEq(payload_checksum_ref, checksum_string); 738 739 // Verify number of packets produced. 740 EXPECT_EQ(expected_packets, packet_count_); 741 742 // Delete the output file. 743 remove(output_file_name.c_str()); 744 } 745 746 // Helper: result must be one the "|"-separated checksums. 747 void ExpectChecksumEq(absl::string_view ref, absl::string_view result) { 748 if (ref.size() == result.size()) { 749 // Only one checksum: clearer message. 750 EXPECT_EQ(ref, result); 751 } else { 752 EXPECT_NE(ref.find(result), absl::string_view::npos) 753 << result << " must be one of these:\n" 754 << ref; 755 } 756 } 757 758 // Inherited from test::PacketSource. 759 std::unique_ptr<RtpPacketReceived> NextPacket() override { 760 auto packet = send_test_->NextPacket(); 761 if (!packet) 762 return nullptr; 763 764 VerifyPacket(packet.get()); 765 // TODO(henrik.lundin) Save the packet to file as well. 766 767 // Pass it on to the caller. The caller becomes the owner of `packet`. 768 return packet; 769 } 770 771 // Verifies the packet. 772 void VerifyPacket(const RtpPacketReceived* packet) { 773 // (We can check the header fields even if valid_header() is false.) 774 EXPECT_EQ(payload_type_, packet->PayloadType()); 775 if (packet_count_ > 0) { 776 // This is not the first packet. 777 uint16_t sequence_number_diff = 778 packet->SequenceNumber() - last_sequence_number_; 779 EXPECT_EQ(1, sequence_number_diff); 780 uint32_t timestamp_diff = packet->Timestamp() - last_timestamp_; 781 EXPECT_EQ(frame_size_rtp_timestamps_, timestamp_diff); 782 } 783 ++packet_count_; 784 last_sequence_number_ = packet->SequenceNumber(); 785 last_timestamp_ = packet->Timestamp(); 786 // Update the checksum. 787 payload_checksum_->Update(packet->payload().data(), 788 packet->payload().size()); 789 } 790 791 void SetUpTest(absl::string_view codec_name, 792 int codec_sample_rate_hz, 793 int channels, 794 int payload_type, 795 int codec_frame_size_samples, 796 int codec_frame_size_rtp_timestamps) { 797 ASSERT_TRUE(SetUpSender( 798 channels == 1 ? kTestFileMono32kHz : kTestFileFakeStereo32kHz, 32000)); 799 ASSERT_TRUE(RegisterSendCodec(codec_name, codec_sample_rate_hz, channels, 800 payload_type, codec_frame_size_samples, 801 codec_frame_size_rtp_timestamps)); 802 } 803 804 void SetUpTestExternalEncoder( 805 std::unique_ptr<AudioEncoder> external_speech_encoder, 806 int payload_type) { 807 ASSERT_TRUE(send_test_); 808 RegisterExternalSendCodec(std::move(external_speech_encoder), payload_type); 809 } 810 811 std::unique_ptr<test::AcmSendTestOldApi> send_test_; 812 std::unique_ptr<test::InputAudioFile> audio_source_; 813 uint32_t frame_size_rtp_timestamps_; 814 int packet_count_; 815 uint8_t payload_type_; 816 uint16_t last_sequence_number_; 817 uint32_t last_timestamp_; 818 std::unique_ptr<MessageDigest> payload_checksum_; 819 const std::string kTestFileMono32kHz = 820 test::ResourcePath("audio_coding/testfile32kHz", "pcm"); 821 const std::string kTestFileFakeStereo32kHz = 822 test::ResourcePath("audio_coding/testfile_fake_stereo_32kHz", "pcm"); 823 const std::string kTestFileQuad48kHz = 824 test::ResourcePath("audio_coding/speech_4_channels_48k_one_second", 825 "wav"); 826 }; 827 828 class AcmSenderBitExactnessNewApi : public AcmSenderBitExactnessOldApi {}; 829 830 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_8000khz_10ms) { 831 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 1, 107, 80, 80)); 832 Run(/*audio_checksum_ref=*/"3e43fd5d3c73a59e8118e68fbfafe2c7", 833 /*payload_checksum_ref=*/"c1edd36339ce0326cc4550041ad719a0", 834 /*expected_packets=*/100, 835 /*expected_channels=*/test::AcmReceiveTestOldApi::kMonoOutput); 836 } 837 838 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_16000khz_10ms) { 839 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 1, 108, 160, 160)); 840 Run(/*audio_checksum_ref=*/"608750138315cbab33d76d38e8367807", 841 /*payload_checksum_ref=*/"ad786526383178b08d80d6eee06e9bad", 842 /*expected_packets=*/100, 843 /*expected_channels=*/test::AcmReceiveTestOldApi::kMonoOutput); 844 } 845 846 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_32000khz_10ms) { 847 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 1, 109, 320, 320)); 848 Run(/*audio_checksum_ref=*/"02e9927ef5e4d2cd792a5df0bdee5e19", 849 /*payload_checksum_ref=*/"5ef82ea885e922263606c6fdbc49f651", 850 /*expected_packets=*/100, 851 /*expected_channels=*/test::AcmReceiveTestOldApi::kMonoOutput); 852 } 853 854 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_8000khz_10ms) { 855 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 8000, 2, 111, 80, 80)); 856 Run(/*audio_checksum_ref=*/"4ff38de045b19f64de9c7e229ba36317", 857 /*payload_checksum_ref=*/"62ce5adb0d4965d0a52ec98ae7f98974", 858 /*expected_packets=*/100, 859 /*expected_channels=*/test::AcmReceiveTestOldApi::kStereoOutput); 860 } 861 862 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_16000khz_10ms) { 863 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 16000, 2, 112, 160, 160)); 864 Run(/*audio_checksum_ref=*/"1ee35394cfca78ad6d55468441af36fa", 865 /*payload_checksum_ref=*/"41ca8edac4b8c71cd54fd9f25ec14870", 866 /*expected_packets=*/100, 867 /*expected_channels=*/test::AcmReceiveTestOldApi::kStereoOutput); 868 } 869 870 TEST_F(AcmSenderBitExactnessOldApi, Pcm16_stereo_32000khz_10ms) { 871 ASSERT_NO_FATAL_FAILURE(SetUpTest("L16", 32000, 2, 113, 320, 320)); 872 Run(/*audio_checksum_ref=*/"19cae34730a0f6a17cf4e76bf21b69d6", 873 /*payload_checksum_ref=*/"50e58502fb04421bf5b857dda4c96879", 874 /*expected_packets=*/100, 875 /*expected_channels=*/test::AcmReceiveTestOldApi::kStereoOutput); 876 } 877 878 TEST_F(AcmSenderBitExactnessOldApi, Pcmu_20ms) { 879 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMU", 8000, 1, 0, 160, 160)); 880 Run(/*audio_checksum_ref=*/"c8d1fc677f33c2022ec5f83c7f302280", 881 /*payload_checksum_ref=*/"8f9b8750bd80fe26b6cbf6659b89f0f9", 882 /*expected_packets=*/50, 883 /*expected_channels=*/test::AcmReceiveTestOldApi::kMonoOutput); 884 } 885 886 TEST_F(AcmSenderBitExactnessOldApi, Pcma_20ms) { 887 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMA", 8000, 1, 8, 160, 160)); 888 Run(/*audio_checksum_ref=*/"ae259cab624095270b7369e53a7b53a3", 889 /*payload_checksum_ref=*/"6ad745e55aa48981bfc790d0eeef2dd1", 890 /*expected_packets=*/50, 891 /*expected_channels=*/test::AcmReceiveTestOldApi::kMonoOutput); 892 } 893 894 TEST_F(AcmSenderBitExactnessOldApi, Pcmu_stereo_20ms) { 895 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMU", 8000, 2, 110, 160, 160)); 896 Run(/*audio_checksum_ref=*/"6ef2f57d4934714787fd0a834e3ea18e", 897 /*payload_checksum_ref=*/"60b6f25e8d1e74cb679cfe756dd9bca5", 898 /*expected_packets=*/50, 899 /*expected_channels=*/test::AcmReceiveTestOldApi::kStereoOutput); 900 } 901 902 TEST_F(AcmSenderBitExactnessOldApi, Pcma_stereo_20ms) { 903 ASSERT_NO_FATAL_FAILURE(SetUpTest("PCMA", 8000, 2, 118, 160, 160)); 904 Run(/*audio_checksum_ref=*/"f2e81d2531a805c40e61da5106b50006", 905 /*payload_checksum_ref=*/"92b282c83efd20e7eeef52ba40842cf7", 906 /*expected_packets=*/50, 907 /*expected_channels=*/test::AcmReceiveTestOldApi::kStereoOutput); 908 } 909 910 #if defined(WEBRTC_LINUX) && defined(WEBRTC_ARCH_X86_64) 911 912 // TODO(bugs.webrtc.org/345525069): Either fix/enable or remove G722. 913 #if defined(__has_feature) && __has_feature(undefined_behavior_sanitizer) 914 TEST_F(AcmSenderBitExactnessOldApi, DISABLED_G722_20ms) { 915 #else 916 TEST_F(AcmSenderBitExactnessOldApi, G722_20ms) { 917 #endif 918 ASSERT_NO_FATAL_FAILURE(SetUpTest("G722", 16000, 1, 9, 320, 160)); 919 Run(/*audio_checksum_ref=*/"b875d9a3e41f5470857bdff02e3b368f", 920 /*payload_checksum_ref=*/"fc68a87e1380614e658087cb35d5ca10", 921 /*expected_packets=*/50, 922 /*expected_channels=*/test::AcmReceiveTestOldApi::kMonoOutput); 923 } 924 #endif 925 926 #if defined(WEBRTC_LINUX) && defined(WEBRTC_ARCH_X86_64) 927 928 // TODO(bugs.webrtc.org/345525069): Either fix/enable or remove G722. 929 #if defined(__has_feature) && __has_feature(undefined_behavior_sanitizer) 930 TEST_F(AcmSenderBitExactnessOldApi, DISABLED_G722_stereo_20ms) { 931 #else 932 TEST_F(AcmSenderBitExactnessOldApi, G722_stereo_20ms) { 933 #endif 934 ASSERT_NO_FATAL_FAILURE(SetUpTest("G722", 16000, 2, 119, 320, 160)); 935 Run(/*audio_checksum_ref=*/"02c427d73363b2f37853a0dd17fe1aba", 936 /*payload_checksum_ref=*/"66516152eeaa1e650ad94ff85f668dac", 937 /*expected_packets=*/50, 938 /*expected_channels=*/test::AcmReceiveTestOldApi::kStereoOutput); 939 } 940 #endif 941 942 namespace { 943 // Checksum depends on libopus being compiled with or without SSE. 944 const std::string audio_checksum = 945 "6a76fe2ffba057c06eb63239b3c47abe" 946 "|0c4f9d33b4a7379a34ee0c0d5718afe6"; 947 const std::string payload_checksum = 948 "b43bdf7638b2bc2a5a6f30bdc640b9ed" 949 "|c30d463e7ed10bdd1da9045f80561f27"; 950 } // namespace 951 952 #if defined(WEBRTC_LINUX) && defined(WEBRTC_ARCH_X86_64) 953 TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms) { 954 ASSERT_NO_FATAL_FAILURE(SetUpTest("opus", 48000, 2, 120, 960, 960)); 955 Run(audio_checksum, payload_checksum, /*expected_packets=*/50, 956 /*expected_channels=*/test::AcmReceiveTestOldApi::kStereoOutput); 957 } 958 #endif 959 960 #if defined(WEBRTC_LINUX) && defined(WEBRTC_ARCH_X86_64) 961 TEST_F(AcmSenderBitExactnessNewApi, OpusFromFormat_stereo_20ms) { 962 const auto config = AudioEncoderOpus::SdpToConfig( 963 SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}})); 964 ASSERT_TRUE(SetUpSender(kTestFileFakeStereo32kHz, 32000)); 965 ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder( 966 AudioEncoderOpus::MakeAudioEncoder(CreateEnvironment(), *config, 967 {.payload_type = 120}), 968 120)); 969 Run(audio_checksum, payload_checksum, /*expected_packets=*/50, 970 /*expected_channels=*/test::AcmReceiveTestOldApi::kStereoOutput); 971 } 972 #endif 973 974 // TODO(webrtc:8649): Disabled until the Encoder counterpart of 975 // https://webrtc-review.googlesource.com/c/src/+/129768 lands. 976 #if defined(WEBRTC_LINUX) && defined(WEBRTC_ARCH_X86_64) 977 TEST_F(AcmSenderBitExactnessNewApi, DISABLED_OpusManyChannels) { 978 constexpr int kNumChannels = 4; 979 constexpr int kOpusPayloadType = 120; 980 981 // Read a 4 channel file at 48kHz. 982 ASSERT_TRUE(SetUpSender(kTestFileQuad48kHz, 48000)); 983 984 const auto sdp_format = SdpAudioFormat("multiopus", 48000, kNumChannels, 985 {{"channel_mapping", "0,1,2,3"}, 986 {"coupled_streams", "2"}, 987 {"num_streams", "2"}}); 988 const auto encoder_config = 989 AudioEncoderMultiChannelOpus::SdpToConfig(sdp_format); 990 991 ASSERT_TRUE(encoder_config.has_value()); 992 993 ASSERT_NO_FATAL_FAILURE( 994 SetUpTestExternalEncoder(AudioEncoderMultiChannelOpus::MakeAudioEncoder( 995 *encoder_config, kOpusPayloadType), 996 kOpusPayloadType)); 997 998 const auto decoder_config = 999 AudioDecoderMultiChannelOpus::SdpToConfig(sdp_format); 1000 const auto opus_decoder = 1001 AudioDecoderMultiChannelOpus::MakeAudioDecoder(*decoder_config); 1002 1003 scoped_refptr<AudioDecoderFactory> decoder_factory = 1004 make_ref_counted<test::AudioDecoderProxyFactory>(opus_decoder.get()); 1005 1006 // Set up an EXTERNAL DECODER to parse 4 channels. 1007 Run("audio checksum check downstream|8051617907766bec5f4e4a4f7c6d5291", 1008 "payload checksum check downstream|b09c52e44b2bdd9a0809e3a5b1623a76", 1009 /*expected_packets=*/50, 1010 /*expected_channels=*/test::AcmReceiveTestOldApi::kQuadOutput, 1011 decoder_factory); 1012 } 1013 #endif 1014 1015 #if defined(WEBRTC_LINUX) && defined(WEBRTC_ARCH_X86_64) 1016 TEST_F(AcmSenderBitExactnessNewApi, OpusFromFormat_stereo_20ms_voip) { 1017 auto config = AudioEncoderOpus::SdpToConfig( 1018 SdpAudioFormat("opus", 48000, 2, {{"stereo", "1"}})); 1019 // If not set, default will be kAudio in case of stereo. 1020 config->application = AudioEncoderOpusConfig::ApplicationMode::kVoip; 1021 ASSERT_TRUE(SetUpSender(kTestFileFakeStereo32kHz, 32000)); 1022 ASSERT_NO_FATAL_FAILURE(SetUpTestExternalEncoder( 1023 AudioEncoderOpus::MakeAudioEncoder(CreateEnvironment(), *config, 1024 {.payload_type = 120}), 1025 120)); 1026 const std::string audio_maybe_sse = 1027 "cb644fc17d9666a0f5986eef24818159" 1028 "|4a74024473c7c729543c2790829b1e42"; 1029 1030 const std::string payload_maybe_sse = 1031 "ea48d94e43217793af9b7e15ece94e54" 1032 "|bd93c492087093daf662cdd968f6cdda"; 1033 1034 Run(audio_maybe_sse, payload_maybe_sse, /*expected_packets=*/50, 1035 /*expected_channels=*/test::AcmReceiveTestOldApi::kStereoOutput); 1036 } 1037 #endif 1038 1039 // This test is for verifying the SetBitRate function. The bitrate is changed at 1040 // the beginning, and the number of generated bytes are checked. 1041 class AcmSetBitRateTest : public ::testing::Test { 1042 protected: 1043 static const int kTestDurationMs = 1000; 1044 1045 // Sets up the test::AcmSendTest object. Returns true on success, otherwise 1046 // false. 1047 bool SetUpSender() { 1048 const std::string input_file_name = 1049 test::ResourcePath("audio_coding/testfile32kHz", "pcm"); 1050 // Note that `audio_source_` will loop forever. The test duration is set 1051 // explicitly by `kTestDurationMs`. 1052 audio_source_.reset(new test::InputAudioFile(input_file_name)); 1053 static const int kSourceRateHz = 32000; 1054 send_test_.reset(new test::AcmSendTestOldApi( 1055 audio_source_.get(), kSourceRateHz, kTestDurationMs)); 1056 return send_test_.get(); 1057 } 1058 1059 // Registers a send codec in the test::AcmSendTest object. Returns true on 1060 // success, false on failure. 1061 virtual bool RegisterSendCodec(absl::string_view payload_name, 1062 int sampling_freq_hz, 1063 int channels, 1064 int payload_type, 1065 int frame_size_samples, 1066 int /* frame_size_rtp_timestamps */) { 1067 return send_test_->RegisterCodec(payload_name, sampling_freq_hz, channels, 1068 payload_type, frame_size_samples); 1069 } 1070 1071 void RegisterExternalSendCodec( 1072 std::unique_ptr<AudioEncoder> external_speech_encoder, 1073 int /* payload_type */) { 1074 send_test_->RegisterExternalCodec(std::move(external_speech_encoder)); 1075 } 1076 1077 void RunInner(int min_expected_total_bits, int max_expected_total_bits) { 1078 int nr_bytes = 0; 1079 while (std::unique_ptr<RtpPacketReceived> next_packet = 1080 send_test_->NextPacket()) { 1081 nr_bytes += checked_cast<int>(next_packet->payload_size()); 1082 } 1083 EXPECT_LE(min_expected_total_bits, nr_bytes * 8); 1084 EXPECT_GE(max_expected_total_bits, nr_bytes * 8); 1085 } 1086 1087 void SetUpTest(absl::string_view codec_name, 1088 int codec_sample_rate_hz, 1089 int channels, 1090 int payload_type, 1091 int codec_frame_size_samples, 1092 int codec_frame_size_rtp_timestamps) { 1093 ASSERT_TRUE(SetUpSender()); 1094 ASSERT_TRUE(RegisterSendCodec(codec_name, codec_sample_rate_hz, channels, 1095 payload_type, codec_frame_size_samples, 1096 codec_frame_size_rtp_timestamps)); 1097 } 1098 1099 std::unique_ptr<test::AcmSendTestOldApi> send_test_; 1100 std::unique_ptr<test::InputAudioFile> audio_source_; 1101 }; 1102 1103 class AcmSetBitRateNewApi : public AcmSetBitRateTest { 1104 protected: 1105 // Runs the test. SetUpSender() must have been called and a codec must be set 1106 // up before calling this method. 1107 void Run(int min_expected_total_bits, int max_expected_total_bits) { 1108 RunInner(min_expected_total_bits, max_expected_total_bits); 1109 } 1110 }; 1111 1112 TEST_F(AcmSetBitRateNewApi, OpusFromFormat_48khz_20ms_10kbps) { 1113 const auto config = AudioEncoderOpus::SdpToConfig( 1114 SdpAudioFormat("opus", 48000, 2, {{"maxaveragebitrate", "10000"}})); 1115 ASSERT_TRUE(SetUpSender()); 1116 RegisterExternalSendCodec( 1117 AudioEncoderOpus::MakeAudioEncoder(CreateEnvironment(), *config, 1118 {.payload_type = 107}), 1119 107); 1120 RunInner(7000, 12000); 1121 } 1122 1123 TEST_F(AcmSetBitRateNewApi, OpusFromFormat_48khz_20ms_50kbps) { 1124 const auto config = AudioEncoderOpus::SdpToConfig( 1125 SdpAudioFormat("opus", 48000, 2, {{"maxaveragebitrate", "50000"}})); 1126 ASSERT_TRUE(SetUpSender()); 1127 RegisterExternalSendCodec( 1128 AudioEncoderOpus::MakeAudioEncoder(CreateEnvironment(), *config, 1129 {.payload_type = 107}), 1130 107); 1131 RunInner(40000, 60000); 1132 } 1133 1134 // Verify that it works when the data to send is mono and the encoder is set to 1135 // send surround audio. 1136 TEST_F(AudioCodingModuleTestOldApi, SendingMultiChannelForMonoInput) { 1137 constexpr int kSampleRateHz = 48000; 1138 constexpr int kSamplesPerChannel = kSampleRateHz * 10 / 1000; 1139 1140 audio_format_ = SdpAudioFormat({"multiopus", 1141 kSampleRateHz, 1142 6, 1143 {{"minptime", "10"}, 1144 {"useinbandfec", "1"}, 1145 {"channel_mapping", "0,4,1,2,3,5"}, 1146 {"num_streams", "4"}, 1147 {"coupled_streams", "2"}}}); 1148 1149 RegisterCodec(); 1150 1151 input_frame_.sample_rate_hz_ = kSampleRateHz; 1152 input_frame_.num_channels_ = 1; 1153 input_frame_.samples_per_channel_ = kSamplesPerChannel; 1154 for (size_t k = 0; k < 10; ++k) { 1155 ASSERT_GE(acm_->Add10MsData(input_frame_), 0); 1156 input_frame_.timestamp_ += kSamplesPerChannel; 1157 } 1158 } 1159 1160 // Verify that it works when the data to send is stereo and the encoder is set 1161 // to send surround audio. 1162 TEST_F(AudioCodingModuleTestOldApi, SendingMultiChannelForStereoInput) { 1163 constexpr int kSampleRateHz = 48000; 1164 constexpr int kSamplesPerChannel = (kSampleRateHz * 10) / 1000; 1165 1166 audio_format_ = SdpAudioFormat({"multiopus", 1167 kSampleRateHz, 1168 6, 1169 {{"minptime", "10"}, 1170 {"useinbandfec", "1"}, 1171 {"channel_mapping", "0,4,1,2,3,5"}, 1172 {"num_streams", "4"}, 1173 {"coupled_streams", "2"}}}); 1174 1175 RegisterCodec(); 1176 1177 input_frame_.sample_rate_hz_ = kSampleRateHz; 1178 input_frame_.num_channels_ = 2; 1179 input_frame_.samples_per_channel_ = kSamplesPerChannel; 1180 for (size_t k = 0; k < 10; ++k) { 1181 ASSERT_GE(acm_->Add10MsData(input_frame_), 0); 1182 input_frame_.timestamp_ += kSamplesPerChannel; 1183 } 1184 } 1185 1186 // Verify that it works when the data to send is mono and the encoder is set to 1187 // send stereo audio. 1188 TEST_F(AudioCodingModuleTestOldApi, SendingStereoForMonoInput) { 1189 constexpr int kSampleRateHz = 48000; 1190 constexpr int kSamplesPerChannel = (kSampleRateHz * 10) / 1000; 1191 1192 audio_format_ = SdpAudioFormat("L16", kSampleRateHz, 2); 1193 1194 RegisterCodec(); 1195 1196 input_frame_.sample_rate_hz_ = kSampleRateHz; 1197 input_frame_.num_channels_ = 1; 1198 input_frame_.samples_per_channel_ = kSamplesPerChannel; 1199 for (size_t k = 0; k < 10; ++k) { 1200 ASSERT_GE(acm_->Add10MsData(input_frame_), 0); 1201 input_frame_.timestamp_ += kSamplesPerChannel; 1202 } 1203 } 1204 1205 // Verify that it works when the data to send is stereo and the encoder is set 1206 // to send mono audio. 1207 TEST_F(AudioCodingModuleTestOldApi, SendingMonoForStereoInput) { 1208 constexpr int kSampleRateHz = 48000; 1209 constexpr int kSamplesPerChannel = (kSampleRateHz * 10) / 1000; 1210 1211 audio_format_ = SdpAudioFormat("L16", kSampleRateHz, 1); 1212 1213 RegisterCodec(); 1214 1215 input_frame_.sample_rate_hz_ = kSampleRateHz; 1216 input_frame_.num_channels_ = 1; 1217 input_frame_.samples_per_channel_ = kSamplesPerChannel; 1218 for (size_t k = 0; k < 10; ++k) { 1219 ASSERT_GE(acm_->Add10MsData(input_frame_), 0); 1220 input_frame_.timestamp_ += kSamplesPerChannel; 1221 } 1222 } 1223 1224 // The result on the Android platforms is inconsistent for this test case. 1225 // On android_rel the result is different from android and android arm64 rel. 1226 #if defined(WEBRTC_ANDROID) 1227 #define MAYBE_OpusFromFormat_48khz_20ms_100kbps \ 1228 DISABLED_OpusFromFormat_48khz_20ms_100kbps 1229 #else 1230 #define MAYBE_OpusFromFormat_48khz_20ms_100kbps \ 1231 OpusFromFormat_48khz_20ms_100kbps 1232 #endif 1233 TEST_F(AcmSetBitRateNewApi, MAYBE_OpusFromFormat_48khz_20ms_100kbps) { 1234 const auto config = AudioEncoderOpus::SdpToConfig( 1235 SdpAudioFormat("opus", 48000, 2, {{"maxaveragebitrate", "100000"}})); 1236 ASSERT_TRUE(SetUpSender()); 1237 RegisterExternalSendCodec( 1238 AudioEncoderOpus::MakeAudioEncoder(CreateEnvironment(), *config, 1239 {.payload_type = 107}), 1240 107); 1241 RunInner(80000, 120000); 1242 } 1243 1244 TEST_F(AcmSenderBitExactnessOldApi, External_Pcmu_20ms) { 1245 AudioEncoderPcmU::Config config; 1246 config.frame_size_ms = 20; 1247 config.num_channels = 1; 1248 config.payload_type = 0; 1249 AudioEncoderPcmU encoder(config); 1250 auto mock_encoder = std::make_unique<MockAudioEncoder>(); 1251 // Set expectations on the mock encoder and also delegate the calls to the 1252 // real encoder. 1253 EXPECT_CALL(*mock_encoder, SampleRateHz()) 1254 .Times(AtLeast(1)) 1255 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::SampleRateHz)); 1256 EXPECT_CALL(*mock_encoder, NumChannels()) 1257 .Times(AtLeast(1)) 1258 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::NumChannels)); 1259 EXPECT_CALL(*mock_encoder, RtpTimestampRateHz()) 1260 .Times(AtLeast(1)) 1261 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::RtpTimestampRateHz)); 1262 EXPECT_CALL(*mock_encoder, Num10MsFramesInNextPacket()) 1263 .Times(AtLeast(1)) 1264 .WillRepeatedly( 1265 Invoke(&encoder, &AudioEncoderPcmU::Num10MsFramesInNextPacket)); 1266 EXPECT_CALL(*mock_encoder, GetTargetBitrate()) 1267 .Times(AtLeast(1)) 1268 .WillRepeatedly(Invoke(&encoder, &AudioEncoderPcmU::GetTargetBitrate)); 1269 EXPECT_CALL(*mock_encoder, EncodeImpl(_, _, _)) 1270 .Times(AtLeast(1)) 1271 .WillRepeatedly(Invoke( 1272 &encoder, static_cast<AudioEncoder::EncodedInfo (AudioEncoder::*)( 1273 uint32_t, ArrayView<const int16_t>, Buffer*)>( 1274 &AudioEncoderPcmU::Encode))); 1275 ASSERT_TRUE(SetUpSender(kTestFileMono32kHz, 32000)); 1276 ASSERT_NO_FATAL_FAILURE( 1277 SetUpTestExternalEncoder(std::move(mock_encoder), config.payload_type)); 1278 Run("c8d1fc677f33c2022ec5f83c7f302280", "8f9b8750bd80fe26b6cbf6659b89f0f9", 1279 50, test::AcmReceiveTestOldApi::kMonoOutput); 1280 } 1281 1282 // This test fixture is implemented to run ACM and change the desired output 1283 // frequency during the call. The input packets are simply PCM16b-wb encoded 1284 // payloads with a constant value of `kSampleValue`. The test fixture itself 1285 // acts as PacketSource in between the receive test class and the constant- 1286 // payload packet source class. The output is both written to file, and analyzed 1287 // in this test fixture. 1288 class AcmSwitchingOutputFrequencyOldApi : public ::testing::Test, 1289 public test::PacketSource, 1290 public test::AudioSink { 1291 protected: 1292 static const size_t kTestNumPackets = 50; 1293 static const int kEncodedSampleRateHz = 16000; 1294 static const size_t kPayloadLenSamples = 30 * kEncodedSampleRateHz / 1000; 1295 static const int kPayloadType = 108; // Default payload type for PCM16b-wb. 1296 1297 AcmSwitchingOutputFrequencyOldApi() 1298 : first_output_(true), 1299 num_packets_(0), 1300 packet_source_(kPayloadLenSamples, 1301 kSampleValue, 1302 kEncodedSampleRateHz, 1303 kPayloadType), 1304 output_freq_2_(0), 1305 has_toggled_(false) {} 1306 1307 void Run(int output_freq_1, int output_freq_2, int toggle_period_ms) { 1308 // Set up the receiver used to decode the packets and verify the decoded 1309 // output. 1310 const std::string output_file_name = 1311 test::OutputPath() + 1312 ::testing::UnitTest::GetInstance() 1313 ->current_test_info() 1314 ->test_case_name() + 1315 "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() + 1316 "_output.pcm"; 1317 test::OutputAudioFile output_file(output_file_name); 1318 // Have the output audio sent both to file and to the WriteArray method in 1319 // this class. 1320 test::AudioSinkFork output(this, &output_file); 1321 test::AcmReceiveTestToggleOutputFreqOldApi receive_test( 1322 this, &output, output_freq_1, output_freq_2, toggle_period_ms, 1323 test::AcmReceiveTestOldApi::kMonoOutput); 1324 ASSERT_NO_FATAL_FAILURE(receive_test.RegisterDefaultCodecs()); 1325 output_freq_2_ = output_freq_2; 1326 1327 // This is where the actual test is executed. 1328 receive_test.Run(); 1329 1330 // Delete output file. 1331 remove(output_file_name.c_str()); 1332 } 1333 1334 // Inherited from test::PacketSource. 1335 std::unique_ptr<RtpPacketReceived> NextPacket() override { 1336 // Check if it is time to terminate the test. The packet source is of type 1337 // ConstantPcmPacketSource, which is infinite, so we must end the test 1338 // "manually". 1339 if (num_packets_++ > kTestNumPackets) { 1340 EXPECT_TRUE(has_toggled_); 1341 return nullptr; // Test ended. 1342 } 1343 1344 // Get the next packet from the source. 1345 return packet_source_.NextPacket(); 1346 } 1347 1348 // Inherited from test::AudioSink. 1349 bool WriteArray(const int16_t* audio, size_t num_samples) override { 1350 // Skip checking the first output frame, since it has a number of zeros 1351 // due to how NetEq is initialized. 1352 if (first_output_) { 1353 first_output_ = false; 1354 return true; 1355 } 1356 for (size_t i = 0; i < num_samples; ++i) { 1357 EXPECT_EQ(kSampleValue, audio[i]); 1358 } 1359 if (num_samples == 1360 static_cast<size_t>(output_freq_2_ / 100)) // Size of 10 ms frame. 1361 has_toggled_ = true; 1362 // The return value does not say if the values match the expectation, just 1363 // that the method could process the samples. 1364 return true; 1365 } 1366 1367 const int16_t kSampleValue = 1000; 1368 bool first_output_; 1369 size_t num_packets_; 1370 test::ConstantPcmPacketSource packet_source_; 1371 int output_freq_2_; 1372 bool has_toggled_; 1373 }; 1374 1375 TEST_F(AcmSwitchingOutputFrequencyOldApi, TestWithoutToggling) { 1376 Run(16000, 16000, 1000); 1377 } 1378 1379 TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle16KhzTo32Khz) { 1380 Run(16000, 32000, 1000); 1381 } 1382 1383 TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle32KhzTo16Khz) { 1384 Run(32000, 16000, 1000); 1385 } 1386 1387 TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle16KhzTo8Khz) { 1388 Run(16000, 8000, 1000); 1389 } 1390 1391 TEST_F(AcmSwitchingOutputFrequencyOldApi, Toggle8KhzTo16Khz) { 1392 Run(8000, 16000, 1000); 1393 } 1394 1395 #endif 1396 1397 } // namespace webrtc