diff --git a/api/test/peerconnection_quality_test_fixture.h b/api/test/peerconnection_quality_test_fixture.h index 55ac76b71e..7828765049 100644 --- a/api/test/peerconnection_quality_test_fixture.h +++ b/api/test/peerconnection_quality_test_fixture.h @@ -532,6 +532,10 @@ class PeerConnectionE2EQualityTestFixture { virtual PeerConfigurer* SetAudioMixer( rtc::scoped_refptr 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 // PeerConnectionInterface implementation that will be created for this // peer. diff --git a/test/pc/e2e/BUILD.gn b/test/pc/e2e/BUILD.gn index b79a4129ca..b9fc6c5ea9 100644 --- a/test/pc/e2e/BUILD.gn +++ b/test/pc/e2e/BUILD.gn @@ -335,6 +335,7 @@ if (!build_with_chromium) { "../../../modules/audio_processing/aec_dump", "../../../p2p:rtc_p2p", "../../../rtc_base:rtc_task_queue", + "../../../rtc_base:threading", ] absl_deps = [ "//third_party/abseil-cpp/absl/memory", diff --git a/test/pc/e2e/peer_configurer.h b/test/pc/e2e/peer_configurer.h index c8239c08d4..9bdc2a165d 100644 --- a/test/pc/e2e/peer_configurer.h +++ b/test/pc/e2e/peer_configurer.h @@ -184,6 +184,12 @@ class PeerConfigurerImpl final components_->pcf_dependencies->audio_mixer = audio_mixer; return this; } + + virtual PeerConfigurer* SetUseNetworkThreadAsWorkerThread() override { + components_->worker_thread = components_->network_thread; + return this; + } + PeerConfigurer* SetRtcEventLogPath(std::string path) override { params_->rtc_event_log_path = std::move(path); return this; diff --git a/test/pc/e2e/peer_connection_e2e_smoke_test.cc b/test/pc/e2e/peer_connection_e2e_smoke_test.cc index e2770aaf82..cb96546a0f 100644 --- a/test/pc/e2e/peer_connection_e2e_smoke_test.cc +++ b/test/pc/e2e/peer_connection_e2e_smoke_test.cc @@ -10,6 +10,7 @@ #include #include +#include #include "api/media_stream_interface.h" #include "api/test/create_network_emulation_manager.h" @@ -191,6 +192,73 @@ TEST_F(PeerConnectionE2EQualityTestSmokeTest, MAYBE_Smoke) { 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 + 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( + std::map>( + {{"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) TEST_F(PeerConnectionE2EQualityTestSmokeTest, SmokeH264) { std::pair diff --git a/test/pc/e2e/peer_connection_quality_test_params.h b/test/pc/e2e/peer_connection_quality_test_params.h index 645ed7a290..221f6b3f7f 100644 --- a/test/pc/e2e/peer_connection_quality_test_params.h +++ b/test/pc/e2e/peer_connection_quality_test_params.h @@ -10,6 +10,7 @@ #ifndef TEST_PC_E2E_PEER_CONNECTION_QUALITY_TEST_PARAMS_H_ #define TEST_PC_E2E_PEER_CONNECTION_QUALITY_TEST_PARAMS_H_ +#include #include #include #include @@ -95,6 +96,7 @@ struct InjectableComponents { rtc::NetworkManager* network_manager, rtc::PacketSocketFactory* packet_socket_factory) : network_thread(network_thread), + worker_thread(nullptr), pcf_dependencies(std::make_unique()), pc_dependencies( std::make_unique(network_manager, @@ -103,6 +105,7 @@ struct InjectableComponents { } rtc::Thread* const network_thread; + rtc::Thread* worker_thread; std::unique_ptr pcf_dependencies; std::unique_ptr pc_dependencies; diff --git a/test/pc/e2e/test_peer.h b/test/pc/e2e/test_peer.h index 741e2e73f1..02e5528a6c 100644 --- a/test/pc/e2e/test_peer.h +++ b/test/pc/e2e/test_peer.h @@ -173,6 +173,8 @@ class TestPeer final : public StatsProvider { nullptr; // 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 worker_thread_; std::unique_ptr wrapper_; std::vector video_sources_; diff --git a/test/pc/e2e/test_peer_factory.cc b/test/pc/e2e/test_peer_factory.cc index 6855d95b54..aa9a731cba 100644 --- a/test/pc/e2e/test_peer_factory.cc +++ b/test/pc/e2e/test_peer_factory.cc @@ -23,6 +23,7 @@ #include "media/engine/webrtc_media_engine_defaults.h" #include "modules/audio_processing/aec_dump/aec_dump_factory.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/echo/echo_emulation.h" #include "test/pc/e2e/peer_configurer.h" @@ -339,15 +340,21 @@ std::unique_ptr TestPeerFactory::CreateTestPeer( CreateMediaEngine(components->pcf_dependencies.get(), audio_device_module); - std::unique_ptr worker_thread = - time_controller_.CreateThread("worker_thread"); + std::unique_ptr owned_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 // `components->pcf_dependencies` rtc::scoped_refptr audio_processing = components->pcf_dependencies->audio_processing; PeerConnectionFactoryDependencies pcf_deps = CreatePCFDependencies( 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 peer_connection_factory = CreateModularPeerConnectionFactory(std::move(pcf_deps)); @@ -362,10 +369,11 @@ std::unique_ptr TestPeerFactory::CreateTestPeer( .MoveValue(); peer_connection->SetBitrate(params->bitrate_settings); - return absl::WrapUnique(new TestPeer( - peer_connection_factory, peer_connection, std::move(observer), - std::move(*params), std::move(*configurable_params), - std::move(video_sources), audio_processing, std::move(worker_thread))); + return absl::WrapUnique( + new TestPeer(peer_connection_factory, peer_connection, + std::move(observer), std::move(*params), + std::move(*configurable_params), std::move(video_sources), + audio_processing, std::move(owned_worker_thread))); } } // namespace webrtc_pc_e2e