Add SmokeSendAndReceivePacketsOnOneThread

Only use the network thread for sending and receiving packets.
The one and only network thread is used as a worker thread in all
PeerConnections. Pacing when sending packets is done on the worker thread.

Bug: webrtc:14502
Change-Id: Ib373315688ae4d810ae1e4421101a859fca93b31
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/278621
Reviewed-by: Evan Shrubsole <eshr@webrtc.org>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Reviewed-by: Artem Titov <titovartem@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38354}
This commit is contained in:
Per Kjellander
2022-10-11 13:05:33 +02:00
committed by WebRTC LUCI CQ
parent ac7577854f
commit 78d80f9be7
7 changed files with 99 additions and 7 deletions

View File

@ -532,6 +532,10 @@ class PeerConnectionE2EQualityTestFixture {
virtual PeerConfigurer* SetAudioMixer( virtual PeerConfigurer* SetAudioMixer(
rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) = 0; rtc::scoped_refptr<webrtc::AudioMixer> audio_mixer) = 0;
// Forces the Peerconnection to use the network thread as the worker thread.
// Ie, worker thread and the network thread is the same thread.
virtual PeerConfigurer* SetUseNetworkThreadAsWorkerThread() = 0;
// The parameters of the following 4 methods will be passed to the // The parameters of the following 4 methods will be passed to the
// PeerConnectionInterface implementation that will be created for this // PeerConnectionInterface implementation that will be created for this
// peer. // peer.

View File

@ -335,6 +335,7 @@ if (!build_with_chromium) {
"../../../modules/audio_processing/aec_dump", "../../../modules/audio_processing/aec_dump",
"../../../p2p:rtc_p2p", "../../../p2p:rtc_p2p",
"../../../rtc_base:rtc_task_queue", "../../../rtc_base:rtc_task_queue",
"../../../rtc_base:threading",
] ]
absl_deps = [ absl_deps = [
"//third_party/abseil-cpp/absl/memory", "//third_party/abseil-cpp/absl/memory",

View File

@ -184,6 +184,12 @@ class PeerConfigurerImpl final
components_->pcf_dependencies->audio_mixer = audio_mixer; components_->pcf_dependencies->audio_mixer = audio_mixer;
return this; return this;
} }
virtual PeerConfigurer* SetUseNetworkThreadAsWorkerThread() override {
components_->worker_thread = components_->network_thread;
return this;
}
PeerConfigurer* SetRtcEventLogPath(std::string path) override { PeerConfigurer* SetRtcEventLogPath(std::string path) override {
params_->rtc_event_log_path = std::move(path); params_->rtc_event_log_path = std::move(path);
return this; return this;

View File

@ -10,6 +10,7 @@
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
#include <string>
#include "api/media_stream_interface.h" #include "api/media_stream_interface.h"
#include "api/test/create_network_emulation_manager.h" #include "api/test/create_network_emulation_manager.h"
@ -191,6 +192,73 @@ TEST_F(PeerConnectionE2EQualityTestSmokeTest, MAYBE_Smoke) {
RunAndCheckEachVideoStreamReceivedFrames(run_params); RunAndCheckEachVideoStreamReceivedFrames(run_params);
} }
// IOS debug builds can be quite slow, disabling to avoid issues with timeouts.
#if defined(WEBRTC_IOS) && defined(WEBRTC_ARCH_ARM64) && !defined(NDEBUG)
#define MAYBE_Smoke DISABLED_Smoke
#else
#define MAYBE_SendAndReceivePacketsOnOneThread \
SmokeSendAndReceivePacketsOnOneThread
#endif
// Only use the network thread for sending and receiving packets.
// The one and only network thread is used as a worker thread in all
// PeerConnections. Pacing when sending packets is done on the worker thread.
// See bugs.webrtc.org/14502.
TEST_F(PeerConnectionE2EQualityTestSmokeTest,
MAYBE_SendAndReceivePacketsOnOneThread) {
test::ScopedFieldTrials trials(
std::string(field_trial::GetFieldTrialString()) +
"WebRTC-SendPacketsOnWorkerThread/Enabled/");
std::pair<EmulatedNetworkManagerInterface*, EmulatedNetworkManagerInterface*>
network_links = CreateNetwork();
AddPeer(network_links.first, [](PeerConfigurer* alice) {
// Peerconnection use the network thread as the worker thread.
alice->SetUseNetworkThreadAsWorkerThread();
VideoConfig video(160, 120, 15);
video.stream_label = "alice-video";
video.sync_group = "alice-media";
alice->AddVideoConfig(std::move(video));
AudioConfig audio;
audio.stream_label = "alice-audio";
audio.mode = AudioConfig::Mode::kFile;
audio.input_file_name =
test::ResourcePath("pc_quality_smoke_test_alice_source", "wav");
audio.sampling_frequency_in_hz = 48000;
audio.sync_group = "alice-media";
alice->SetAudioConfig(std::move(audio));
alice->SetVideoCodecs(
{VideoCodecConfig(cricket::kVp9CodecName, {{"profile-id", "0"}})});
});
AddPeer(network_links.second, [](PeerConfigurer* charlie) {
// Peerconnection use the network thread as the worker thread.
charlie->SetUseNetworkThreadAsWorkerThread();
charlie->SetName("charlie");
VideoConfig video(160, 120, 15);
video.stream_label = "charlie-video";
video.temporal_layers_count = 2;
charlie->AddVideoConfig(std::move(video));
AudioConfig audio;
audio.stream_label = "charlie-audio";
audio.mode = AudioConfig::Mode::kFile;
audio.input_file_name =
test::ResourcePath("pc_quality_smoke_test_bob_source", "wav");
charlie->SetAudioConfig(std::move(audio));
charlie->SetVideoCodecs(
{VideoCodecConfig(cricket::kVp9CodecName, {{"profile-id", "0"}})});
charlie->SetVideoEncoderBitrateMultiplier(1.1);
});
fixture()->AddQualityMetricsReporter(
std::make_unique<StatsBasedNetworkQualityMetricsReporter>(
std::map<std::string, std::vector<EmulatedEndpoint*>>(
{{"alice", network_links.first->endpoints()},
{"charlie", network_links.second->endpoints()}}),
network_emulation(), test::GetGlobalMetricsLogger()));
RunParams run_params(TimeDelta::Seconds(2));
RunAndCheckEachVideoStreamReceivedFrames(run_params);
}
#if defined(WEBRTC_MAC) || defined(WEBRTC_IOS) #if defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
TEST_F(PeerConnectionE2EQualityTestSmokeTest, SmokeH264) { TEST_F(PeerConnectionE2EQualityTestSmokeTest, SmokeH264) {
std::pair<EmulatedNetworkManagerInterface*, EmulatedNetworkManagerInterface*> std::pair<EmulatedNetworkManagerInterface*, EmulatedNetworkManagerInterface*>

View File

@ -10,6 +10,7 @@
#ifndef TEST_PC_E2E_PEER_CONNECTION_QUALITY_TEST_PARAMS_H_ #ifndef TEST_PC_E2E_PEER_CONNECTION_QUALITY_TEST_PARAMS_H_
#define TEST_PC_E2E_PEER_CONNECTION_QUALITY_TEST_PARAMS_H_ #define TEST_PC_E2E_PEER_CONNECTION_QUALITY_TEST_PARAMS_H_
#include <cstddef>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
@ -95,6 +96,7 @@ struct InjectableComponents {
rtc::NetworkManager* network_manager, rtc::NetworkManager* network_manager,
rtc::PacketSocketFactory* packet_socket_factory) rtc::PacketSocketFactory* packet_socket_factory)
: network_thread(network_thread), : network_thread(network_thread),
worker_thread(nullptr),
pcf_dependencies(std::make_unique<PeerConnectionFactoryComponents>()), pcf_dependencies(std::make_unique<PeerConnectionFactoryComponents>()),
pc_dependencies( pc_dependencies(
std::make_unique<PeerConnectionComponents>(network_manager, std::make_unique<PeerConnectionComponents>(network_manager,
@ -103,6 +105,7 @@ struct InjectableComponents {
} }
rtc::Thread* const network_thread; rtc::Thread* const network_thread;
rtc::Thread* worker_thread;
std::unique_ptr<PeerConnectionFactoryComponents> pcf_dependencies; std::unique_ptr<PeerConnectionFactoryComponents> pcf_dependencies;
std::unique_ptr<PeerConnectionComponents> pc_dependencies; std::unique_ptr<PeerConnectionComponents> pc_dependencies;

View File

@ -173,6 +173,8 @@ class TestPeer final : public StatsProvider {
nullptr; nullptr;
// Keeps ownership of worker thread. It has to be destroyed after `wrapper_`. // Keeps ownership of worker thread. It has to be destroyed after `wrapper_`.
// `worker_thread_`can be null if the Peer use only one thread as both the
// worker thread and network thread.
std::unique_ptr<rtc::Thread> worker_thread_; std::unique_ptr<rtc::Thread> worker_thread_;
std::unique_ptr<PeerConnectionWrapper> wrapper_; std::unique_ptr<PeerConnectionWrapper> wrapper_;
std::vector<PeerConfigurerImpl::VideoSource> video_sources_; std::vector<PeerConfigurerImpl::VideoSource> video_sources_;

View File

@ -23,6 +23,7 @@
#include "media/engine/webrtc_media_engine_defaults.h" #include "media/engine/webrtc_media_engine_defaults.h"
#include "modules/audio_processing/aec_dump/aec_dump_factory.h" #include "modules/audio_processing/aec_dump/aec_dump_factory.h"
#include "p2p/client/basic_port_allocator.h" #include "p2p/client/basic_port_allocator.h"
#include "rtc_base/thread.h"
#include "test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h" #include "test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h"
#include "test/pc/e2e/echo/echo_emulation.h" #include "test/pc/e2e/echo/echo_emulation.h"
#include "test/pc/e2e/peer_configurer.h" #include "test/pc/e2e/peer_configurer.h"
@ -339,15 +340,21 @@ std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
CreateMediaEngine(components->pcf_dependencies.get(), CreateMediaEngine(components->pcf_dependencies.get(),
audio_device_module); audio_device_module);
std::unique_ptr<rtc::Thread> worker_thread = std::unique_ptr<rtc::Thread> owned_worker_thread =
time_controller_.CreateThread("worker_thread"); components->worker_thread != nullptr
? nullptr
: time_controller_.CreateThread("worker_thread");
if (components->worker_thread == nullptr) {
components->worker_thread = owned_worker_thread.get();
}
// Store `webrtc::AudioProcessing` into local variable before move of // Store `webrtc::AudioProcessing` into local variable before move of
// `components->pcf_dependencies` // `components->pcf_dependencies`
rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing = rtc::scoped_refptr<webrtc::AudioProcessing> audio_processing =
components->pcf_dependencies->audio_processing; components->pcf_dependencies->audio_processing;
PeerConnectionFactoryDependencies pcf_deps = CreatePCFDependencies( PeerConnectionFactoryDependencies pcf_deps = CreatePCFDependencies(
std::move(components->pcf_dependencies), std::move(media_engine), std::move(components->pcf_dependencies), std::move(media_engine),
signaling_thread_, worker_thread.get(), components->network_thread); signaling_thread_, components->worker_thread, components->network_thread);
rtc::scoped_refptr<PeerConnectionFactoryInterface> peer_connection_factory = rtc::scoped_refptr<PeerConnectionFactoryInterface> peer_connection_factory =
CreateModularPeerConnectionFactory(std::move(pcf_deps)); CreateModularPeerConnectionFactory(std::move(pcf_deps));
@ -362,10 +369,11 @@ std::unique_ptr<TestPeer> TestPeerFactory::CreateTestPeer(
.MoveValue(); .MoveValue();
peer_connection->SetBitrate(params->bitrate_settings); peer_connection->SetBitrate(params->bitrate_settings);
return absl::WrapUnique(new TestPeer( return absl::WrapUnique(
peer_connection_factory, peer_connection, std::move(observer), new TestPeer(peer_connection_factory, peer_connection,
std::move(*params), std::move(*configurable_params), std::move(observer), std::move(*params),
std::move(video_sources), audio_processing, std::move(worker_thread))); std::move(*configurable_params), std::move(video_sources),
audio_processing, std::move(owned_worker_thread)));
} }
} // namespace webrtc_pc_e2e } // namespace webrtc_pc_e2e