diff --git a/modules/desktop_capture/BUILD.gn b/modules/desktop_capture/BUILD.gn index 7499c16b09..580a886822 100644 --- a/modules/desktop_capture/BUILD.gn +++ b/modules/desktop_capture/BUILD.gn @@ -6,6 +6,7 @@ # in the file PATENTS. All contributing project authors may # be found in the AUTHORS file in the root of the source tree. +import("//build/config/linux/gtk/gtk.gni") import("//build/config/linux/pkg_config.gni") import("//build/config/ui.gni") import("//tools/generate_stubs/rules.gni") @@ -266,6 +267,13 @@ if (is_linux || is_chromeos) { if (!rtc_link_pipewire) { defines += [ "WEBRTC_DLOPEN_PIPEWIRE" ] } + + # Chromecast build config overrides `WEBRTC_USE_PIPEWIRE` even when + # `rtc_use_pipewire` is not set, which causes pipewire_config to not be + # included in targets. More details in: webrtc:13898 + if (is_linux && !is_chromecast) { + defines += [ "WEBRTC_USE_GIO" ] + } } } } @@ -369,7 +377,9 @@ rtc_library("desktop_capture_generic") { "window_finder.cc", "window_finder.h", ] - + if (is_linux && !is_chromecast && rtc_use_pipewire) { + sources += [ "desktop_capture_metadata.h" ] + } if (is_mac) { sources += [ "mac/desktop_configuration.h", @@ -395,7 +405,6 @@ rtc_library("desktop_capture_generic") { ] } } - if (rtc_use_x11_extensions || rtc_use_pipewire) { sources += [ "mouse_cursor_monitor_linux.cc", @@ -570,6 +579,7 @@ rtc_library("desktop_capture_generic") { "linux/wayland/mouse_cursor_monitor_pipewire.h", "linux/wayland/scoped_glib.cc", "linux/wayland/scoped_glib.h", + "linux/wayland/screen_capture_portal_interface.h", "linux/wayland/screencast_portal.cc", "linux/wayland/screencast_portal.h", "linux/wayland/screencast_stream_utils.cc", @@ -578,6 +588,7 @@ rtc_library("desktop_capture_generic") { "linux/wayland/shared_screencast_stream.h", "linux/wayland/xdg_desktop_portal_utils.cc", "linux/wayland/xdg_desktop_portal_utils.h", + "linux/wayland/xdg_session_details.h", ] configs += [ diff --git a/modules/desktop_capture/desktop_and_cursor_composer.cc b/modules/desktop_capture/desktop_and_cursor_composer.cc index 7ca0af038c..355bfacfbb 100644 --- a/modules/desktop_capture/desktop_and_cursor_composer.cc +++ b/modules/desktop_capture/desktop_and_cursor_composer.cc @@ -203,6 +203,12 @@ bool DesktopAndCursorComposer::IsOccluded(const DesktopVector& pos) { return desktop_capturer_->IsOccluded(pos); } +#if defined(WEBRTC_USE_GIO) +DesktopCaptureMetadata DesktopAndCursorComposer::GetMetadata() { + return desktop_capturer_->GetMetadata(); +} +#endif // defined(WEBRTC_USE_GIO) + void DesktopAndCursorComposer::OnCaptureResult( DesktopCapturer::Result result, std::unique_ptr frame) { diff --git a/modules/desktop_capture/desktop_and_cursor_composer.h b/modules/desktop_capture/desktop_and_cursor_composer.h index edb764d168..a078b3eeef 100644 --- a/modules/desktop_capture/desktop_and_cursor_composer.h +++ b/modules/desktop_capture/desktop_and_cursor_composer.h @@ -12,7 +12,9 @@ #define MODULES_DESKTOP_CAPTURE_DESKTOP_AND_CURSOR_COMPOSER_H_ #include - +#if defined(WEBRTC_USE_GIO) +#include "modules/desktop_capture/desktop_capture_metadata.h" +#endif // defined(WEBRTC_USE_GIO) #include "modules/desktop_capture/desktop_capture_options.h" #include "modules/desktop_capture/desktop_capture_types.h" #include "modules/desktop_capture/desktop_capturer.h" @@ -59,6 +61,9 @@ class RTC_EXPORT DesktopAndCursorComposer bool SelectSource(SourceId id) override; bool FocusOnSelectedSource() override; bool IsOccluded(const DesktopVector& pos) override; +#if defined(WEBRTC_USE_GIO) + DesktopCaptureMetadata GetMetadata() override; +#endif // defined(WEBRTC_USE_GIO) // MouseCursorMonitor::Callback interface. void OnMouseCursor(MouseCursor* cursor) override; diff --git a/modules/desktop_capture/desktop_capture_metadata.h b/modules/desktop_capture/desktop_capture_metadata.h new file mode 100644 index 0000000000..faca156e33 --- /dev/null +++ b/modules/desktop_capture/desktop_capture_metadata.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_METADATA_H_ +#define MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_METADATA_H_ + +#if defined(WEBRTC_USE_GIO) +#include "modules/desktop_capture/linux/wayland/xdg_session_details.h" +#endif // defined(WEBRTC_USE_GIO) + +namespace webrtc { + +// Container for the metadata associated with a desktop capturer. +struct DesktopCaptureMetadata { +#if defined(WEBRTC_USE_GIO) + // Details about the XDG desktop session handle (used by wayland + // implementation in remoting) + xdg_portal::SessionDetails session_details; +#endif // defined(WEBRTC_USE_GIO) +}; + +} // namespace webrtc + +#endif // MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_METADATA_H_ diff --git a/modules/desktop_capture/desktop_capturer.h b/modules/desktop_capture/desktop_capturer.h index 822a75d947..d3164258ec 100644 --- a/modules/desktop_capture/desktop_capturer.h +++ b/modules/desktop_capture/desktop_capturer.h @@ -19,6 +19,9 @@ #include #include +#if defined(WEBRTC_USE_GIO) +#include "modules/desktop_capture/desktop_capture_metadata.h" +#endif // defined(WEBRTC_USE_GIO) #include "modules/desktop_capture/desktop_capture_types.h" #include "modules/desktop_capture/desktop_frame.h" #include "modules/desktop_capture/shared_memory.h" @@ -143,6 +146,12 @@ class RTC_EXPORT DesktopCapturer { static bool IsRunningUnderWayland(); #endif // defined(WEBRTC_USE_PIPEWIRE) || defined(WEBRTC_USE_X11) +#if defined(WEBRTC_USE_GIO) + // Populates implementation specific metadata into the passed in pointer. + // Classes can choose to override it or use the default no-op implementation. + virtual DesktopCaptureMetadata GetMetadata() { return {}; } +#endif // defined(WEBRTC_USE_GIO) + protected: // CroppingWindowCapturer needs to create raw capturers without wrappers, so // the following two functions are protected. diff --git a/modules/desktop_capture/desktop_capturer_differ_wrapper.cc b/modules/desktop_capture/desktop_capturer_differ_wrapper.cc index 916d76f7ce..77543e4060 100644 --- a/modules/desktop_capture/desktop_capturer_differ_wrapper.cc +++ b/modules/desktop_capture/desktop_capturer_differ_wrapper.cc @@ -186,6 +186,12 @@ bool DesktopCapturerDifferWrapper::IsOccluded(const DesktopVector& pos) { return base_capturer_->IsOccluded(pos); } +#if defined(WEBRTC_USE_GIO) +DesktopCaptureMetadata DesktopCapturerDifferWrapper::GetMetadata() { + return base_capturer_->GetMetadata(); +} +#endif // defined(WEBRTC_USE_GIO) + void DesktopCapturerDifferWrapper::OnCaptureResult( Result result, std::unique_ptr input_frame) { diff --git a/modules/desktop_capture/desktop_capturer_differ_wrapper.h b/modules/desktop_capture/desktop_capturer_differ_wrapper.h index 1f70cef186..6ebb5d7bc3 100644 --- a/modules/desktop_capture/desktop_capturer_differ_wrapper.h +++ b/modules/desktop_capture/desktop_capturer_differ_wrapper.h @@ -12,7 +12,9 @@ #define MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURER_DIFFER_WRAPPER_H_ #include - +#if defined(WEBRTC_USE_GIO) +#include "modules/desktop_capture/desktop_capture_metadata.h" +#endif // defined(WEBRTC_USE_GIO) #include "modules/desktop_capture/desktop_capture_types.h" #include "modules/desktop_capture/desktop_capturer.h" #include "modules/desktop_capture/desktop_frame.h" @@ -52,7 +54,9 @@ class RTC_EXPORT DesktopCapturerDifferWrapper bool SelectSource(SourceId id) override; bool FocusOnSelectedSource() override; bool IsOccluded(const DesktopVector& pos) override; - +#if defined(WEBRTC_USE_GIO) + DesktopCaptureMetadata GetMetadata() override; +#endif // defined(WEBRTC_USE_GIO) private: // DesktopCapturer::Callback interface. void OnCaptureResult(Result result, diff --git a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc index ae26570a7c..0fc90e0e8d 100644 --- a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc +++ b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.cc @@ -21,14 +21,22 @@ namespace webrtc { namespace { using xdg_portal::RequestResponse; +using xdg_portal::ScreenCapturePortalInterface; +using xdg_portal::SessionDetails; } // namespace BaseCapturerPipeWire::BaseCapturerPipeWire(const DesktopCaptureOptions& options) - : options_(options) { - screencast_portal_ = std::make_unique( - ScreenCastPortal::CaptureSourceType::kAnyScreenContent, this); -} + : BaseCapturerPipeWire( + options, + std::make_unique( + ScreenCastPortal::CaptureSourceType::kAnyScreenContent, + this)) {} + +BaseCapturerPipeWire::BaseCapturerPipeWire( + const DesktopCaptureOptions& options, + std::unique_ptr portal) + : options_(options), portal_(std::move(portal)) {} BaseCapturerPipeWire::~BaseCapturerPipeWire() {} @@ -56,7 +64,7 @@ void BaseCapturerPipeWire::Start(Callback* callback) { callback_ = callback; - screencast_portal_->Start(); + portal_->Start(); } void BaseCapturerPipeWire::CaptureFrame() { @@ -97,4 +105,8 @@ bool BaseCapturerPipeWire::SelectSource(SourceId id) { return true; } +SessionDetails BaseCapturerPipeWire::GetSessionDetails() { + return portal_->GetSessionDetails(); +} + } // namespace webrtc diff --git a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.h b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.h index e9d67d04be..da0ce95a01 100644 --- a/modules/desktop_capture/linux/wayland/base_capturer_pipewire.h +++ b/modules/desktop_capture/linux/wayland/base_capturer_pipewire.h @@ -13,16 +13,21 @@ #include "modules/desktop_capture/desktop_capture_options.h" #include "modules/desktop_capture/desktop_capturer.h" +#include "modules/desktop_capture/linux/wayland/screen_capture_portal_interface.h" #include "modules/desktop_capture/linux/wayland/screencast_portal.h" #include "modules/desktop_capture/linux/wayland/shared_screencast_stream.h" #include "modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h" +#include "modules/desktop_capture/linux/wayland/xdg_session_details.h" namespace webrtc { class BaseCapturerPipeWire : public DesktopCapturer, public ScreenCastPortal::PortalNotifier { public: - BaseCapturerPipeWire(const DesktopCaptureOptions& options); + explicit BaseCapturerPipeWire(const DesktopCaptureOptions& options); + BaseCapturerPipeWire( + const DesktopCaptureOptions& options, + std::unique_ptr portal); ~BaseCapturerPipeWire() override; BaseCapturerPipeWire(const BaseCapturerPipeWire&) = delete; @@ -40,11 +45,13 @@ class BaseCapturerPipeWire : public DesktopCapturer, int fd) override; void OnScreenCastSessionClosed() override; + xdg_portal::SessionDetails GetSessionDetails(); + private: DesktopCaptureOptions options_ = {}; Callback* callback_ = nullptr; bool capturer_failed_ = false; - std::unique_ptr screencast_portal_; + std::unique_ptr portal_; }; } // namespace webrtc diff --git a/modules/desktop_capture/linux/wayland/screen_capture_portal_interface.h b/modules/desktop_capture/linux/wayland/screen_capture_portal_interface.h new file mode 100644 index 0000000000..76cbd276c9 --- /dev/null +++ b/modules/desktop_capture/linux/wayland/screen_capture_portal_interface.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_SCREEN_CAPTURE_PORTAL_INTERFACE_H_ +#define MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_SCREEN_CAPTURE_PORTAL_INTERFACE_H_ + +#include "modules/desktop_capture/linux/wayland/xdg_session_details.h" + +namespace webrtc { +namespace xdg_portal { + +// An interface for XDG desktop portals that can capture desktop/screen. +class ScreenCapturePortalInterface { + public: + virtual ~ScreenCapturePortalInterface() {} + virtual xdg_portal::SessionDetails GetSessionDetails() = 0; + virtual void Start() = 0; +}; + +} // namespace xdg_portal +} // namespace webrtc + +#endif // MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_SCREEN_CAPTURE_PORTAL_INTERFACE_H_ diff --git a/modules/desktop_capture/linux/wayland/screencast_portal.cc b/modules/desktop_capture/linux/wayland/screencast_portal.cc index bbf933966b..ab516a7f4d 100644 --- a/modules/desktop_capture/linux/wayland/screencast_portal.cc +++ b/modules/desktop_capture/linux/wayland/screencast_portal.cc @@ -112,6 +112,10 @@ void ScreenCastPortal::Start() { cancellable_, this); } +xdg_portal::SessionDetails ScreenCastPortal::GetSessionDetails() { + return {}; // No-op +} + void ScreenCastPortal::PortalFailed(RequestResponse result) { notifier_->OnScreenCastRequestResult(result, pw_stream_node_id_, pw_fd_); } diff --git a/modules/desktop_capture/linux/wayland/screencast_portal.h b/modules/desktop_capture/linux/wayland/screencast_portal.h index d29f773cb2..3d86006050 100644 --- a/modules/desktop_capture/linux/wayland/screencast_portal.h +++ b/modules/desktop_capture/linux/wayland/screencast_portal.h @@ -15,11 +15,13 @@ #include +#include "modules/desktop_capture/linux/wayland/screen_capture_portal_interface.h" #include "modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h" +#include "modules/desktop_capture/linux/wayland/xdg_session_details.h" namespace webrtc { -class ScreenCastPortal { +class ScreenCastPortal : public xdg_portal::ScreenCapturePortalInterface { public: using ProxyRequestResponseHandler = void (*)(GObject* object, GAsyncResult* result, @@ -86,7 +88,8 @@ class ScreenCastPortal { // The observer will return whether the communication with xdg-desktop-portal // was successful and only then you will be able to get all the required // information in order to continue working with PipeWire. - void Start(); + void Start() override; + xdg_portal::SessionDetails GetSessionDetails() override; // Method to notify the reason for failure of a portal request. void PortalFailed(xdg_portal::RequestResponse result); diff --git a/modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h b/modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h index 4fb058c427..98979c1f40 100644 --- a/modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h +++ b/modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h @@ -18,6 +18,7 @@ #include #include "modules/desktop_capture/linux/wayland/scoped_glib.h" +#include "modules/desktop_capture/linux/wayland/xdg_session_details.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h" @@ -32,13 +33,6 @@ constexpr char kSessionInterfaceName[] = "org.freedesktop.portal.Session"; constexpr char kRequestInterfaceName[] = "org.freedesktop.portal.Request"; constexpr char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast"; -struct SessionDetails { - GDBusProxy* proxy; - GCancellable* cancellable; - std::string session_handle; - uint32_t pipewire_stream_node_id; -}; - using ProxyRequestCallback = void (*)(GObject*, GAsyncResult*, gpointer); using SessionRequestCallback = void (*)(GDBusProxy*, GAsyncResult*, gpointer); using SessionRequestResponseSignalHandler = void (*)(GDBusConnection*, diff --git a/modules/desktop_capture/linux/wayland/xdg_session_details.h b/modules/desktop_capture/linux/wayland/xdg_session_details.h new file mode 100644 index 0000000000..b70ac4aa59 --- /dev/null +++ b/modules/desktop_capture/linux/wayland/xdg_session_details.h @@ -0,0 +1,33 @@ +/* + * Copyright 2022 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. + */ + +#ifndef MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_XDG_SESSION_DETAILS_H_ +#define MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_XDG_SESSION_DETAILS_H_ + +#include + +#include + +namespace webrtc { +namespace xdg_portal { + +// Details of the session associated with XDG desktop portal session. Portal API +// calls can be invoked by utilizing the information here. +struct SessionDetails { + GDBusProxy* proxy = nullptr; + GCancellable* cancellable = nullptr; + std::string session_handle; + uint32_t pipewire_stream_node_id = 0; +}; + +} // namespace xdg_portal +} // namespace webrtc + +#endif // MODULES_DESKTOP_CAPTURE_LINUX_WAYLAND_XDG_SESSION_DETAILS_H_