diff --git a/modules/desktop_capture/BUILD.gn b/modules/desktop_capture/BUILD.gn index 7499c16b09..5351a76f29 100644 --- a/modules/desktop_capture/BUILD.gn +++ b/modules/desktop_capture/BUILD.gn @@ -332,6 +332,7 @@ rtc_library("desktop_capture_generic") { "cropping_window_capturer.h", "desktop_and_cursor_composer.cc", "desktop_and_cursor_composer.h", + "desktop_capture_metadata.h", "desktop_capture_metrics_helper.cc", "desktop_capture_metrics_helper.h", "desktop_capture_options.cc", @@ -570,6 +571,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 +580,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..c959fc6e0f 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_PIPEWIRE) +DesktopCaptureMetadata DesktopAndCursorComposer::GetMetadata() { + return desktop_capturer_->GetMetadata(); +} +#endif // defined(WEBRTC_USE_PIPEWIRE) + 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..56c30e7637 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_PIPEWIRE) +#include "modules/desktop_capture/desktop_capture_metadata.h" +#endif // defined(WEBRTC_USE_PIPEWIRE) #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_PIPEWIRE) + DesktopCaptureMetadata GetMetadata() override; +#endif // defined(WEBRTC_USE_PIPEWIRE) // 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..d64cf75ebc --- /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_PIPEWIRE) +#include "modules/desktop_capture/linux/wayland/xdg_session_details.h" +#endif + +namespace webrtc { + +// Container for the metadata associated with a desktop capturer. +struct DesktopCaptureMetadata { +#if defined(WEBRTC_USE_PIPEWIRE) + // Details about the XDG desktop session handle (used by wayland + // implementation in remoting) + xdg_portal::SessionDetails session_details; +#endif +}; + +} // 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..50c6d64c94 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_PIPEWIRE) +#include "modules/desktop_capture/desktop_capture_metadata.h" +#endif // defined(WEBRTC_USE_PIPEWIRE) #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_PIPEWIRE) + // 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_PIPEWIRE) + 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..59315153cd 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_PIPEWIRE) +DesktopCaptureMetadata DesktopCapturerDifferWrapper::GetMetadata() { + return base_capturer_->GetMetadata(); +} +#endif // defined(WEBRTC_USE_PIPEWIRE) + 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..5be8a1ee3e 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_PIPEWIRE) +#include "modules/desktop_capture/desktop_capture_metadata.h" +#endif // defined(WEBRTC_USE_PIPEWIRE) #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_PIPEWIRE) + DesktopCaptureMetadata GetMetadata() override; +#endif // defined(WEBRTC_USE_PIPEWIRE) 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_