/* * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "audio/voip/audio_channel.h" #include "api/audio_codecs/builtin_audio_decoder_factory.h" #include "api/audio_codecs/builtin_audio_encoder_factory.h" #include "api/call/transport.h" #include "api/task_queue/default_task_queue_factory.h" #include "modules/audio_mixer/audio_mixer_impl.h" #include "modules/audio_mixer/sine_wave_generator.h" #include "modules/rtp_rtcp/source/rtp_packet_received.h" #include "modules/utility/include/process_thread.h" #include "rtc_base/event.h" #include "rtc_base/logging.h" #include "test/gmock.h" #include "test/gtest.h" #include "test/mock_transport.h" namespace webrtc { namespace { using ::testing::Invoke; using ::testing::NiceMock; using ::testing::Unused; constexpr uint64_t kStartTime = 123456789; constexpr uint32_t kLocalSsrc = 0xdeadc0de; constexpr int16_t kAudioLevel = 3004; // used for sine wave level constexpr int kPcmuPayload = 0; class AudioChannelTest : public ::testing::Test { public: const SdpAudioFormat kPcmuFormat = {"pcmu", 8000, 1}; AudioChannelTest() : fake_clock_(kStartTime), wave_generator_(1000.0, kAudioLevel) { process_thread_ = ProcessThread::Create("ModuleProcessThread"); audio_mixer_ = AudioMixerImpl::Create(); task_queue_factory_ = CreateDefaultTaskQueueFactory(); encoder_factory_ = CreateBuiltinAudioEncoderFactory(); decoder_factory_ = CreateBuiltinAudioDecoderFactory(); } void SetUp() override { audio_channel_ = new rtc::RefCountedObject( &transport_, kLocalSsrc, task_queue_factory_.get(), process_thread_.get(), audio_mixer_.get(), decoder_factory_); audio_channel_->SetEncoder(kPcmuPayload, kPcmuFormat, encoder_factory_->MakeAudioEncoder( kPcmuPayload, kPcmuFormat, absl::nullopt)); audio_channel_->SetReceiveCodecs({{kPcmuPayload, kPcmuFormat}}); audio_channel_->StartSend(); audio_channel_->StartPlay(); } void TearDown() override { audio_channel_->StopSend(); audio_channel_->StopPlay(); audio_channel_ = nullptr; } std::unique_ptr GetAudioFrame(int order) { auto frame = std::make_unique(); frame->sample_rate_hz_ = kPcmuFormat.clockrate_hz; frame->samples_per_channel_ = kPcmuFormat.clockrate_hz / 100; // 10 ms. frame->num_channels_ = kPcmuFormat.num_channels; frame->timestamp_ = frame->samples_per_channel_ * order; wave_generator_.GenerateNextFrame(frame.get()); return frame; } SimulatedClock fake_clock_; SineWaveGenerator wave_generator_; NiceMock transport_; std::unique_ptr task_queue_factory_; rtc::scoped_refptr audio_mixer_; rtc::scoped_refptr decoder_factory_; rtc::scoped_refptr encoder_factory_; std::unique_ptr process_thread_; rtc::scoped_refptr audio_channel_; }; // Validate RTP packet generation by feeding audio frames with sine wave. // Resulted RTP packet is looped back into AudioChannel and gets decoded into // audio frame to see if it has some signal to indicate its validity. TEST_F(AudioChannelTest, PlayRtpByLocalLoop) { rtc::Event event; auto loop_rtp = [&](const uint8_t* packet, size_t length, Unused) { audio_channel_->ReceivedRTPPacket( rtc::ArrayView(packet, length)); event.Set(); return true; }; EXPECT_CALL(transport_, SendRtp).WillOnce(Invoke(loop_rtp)); auto audio_sender = audio_channel_->GetAudioSender(); audio_sender->SendAudioData(GetAudioFrame(0)); audio_sender->SendAudioData(GetAudioFrame(1)); event.Wait(/*ms=*/1000); AudioFrame empty_frame, audio_frame; empty_frame.Mute(); empty_frame.mutable_data(); // This will zero out the data. audio_frame.CopyFrom(empty_frame); audio_mixer_->Mix(/*number_of_channels*/ 1, &audio_frame); // We expect now audio frame to pick up something. EXPECT_NE(memcmp(empty_frame.data(), audio_frame.data(), AudioFrame::kMaxDataSizeBytes), 0); } // Validate assigned local SSRC is resulted in RTP packet. TEST_F(AudioChannelTest, VerifyLocalSsrcAsAssigned) { RtpPacketReceived rtp; rtc::Event event; auto loop_rtp = [&](const uint8_t* packet, size_t length, Unused) { rtp.Parse(packet, length); event.Set(); return true; }; EXPECT_CALL(transport_, SendRtp).WillOnce(Invoke(loop_rtp)); auto audio_sender = audio_channel_->GetAudioSender(); audio_sender->SendAudioData(GetAudioFrame(0)); audio_sender->SendAudioData(GetAudioFrame(1)); event.Wait(/*ms=*/1000); EXPECT_EQ(rtp.Ssrc(), kLocalSsrc); } } // namespace } // namespace webrtc