// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "remoting/protocol/audio_pump.h" #include #include #include #include #include "base/memory/ptr_util.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/test/task_environment.h" #include "remoting/codec/audio_encoder.h" #include "remoting/proto/audio.pb.h" #include "remoting/protocol/audio_source.h" #include "remoting/protocol/audio_stub.h" #include "remoting/protocol/fake_audio_source.h" #include "testing/gtest/include/gtest/gtest.h" namespace remoting { namespace protocol { namespace { // Creates a dummy packet with 1k data std::unique_ptr MakeAudioPacket(int channel_count = 2) { std::unique_ptr packet(new AudioPacket); packet->add_data()->resize(1024); packet->set_encoding(AudioPacket::ENCODING_RAW); packet->set_sampling_rate(AudioPacket::SAMPLING_RATE_44100); packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2); packet->set_channels(static_cast(channel_count)); return packet; } } // namespace class FakeAudioEncoder : public AudioEncoder { public: FakeAudioEncoder() = default; FakeAudioEncoder(const FakeAudioEncoder&) = delete; FakeAudioEncoder& operator=(const FakeAudioEncoder&) = delete; ~FakeAudioEncoder() override = default; std::unique_ptr Encode( std::unique_ptr packet) override { EXPECT_TRUE(!!packet); EXPECT_EQ(packet->encoding(), AudioPacket::ENCODING_RAW); EXPECT_EQ(packet->sampling_rate(), AudioPacket::SAMPLING_RATE_44100); EXPECT_EQ(packet->bytes_per_sample(), AudioPacket::BYTES_PER_SAMPLE_2); EXPECT_LE(packet->channels(), AudioPacket::CHANNELS_STEREO); return packet; } int GetBitrate() override { return 160000; } }; class AudioPumpTest : public testing::Test, public protocol::AudioStub { public: AudioPumpTest() = default; AudioPumpTest(const AudioPumpTest&) = delete; AudioPumpTest& operator=(const AudioPumpTest&) = delete; void SetUp() override; void TearDown() override; // protocol::AudioStub interface. void ProcessAudioPacket(std::unique_ptr audio_packet, base::OnceClosure done) override; protected: base::test::SingleThreadTaskEnvironment task_environment_; // |source_| and |encoder_| are owned by the |pump_|. raw_ptr source_; raw_ptr encoder_; std::unique_ptr pump_; std::vector> sent_packets_; std::vector done_closures_; }; void AudioPumpTest::SetUp() { source_ = new FakeAudioSource(); encoder_ = new FakeAudioEncoder(); pump_ = std::make_unique( task_environment_.GetMainThreadTaskRunner(), base::WrapUnique(source_.get()), base::WrapUnique(encoder_.get()), this); } void AudioPumpTest::TearDown() { pump_.reset(); // Let the message loop run to finish destroying the capturer. base::RunLoop().RunUntilIdle(); } void AudioPumpTest::ProcessAudioPacket( std::unique_ptr audio_packet, base::OnceClosure done) { sent_packets_.push_back(std::move(audio_packet)); done_closures_.push_back(std::move(done)); } // Verify that the pump pauses pumping when the network is congested. TEST_F(AudioPumpTest, BufferSizeLimit) { // Run message loop to let the pump start the capturer. base::RunLoop().RunUntilIdle(); ASSERT_FALSE(source_->callback().is_null()); // Try sending 100 packets, 1k each. The pump should stop pumping and start // dropping the data at some point. for (size_t i = 0; i < 100; ++i) { source_->callback().Run(MakeAudioPacket()); base::RunLoop().RunUntilIdle(); } size_t num_sent_packets = sent_packets_.size(); EXPECT_LT(num_sent_packets, 100U); EXPECT_GT(num_sent_packets, 0U); // Call done closure for the first packet. This should allow one more packet // to be sent below. std::move(done_closures_.front()).Run(); base::RunLoop().RunUntilIdle(); // Verify that the pump continues to send captured audio. source_->callback().Run(MakeAudioPacket()); base::RunLoop().RunUntilIdle(); EXPECT_EQ(num_sent_packets + 1, sent_packets_.size()); } TEST_F(AudioPumpTest, DownmixAudioPacket) { // Run message loop to let the pump start the capturer. base::RunLoop().RunUntilIdle(); ASSERT_TRUE(source_->callback()); // Generate several audio packets with different channel counts. static const int kChannels[] = { AudioPacket::CHANNELS_7_1, AudioPacket::CHANNELS_6_1, AudioPacket::CHANNELS_5_1, AudioPacket::CHANNELS_STEREO, AudioPacket::CHANNELS_MONO, AudioPacket::CHANNELS_7_1, AudioPacket::CHANNELS_7_1, AudioPacket::CHANNELS_7_1, AudioPacket::CHANNELS_7_1, AudioPacket::CHANNELS_6_1, AudioPacket::CHANNELS_6_1, AudioPacket::CHANNELS_6_1, AudioPacket::CHANNELS_6_1, AudioPacket::CHANNELS_5_1, AudioPacket::CHANNELS_5_1, AudioPacket::CHANNELS_5_1, AudioPacket::CHANNELS_5_1, AudioPacket::CHANNELS_STEREO, AudioPacket::CHANNELS_STEREO, AudioPacket::CHANNELS_STEREO, AudioPacket::CHANNELS_STEREO, AudioPacket::CHANNELS_MONO, AudioPacket::CHANNELS_MONO, AudioPacket::CHANNELS_MONO, AudioPacket::CHANNELS_MONO, }; for (size_t i = 0; i < std::size(kChannels); i++) { source_->callback().Run(MakeAudioPacket(kChannels[i])); // Run message loop to let the pump processes the audio packet and send it // to the encoder. base::RunLoop().RunUntilIdle(); // Call done closure to allow one more packet to be sent. ASSERT_EQ(done_closures_.size(), 1U); std::move(done_closures_.front()).Run(); done_closures_.pop_back(); base::RunLoop().RunUntilIdle(); } ASSERT_EQ(sent_packets_.size(), std::size(kChannels)); } } // namespace protocol } // namespace remoting