mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-12 21:30:45 +01:00
wayland: Add a common interface for screencast and remote desktop portal
Change adapts the `base_capturer_pipewire` so that a portal can be injected in the capturer. This allows the remoting to inject its own portal for the purpose of capturing desktop stream as long as the injected portal provides implementation of the new interface that is added as part of this change. Additionally, a method has been exposed on the capturer to get details about the portal session so that the remoting implementation can use the same underlying session for controlling inputs on the remote host. Finally, desktop capturer interface is extended with a generic method `GetMetadata` that is used to retrieve session related information by CRD and relay it over to its input injector. Clients provide override for the method and it eventually invokes the underlying `GetSessionDetails` method on the portal instance. Bug: chromium:1291247 Change-Id: I0dbd154eb16d4149f967c4a818eea51e7e6eb9a9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/257000 Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org> Reviewed-by: Alexander Cooper <alcooper@chromium.org> Commit-Queue: Salman Malik <salmanmalik@google.com> Cr-Commit-Position: refs/heads/main@{#36399}
This commit is contained in:
parent
3455481554
commit
24927780f1
14 changed files with 176 additions and 21 deletions
|
@ -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 += [
|
||||
|
|
|
@ -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<DesktopFrame> frame) {
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
#define MODULES_DESKTOP_CAPTURE_DESKTOP_AND_CURSOR_COMPOSER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#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;
|
||||
|
|
31
modules/desktop_capture/desktop_capture_metadata.h
Normal file
31
modules/desktop_capture/desktop_capture_metadata.h
Normal file
|
@ -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_
|
|
@ -19,6 +19,9 @@
|
|||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
#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.
|
||||
|
|
|
@ -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<DesktopFrame> input_frame) {
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
#define MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURER_DIFFER_WRAPPER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#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,
|
||||
|
|
|
@ -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>(
|
||||
ScreenCastPortal::CaptureSourceType::kAnyScreenContent, this);
|
||||
}
|
||||
: BaseCapturerPipeWire(
|
||||
options,
|
||||
std::make_unique<ScreenCastPortal>(
|
||||
ScreenCastPortal::CaptureSourceType::kAnyScreenContent,
|
||||
this)) {}
|
||||
|
||||
BaseCapturerPipeWire::BaseCapturerPipeWire(
|
||||
const DesktopCaptureOptions& options,
|
||||
std::unique_ptr<ScreenCapturePortalInterface> 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
|
||||
|
|
|
@ -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<xdg_portal::ScreenCapturePortalInterface> 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<ScreenCastPortal> screencast_portal_;
|
||||
std::unique_ptr<xdg_portal::ScreenCapturePortalInterface> portal_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
|
|
@ -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_
|
|
@ -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_);
|
||||
}
|
||||
|
|
|
@ -15,11 +15,13 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#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);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <vector>
|
||||
|
||||
#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*,
|
||||
|
|
33
modules/desktop_capture/linux/wayland/xdg_session_details.h
Normal file
33
modules/desktop_capture/linux/wayland/xdg_session_details.h
Normal file
|
@ -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 <gio/gio.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
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_
|
Loading…
Reference in a new issue