diff options
Diffstat (limited to 'third_party/libwebrtc/audio/test')
5 files changed, 411 insertions, 0 deletions
diff --git a/third_party/libwebrtc/audio/test/audio_end_to_end_test.cc b/third_party/libwebrtc/audio/test/audio_end_to_end_test.cc new file mode 100644 index 0000000000..b1e2712f60 --- /dev/null +++ b/third_party/libwebrtc/audio/test/audio_end_to_end_test.cc @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2017 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/test/audio_end_to_end_test.h" + +#include <algorithm> +#include <memory> + +#include "api/task_queue/task_queue_base.h" +#include "call/fake_network_pipe.h" +#include "call/simulated_network.h" +#include "modules/audio_device/include/test_audio_device.h" +#include "system_wrappers/include/sleep.h" +#include "test/gtest.h" +#include "test/video_test_constants.h" + +namespace webrtc { +namespace test { +namespace { + +constexpr int kSampleRate = 48000; + +} // namespace + +AudioEndToEndTest::AudioEndToEndTest() + : EndToEndTest(VideoTestConstants::kDefaultTimeout) {} + +size_t AudioEndToEndTest::GetNumVideoStreams() const { + return 0; +} + +size_t AudioEndToEndTest::GetNumAudioStreams() const { + return 1; +} + +size_t AudioEndToEndTest::GetNumFlexfecStreams() const { + return 0; +} + +std::unique_ptr<TestAudioDeviceModule::Capturer> +AudioEndToEndTest::CreateCapturer() { + return TestAudioDeviceModule::CreatePulsedNoiseCapturer(32000, kSampleRate); +} + +std::unique_ptr<TestAudioDeviceModule::Renderer> +AudioEndToEndTest::CreateRenderer() { + return TestAudioDeviceModule::CreateDiscardRenderer(kSampleRate); +} + +void AudioEndToEndTest::OnFakeAudioDevicesCreated( + AudioDeviceModule* send_audio_device, + AudioDeviceModule* recv_audio_device) { + send_audio_device_ = send_audio_device; +} + +void AudioEndToEndTest::ModifyAudioConfigs( + AudioSendStream::Config* send_config, + std::vector<AudioReceiveStreamInterface::Config>* receive_configs) { + // Large bitrate by default. + const webrtc::SdpAudioFormat kDefaultFormat("opus", 48000, 2, + {{"stereo", "1"}}); + send_config->send_codec_spec = AudioSendStream::Config::SendCodecSpec( + test::VideoTestConstants::kAudioSendPayloadType, kDefaultFormat); + send_config->min_bitrate_bps = 32000; + send_config->max_bitrate_bps = 32000; +} + +void AudioEndToEndTest::OnAudioStreamsCreated( + AudioSendStream* send_stream, + const std::vector<AudioReceiveStreamInterface*>& receive_streams) { + ASSERT_NE(nullptr, send_stream); + ASSERT_EQ(1u, receive_streams.size()); + ASSERT_NE(nullptr, receive_streams[0]); + send_stream_ = send_stream; + receive_stream_ = receive_streams[0]; +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/audio/test/audio_end_to_end_test.h b/third_party/libwebrtc/audio/test/audio_end_to_end_test.h new file mode 100644 index 0000000000..d326b790ff --- /dev/null +++ b/third_party/libwebrtc/audio/test/audio_end_to_end_test.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2017 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. + */ +#ifndef AUDIO_TEST_AUDIO_END_TO_END_TEST_H_ +#define AUDIO_TEST_AUDIO_END_TO_END_TEST_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "api/task_queue/task_queue_base.h" +#include "api/test/simulated_network.h" +#include "modules/audio_device/include/audio_device.h" +#include "modules/audio_device/include/test_audio_device.h" +#include "test/call_test.h" + +namespace webrtc { +namespace test { + +class AudioEndToEndTest : public test::EndToEndTest { + public: + AudioEndToEndTest(); + + protected: + AudioDeviceModule* send_audio_device() { return send_audio_device_; } + const AudioSendStream* send_stream() const { return send_stream_; } + const AudioReceiveStreamInterface* receive_stream() const { + return receive_stream_; + } + + size_t GetNumVideoStreams() const override; + size_t GetNumAudioStreams() const override; + size_t GetNumFlexfecStreams() const override; + + std::unique_ptr<TestAudioDeviceModule::Capturer> CreateCapturer() override; + std::unique_ptr<TestAudioDeviceModule::Renderer> CreateRenderer() override; + + void OnFakeAudioDevicesCreated(AudioDeviceModule* send_audio_device, + AudioDeviceModule* recv_audio_device) override; + + void ModifyAudioConfigs(AudioSendStream::Config* send_config, + std::vector<AudioReceiveStreamInterface::Config>* + receive_configs) override; + void OnAudioStreamsCreated(AudioSendStream* send_stream, + const std::vector<AudioReceiveStreamInterface*>& + receive_streams) override; + + private: + AudioDeviceModule* send_audio_device_ = nullptr; + AudioSendStream* send_stream_ = nullptr; + AudioReceiveStreamInterface* receive_stream_ = nullptr; +}; + +} // namespace test +} // namespace webrtc + +#endif // AUDIO_TEST_AUDIO_END_TO_END_TEST_H_ diff --git a/third_party/libwebrtc/audio/test/audio_stats_test.cc b/third_party/libwebrtc/audio/test/audio_stats_test.cc new file mode 100644 index 0000000000..e8521cfe99 --- /dev/null +++ b/third_party/libwebrtc/audio/test/audio_stats_test.cc @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2017 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/test/audio_end_to_end_test.h" +#include "rtc_base/numerics/safe_compare.h" +#include "system_wrappers/include/sleep.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { +namespace { + +// Wait half a second between stopping sending and stopping receiving audio. +constexpr int kExtraRecordTimeMs = 500; + +bool IsNear(int reference, int v) { + // Margin is 10%. + const int error = reference / 10 + 1; + return std::abs(reference - v) <= error; +} + +class NoLossTest : public AudioEndToEndTest { + public: + const int kTestDurationMs = 8000; + const int kBytesSent = 69351; + const int32_t kPacketsSent = 400; + const int64_t kRttMs = 100; + + NoLossTest() = default; + + BuiltInNetworkBehaviorConfig GetSendTransportConfig() const override { + BuiltInNetworkBehaviorConfig pipe_config; + pipe_config.queue_delay_ms = kRttMs / 2; + return pipe_config; + } + + void PerformTest() override { + SleepMs(kTestDurationMs); + send_audio_device()->StopRecording(); + // and some extra time to account for network delay. + SleepMs(GetSendTransportConfig().queue_delay_ms + kExtraRecordTimeMs); + } + + void OnStreamsStopped() override { + AudioSendStream::Stats send_stats = send_stream()->GetStats(); + EXPECT_PRED2(IsNear, kBytesSent, send_stats.payload_bytes_sent); + EXPECT_PRED2(IsNear, kPacketsSent, send_stats.packets_sent); + EXPECT_EQ(0, send_stats.packets_lost); + EXPECT_EQ(0.0f, send_stats.fraction_lost); + EXPECT_EQ("opus", send_stats.codec_name); + // send_stats.jitter_ms + EXPECT_PRED2(IsNear, kRttMs, send_stats.rtt_ms); + // Send level is 0 because it is cleared in TransmitMixer::StopSend(). + EXPECT_EQ(0, send_stats.audio_level); + // send_stats.total_input_energy + // send_stats.total_input_duration + EXPECT_FALSE(send_stats.apm_statistics.delay_median_ms); + EXPECT_FALSE(send_stats.apm_statistics.delay_standard_deviation_ms); + EXPECT_FALSE(send_stats.apm_statistics.echo_return_loss); + EXPECT_FALSE(send_stats.apm_statistics.echo_return_loss_enhancement); + EXPECT_FALSE(send_stats.apm_statistics.residual_echo_likelihood); + EXPECT_FALSE(send_stats.apm_statistics.residual_echo_likelihood_recent_max); + + AudioReceiveStreamInterface::Stats recv_stats = + receive_stream()->GetStats(/*get_and_clear_legacy_stats=*/true); + EXPECT_PRED2(IsNear, kBytesSent, recv_stats.payload_bytes_received); + EXPECT_PRED2(IsNear, kPacketsSent, recv_stats.packets_received); + EXPECT_EQ(0, recv_stats.packets_lost); + EXPECT_EQ("opus", send_stats.codec_name); + // recv_stats.jitter_ms + // recv_stats.jitter_buffer_ms + EXPECT_EQ(20u, recv_stats.jitter_buffer_preferred_ms); + // recv_stats.delay_estimate_ms + // Receive level is 0 because it is cleared in Channel::StopPlayout(). + EXPECT_EQ(0, recv_stats.audio_level); + // recv_stats.total_output_energy + // recv_stats.total_samples_received + // recv_stats.total_output_duration + // recv_stats.concealed_samples + // recv_stats.expand_rate + // recv_stats.speech_expand_rate + EXPECT_EQ(0.0, recv_stats.secondary_decoded_rate); + EXPECT_EQ(0.0, recv_stats.secondary_discarded_rate); + EXPECT_EQ(0.0, recv_stats.accelerate_rate); + EXPECT_EQ(0.0, recv_stats.preemptive_expand_rate); + EXPECT_EQ(0, recv_stats.decoding_calls_to_silence_generator); + // recv_stats.decoding_calls_to_neteq + // recv_stats.decoding_normal + // recv_stats.decoding_plc + EXPECT_EQ(0, recv_stats.decoding_cng); + // recv_stats.decoding_plc_cng + // recv_stats.decoding_muted_output + // Capture start time is -1 because we do not have an associated send stream + // on the receiver side. + EXPECT_EQ(-1, recv_stats.capture_start_ntp_time_ms); + + // Match these stats between caller and receiver. + EXPECT_EQ(send_stats.local_ssrc, recv_stats.remote_ssrc); + EXPECT_EQ(*send_stats.codec_payload_type, *recv_stats.codec_payload_type); + } +}; +} // namespace + +using AudioStatsTest = CallTest; + +TEST_F(AudioStatsTest, DISABLED_NoLoss) { + NoLossTest test; + RunBaseTest(&test); +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/audio/test/nack_test.cc b/third_party/libwebrtc/audio/test/nack_test.cc new file mode 100644 index 0000000000..b36adf8991 --- /dev/null +++ b/third_party/libwebrtc/audio/test/nack_test.cc @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 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/test/audio_end_to_end_test.h" +#include "system_wrappers/include/sleep.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { + +using NackTest = CallTest; + +TEST_F(NackTest, ShouldNackInLossyNetwork) { + class NackTest : public AudioEndToEndTest { + public: + const int kTestDurationMs = 2000; + const int64_t kRttMs = 30; + const int64_t kLossPercent = 30; + const int kNackHistoryMs = 1000; + + BuiltInNetworkBehaviorConfig GetSendTransportConfig() const override { + BuiltInNetworkBehaviorConfig pipe_config; + pipe_config.queue_delay_ms = kRttMs / 2; + pipe_config.loss_percent = kLossPercent; + return pipe_config; + } + + void ModifyAudioConfigs(AudioSendStream::Config* send_config, + std::vector<AudioReceiveStreamInterface::Config>* + receive_configs) override { + ASSERT_EQ(receive_configs->size(), 1U); + (*receive_configs)[0].rtp.nack.rtp_history_ms = kNackHistoryMs; + AudioEndToEndTest::ModifyAudioConfigs(send_config, receive_configs); + } + + void PerformTest() override { SleepMs(kTestDurationMs); } + + void OnStreamsStopped() override { + AudioReceiveStreamInterface::Stats recv_stats = + receive_stream()->GetStats(/*get_and_clear_legacy_stats=*/true); + EXPECT_GT(recv_stats.nacks_sent, 0U); + AudioSendStream::Stats send_stats = send_stream()->GetStats(); + EXPECT_GT(send_stats.retransmitted_packets_sent, 0U); + EXPECT_GT(send_stats.nacks_received, 0U); + } + } test; + + RunBaseTest(&test); +} + +} // namespace test +} // namespace webrtc diff --git a/third_party/libwebrtc/audio/test/non_sender_rtt_test.cc b/third_party/libwebrtc/audio/test/non_sender_rtt_test.cc new file mode 100644 index 0000000000..278193e335 --- /dev/null +++ b/third_party/libwebrtc/audio/test/non_sender_rtt_test.cc @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2021 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/test/audio_end_to_end_test.h" +#include "rtc_base/gunit.h" +#include "rtc_base/task_queue_for_test.h" +#include "system_wrappers/include/sleep.h" +#include "test/gtest.h" + +namespace webrtc { +namespace test { + +using NonSenderRttTest = CallTest; + +TEST_F(NonSenderRttTest, NonSenderRttStats) { + class NonSenderRttTest : public AudioEndToEndTest { + public: + const int kLongTimeoutMs = 20000; + const int64_t kRttMs = 30; + + explicit NonSenderRttTest(TaskQueueBase* task_queue) + : task_queue_(task_queue) {} + + BuiltInNetworkBehaviorConfig GetSendTransportConfig() const override { + BuiltInNetworkBehaviorConfig pipe_config; + pipe_config.queue_delay_ms = kRttMs / 2; + return pipe_config; + } + + void ModifyAudioConfigs(AudioSendStream::Config* send_config, + std::vector<AudioReceiveStreamInterface::Config>* + receive_configs) override { + ASSERT_EQ(receive_configs->size(), 1U); + (*receive_configs)[0].enable_non_sender_rtt = true; + AudioEndToEndTest::ModifyAudioConfigs(send_config, receive_configs); + send_config->send_codec_spec->enable_non_sender_rtt = true; + } + + void PerformTest() override { + // Wait until we have an RTT measurement, but no longer than + // `kLongTimeoutMs`. This usually takes around 5 seconds, but in rare + // cases it can take more than 10 seconds. + EXPECT_TRUE_WAIT(HasRoundTripTimeMeasurement(), kLongTimeoutMs); + } + + void OnStreamsStopped() override { + AudioReceiveStreamInterface::Stats recv_stats = + receive_stream()->GetStats(/*get_and_clear_legacy_stats=*/true); + EXPECT_GT(recv_stats.round_trip_time_measurements, 0); + ASSERT_TRUE(recv_stats.round_trip_time.has_value()); + EXPECT_GT(recv_stats.round_trip_time->ms(), 0); + EXPECT_GE(recv_stats.total_round_trip_time.ms(), + recv_stats.round_trip_time->ms()); + } + + protected: + bool HasRoundTripTimeMeasurement() { + bool has_rtt = false; + // GetStats() can only be called on `task_queue_`, block while we check. + SendTask(task_queue_, [this, &has_rtt]() { + if (receive_stream() && + receive_stream()->GetStats(true).round_trip_time_measurements > 0) { + has_rtt = true; + } + }); + return has_rtt; + } + + private: + TaskQueueBase* task_queue_; + } test(task_queue()); + + RunBaseTest(&test); +} + +} // namespace test +} // namespace webrtc |