Improve screen sharing with PipeWire on Wayland

Currently, sharing a screen or a window on Wayland opens unnecessary
preview dialog on Chromium side, which is then followed by a similar
dialog on xdg-desktop-portal side. The Chromium dialog is useless on
Wayland, as it doesn't show anything. This is because Chromium doesn't
have access to screen content as in case of X11 session. To fix this, we
want to avoid showing the preview dialog in case we find that we run on
Wayland and only pick a screen or a window from the dialog that comes
from xdg-desktop-portal.

This patch splits BaseCapturerPipeWire class, moving portal related code
into XdgPortalBase, which does all the DBus communication and which is
supposed to be reused by BaseCapturerPipeWire when the user confirms
the dialog from xdg-desktop-portal. The XdgPortalBase is extended to
support multiple calls at once, where each call is identified by Id.

Relevant change on Chromium side will be in a different review.

Bug: chromium:682122
Change-Id: If8afd36da66231eb154cdc00114908ac897ee4cf
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/160649
Commit-Queue: Tommi <tommi@webrtc.org>
Reviewed-by: Tommi <tommi@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32342}
This commit is contained in:
Jan Grulich
2020-10-06 19:54:16 +02:00
committed by Commit Bot
parent ff9f6461b6
commit 9b87037073
16 changed files with 1825 additions and 1082 deletions

View File

@ -10,6 +10,7 @@
#ifndef MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_
#define MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_
#include "absl/types/optional.h"
#include "api/scoped_refptr.h"
#include "rtc_base/system/rtc_export.h"
@ -23,6 +24,10 @@
#include "modules/desktop_capture/full_screen_window_detector.h"
#if defined(WEBRTC_USE_PIPEWIRE)
#include "modules/desktop_capture/linux/xdg_desktop_portal_base.h"
#endif
namespace webrtc {
// An object that stores initialization parameters for screen and window
@ -131,13 +136,68 @@ class RTC_EXPORT DesktopCaptureOptions {
#if defined(WEBRTC_USE_PIPEWIRE)
bool allow_pipewire() const { return allow_pipewire_; }
void set_allow_pipewire(bool allow) { allow_pipewire_ = allow; }
// Provides a way how to identify portal call for a sharing request
// made by the client. This allows to go through the preview dialog
// and to the web page itself with just one xdg-desktop-portal call.
// Client is supposed to:
// 1) Call start_request(id) to tell us an identificator for the current
// request
// 2) Call close_request(id) in case the preview dialog was cancelled
// or user picked a web page to be shared
// Note: In case the current request is not finalized, we will close it for
// safety reasons and client will need to ask the portal again
// This was done primarily for chromium support as there was no way how to
// identify a portal call made for the preview and later on continue with the
// same content on the web page itself.
void start_request(int32_t request_id) {
// In case we get a duplicit start_request call, which might happen when a
// browser requests both screen and window sharing, we don't want to do
// anything.
if (request_id == xdp_base_->CurrentConnectionId()) {
return;
}
// In case we are about to start a new request and the previous one is not
// finalized and not stream to the web page itself we will just close it.
if (!xdp_base_->IsConnectionStreamingOnWeb(absl::nullopt) &&
xdp_base_->IsConnectionInitialized(absl::nullopt)) {
xdp_base_->CloseConnection(absl::nullopt);
}
xdp_base_->SetCurrentConnectionId(request_id);
}
void close_request(int32_t request_id) {
xdp_base_->CloseConnection(request_id);
xdp_base_->SetCurrentConnectionId(absl::nullopt);
}
absl::optional<int32_t> request_id() {
// Reset request_id in case the connection is in final state, which means it
// is streaming content to the web page itself and nobody should be asking
// again for this ID.
if (xdp_base_->IsConnectionStreamingOnWeb(absl::nullopt)) {
xdp_base_->SetCurrentConnectionId(absl::nullopt);
}
return xdp_base_->CurrentConnectionId();
}
XdgDesktopPortalBase* xdp_base() const { return xdp_base_; }
void set_xdp_base(rtc::scoped_refptr<XdgDesktopPortalBase> xdp_base) {
xdp_base_ = std::move(xdp_base);
}
#endif
private:
#if defined(WEBRTC_USE_X11)
rtc::scoped_refptr<SharedXDisplay> x_display_;
#endif
#if defined(WEBRTC_USE_PIPEWIRE)
rtc::scoped_refptr<XdgDesktopPortalBase> xdp_base_;
#endif
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
rtc::scoped_refptr<DesktopConfigurationMonitor> configuration_monitor_;
bool allow_iosurface_ = false;