diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 72c5e85bef..767054b15c 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -131,3 +131,4 @@ fix_select_the_first_menu_item_when_opened_via_keyboard.patch fix_return_v8_value_from_localframe_requestexecutescript.patch fix_harden_blink_scriptstate_maybefrom.patch chore_add_buildflag_guard_around_new_include.patch +fix_use_delegated_generic_capturer_when_available.patch diff --git a/patches/chromium/fix_use_delegated_generic_capturer_when_available.patch b/patches/chromium/fix_use_delegated_generic_capturer_when_available.patch new file mode 100644 index 0000000000..79099b2382 --- /dev/null +++ b/patches/chromium/fix_use_delegated_generic_capturer_when_available.patch @@ -0,0 +1,54 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Athul Iddya +Date: Fri, 14 Jul 2023 08:03:37 -0700 +Subject: fix: use delegated generic capturer when available + +When the generic capturer is used to fetch capture sources, the returned +ID will be arbitrarily prefixed with "screen" or "window" regardless of +the source type. If the window capturer is used to stream video when the +source was a screen or vice-versa, the stream fails to restart in +delegated capturers like PipeWire. + +To fix this, use the generic capturer to fetch the media stream if it's +delegated and available. This does not cause any issues if the original +capturer was window or screen-specific, as the IDs remain valid for +generic capturer as well. + +diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc +index b0c4efdd8a6401e09520bdfa96221e5addcfd829..f5b7447938f70dd4623a60fa6a856775b627f3d6 100644 +--- a/content/browser/media/capture/desktop_capture_device.cc ++++ b/content/browser/media/capture/desktop_capture_device.cc +@@ -794,8 +794,14 @@ std::unique_ptr DesktopCaptureDevice::Create( + DesktopCapturerLacros::CaptureType::kScreen, + webrtc::DesktopCaptureOptions()); + #else +- std::unique_ptr screen_capturer( +- webrtc::DesktopCapturer::CreateScreenCapturer(options)); ++ std::unique_ptr screen_capturer; ++ if (auto generic_capturer = ++ webrtc::DesktopCapturer::CreateGenericCapturer(options); ++ generic_capturer && generic_capturer->GetDelegatedSourceListController()) { ++ screen_capturer = std::move(generic_capturer); ++ } else { ++ screen_capturer = webrtc::DesktopCapturer::CreateScreenCapturer(options); ++ } + #endif + if (screen_capturer && screen_capturer->SelectSource(source.id)) { + capturer = std::make_unique( +@@ -814,8 +820,14 @@ std::unique_ptr DesktopCaptureDevice::Create( + new DesktopCapturerLacros(DesktopCapturerLacros::CaptureType::kWindow, + webrtc::DesktopCaptureOptions())); + #else +- std::unique_ptr window_capturer = +- webrtc::DesktopCapturer::CreateWindowCapturer(options); ++ std::unique_ptr window_capturer; ++ if (auto generic_capturer = ++ webrtc::DesktopCapturer::CreateGenericCapturer(options); ++ generic_capturer && generic_capturer->GetDelegatedSourceListController()) { ++ window_capturer = std::move(generic_capturer); ++ } else { ++ window_capturer = webrtc::DesktopCapturer::CreateWindowCapturer(options); ++ } + #endif + if (window_capturer && window_capturer->SelectSource(source.id)) { + capturer = std::make_unique( diff --git a/shell/browser/api/electron_api_desktop_capturer.cc b/shell/browser/api/electron_api_desktop_capturer.cc index 1e908db7c8..5cfe0fedb9 100644 --- a/shell/browser/api/electron_api_desktop_capturer.cc +++ b/shell/browser/api/electron_api_desktop_capturer.cc @@ -234,6 +234,33 @@ void DesktopCapturer::StartHandling(bool capture_window, // clear any existing captured sources. captured_sources_.clear(); + if (capture_window && capture_screen) { + // Some capturers like PipeWire suppport a single capturer for both screens + // and windows. Use it if possible, treating both as window capture + if (auto capturer = webrtc::DesktopCapturer::CreateGenericCapturer( + content::desktop_capture::CreateDesktopCaptureOptions()); + capturer && capturer->GetDelegatedSourceListController()) { + capture_screen_ = false; + capture_window_ = capture_window; + window_capturer_ = std::make_unique( + DesktopMediaList::Type::kWindow, std::move(capturer)); + window_capturer_->SetThumbnailSize(thumbnail_size); + + OnceCallback update_callback = base::BindOnce( + &DesktopCapturer::UpdateSourcesList, weak_ptr_factory_.GetWeakPtr(), + window_capturer_.get()); + OnceCallback failure_callback = base::BindOnce( + &DesktopCapturer::HandleFailure, weak_ptr_factory_.GetWeakPtr()); + + window_listener_ = std::make_unique( + std::move(update_callback), std::move(failure_callback), + thumbnail_size.IsEmpty()); + window_capturer_->StartUpdating(window_listener_.get()); + + return; + } + } + // Start listening for captured sources. capture_window_ = capture_window; capture_screen_ = capture_screen;