Commit 6a148854 authored by Markus Handell's avatar Markus Handell Committed by Chromium LUCI CQ

WebRtcDistinctWorkerThread: enable a separate WebRTC worker thread.

It was noticed that incoming packets are now handled on the WebRTC
signaling thread. This is problematic because many JS WebRTC API calls
get indirectly executed there due to WebRTC's synchronous proxies. And
vice versa - lots of packet handling can delay API calls.

This change adds an enabled-by-default feature called
WebRtcDistinctWorkerThread which splices out WebRTC's worker execution
into its own thread - decoupling the packet processing from the signal
thread.

Bug: 1157617
Change-Id: I16998a3ae0df022ffd544f5a3e2d7d8ada1acfb3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2546006
Commit-Queue: Markus Handell <handellm@google.com>
Reviewed-by: default avatarPhilip Jägenstedt <foolip@chromium.org>
Reviewed-by: default avatarHenrik Boström <hbos@chromium.org>
Reviewed-by: default avatarTommi <tommi@chromium.org>
Reviewed-by: default avatarHarald Alvestrand <hta@chromium.org>
Cr-Commit-Position: refs/heads/master@{#835887}
parent 5eaf02ed
......@@ -851,5 +851,11 @@ const base::Feature kMediaStreamTrackUseConfigMaxFrameRate{
// in Chrome 92.
const base::Feature kCloneSessionStorageForNoOpener{
"CloneSessionStorageForNoOpener", base::FEATURE_DISABLED_BY_DEFAULT};
// When enabled, WebRTC's worker thread will run on a thread context distinct
// from the WebRTC signaling and network threads.
const base::Feature kWebRtcDistinctWorkerThread{
"WebRtcDistinctWorkerThread", base::FEATURE_ENABLED_BY_DEFAULT};
} // namespace features
} // namespace blink
......@@ -344,6 +344,9 @@ BLINK_COMMON_EXPORT extern const base::Feature
kMediaStreamTrackUseConfigMaxFrameRate;
BLINK_COMMON_EXPORT extern const base::Feature kCloneSessionStorageForNoOpener;
BLINK_COMMON_EXPORT extern const base::Feature kWebRtcDistinctWorkerThread;
} // namespace features
} // namespace blink
......
......@@ -117,6 +117,9 @@ PeerConnectionDependencyFactory::PeerConnectionDependencyFactory(
create_p2p_socket_dispatcher ? new P2PSocketDispatcher() : nullptr),
chrome_signaling_thread_("WebRTC_Signaling"),
chrome_network_thread_("WebRTC_Network") {
if (base::FeatureList::IsEnabled(features::kWebRtcDistinctWorkerThread)) {
chrome_worker_thread_.emplace("WebRTC_Worker");
}
TryScheduleStunProbeTrial();
}
......@@ -164,10 +167,12 @@ void PeerConnectionDependencyFactory::WillDestroyCurrentMessageLoop() {
void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
DCHECK(!pc_factory_.get());
DCHECK(!signaling_thread_);
DCHECK(!worker_thread_);
DCHECK(!network_thread_);
DCHECK(!network_manager_);
DCHECK(!socket_factory_);
DCHECK(!chrome_signaling_thread_.IsRunning());
DCHECK(!chrome_worker_thread_ || !chrome_worker_thread_->IsRunning());
DCHECK(!chrome_network_thread_.IsRunning());
DVLOG(1) << "PeerConnectionDependencyFactory::CreatePeerConnectionFactory()";
......@@ -197,6 +202,19 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
return;
}
base::WaitableEvent start_worker_event(
base::WaitableEvent::ResetPolicy::MANUAL,
base::WaitableEvent::InitialState::NOT_SIGNALED);
if (chrome_worker_thread_) {
CHECK(chrome_worker_thread_->Start());
PostCrossThreadTask(
*chrome_worker_thread_->task_runner().get(), FROM_HERE,
CrossThreadBindOnce(
&PeerConnectionDependencyFactory::InitializeWorkerThread,
CrossThreadUnretained(this), CrossThreadUnretained(&worker_thread_),
CrossThreadUnretained(&start_worker_event)));
}
CHECK(chrome_signaling_thread_.Start());
CHECK(chrome_network_thread_.Start());
......@@ -236,6 +254,10 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
CrossThreadUnretained(Platform::Current()->GetMediaDecoderFactory()),
CrossThreadUnretained(&start_signaling_event)));
if (chrome_worker_thread_) {
start_worker_event.Wait();
CHECK(worker_thread_);
}
start_signaling_event.Wait();
CHECK(signaling_thread_);
}
......@@ -313,7 +335,7 @@ void PeerConnectionDependencyFactory::InitializeSignalingThread(
}
webrtc::PeerConnectionFactoryDependencies pcf_deps;
pcf_deps.worker_thread = signaling_thread_;
pcf_deps.worker_thread = worker_thread_ ? worker_thread_ : signaling_thread_;
pcf_deps.signaling_thread = signaling_thread_;
pcf_deps.network_thread = network_thread_;
pcf_deps.task_queue_factory = CreateWebRtcTaskQueueFactory();
......@@ -535,6 +557,15 @@ PeerConnectionDependencyFactory::GetWebRtcAudioDevice() {
return audio_device_.get();
}
void PeerConnectionDependencyFactory::InitializeWorkerThread(
rtc::Thread** thread,
base::WaitableEvent* event) {
jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
*thread = jingle_glue::JingleThreadWrapper::current();
event->Signal();
}
void PeerConnectionDependencyFactory::TryScheduleStunProbeTrial() {
base::Optional<WebString> params =
Platform::Current()->WebRtcStunProbeTrialParameter();
......
......@@ -153,6 +153,8 @@ class MODULES_EXPORT PeerConnectionDependencyFactory
media::DecoderFactory* media_decoder_factory,
base::WaitableEvent* event);
void InitializeWorkerThread(rtc::Thread** thread, base::WaitableEvent* event);
void CreateIpcNetworkManagerOnNetworkThread(
base::WaitableEvent* event,
std::unique_ptr<MdnsResponderAdapter> mdns_responder,
......@@ -177,8 +179,10 @@ class MODULES_EXPORT PeerConnectionDependencyFactory
// PeerConnection threads. signaling_thread_ is created from the
// "current" chrome thread.
rtc::Thread* signaling_thread_ = nullptr;
rtc::Thread* worker_thread_ = nullptr;
rtc::Thread* network_thread_ = nullptr;
base::Thread chrome_signaling_thread_;
base::Optional<base::Thread> chrome_worker_thread_;
base::Thread chrome_network_thread_;
THREAD_CHECKER(thread_checker_);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment