summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/audio/test
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/audio/test')
-rw-r--r--third_party/libwebrtc/audio/test/audio_end_to_end_test.cc86
-rw-r--r--third_party/libwebrtc/audio/test/audio_end_to_end_test.h63
-rw-r--r--third_party/libwebrtc/audio/test/audio_stats_test.cc119
-rw-r--r--third_party/libwebrtc/audio/test/nack_test.cc59
-rw-r--r--third_party/libwebrtc/audio/test/non_sender_rtt_test.cc84
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