| /* | |
| * 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 <cstdint> | |
| #include <cstdlib> | |
| #include "api/test/simulated_network.h" | |
| #include "audio/test/audio_end_to_end_test.h" | |
| #include "call/audio_receive_stream.h" | |
| #include "call/audio_send_stream.h" | |
| #include "rtc_base/thread.h" | |
| #include "test/call_test.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 { | |
| Thread::SleepMs(kTestDurationMs); | |
| send_audio_device()->StopRecording(); | |
| // and some extra time to account for network delay. | |
| Thread::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 |