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}
113 lines
3.7 KiB
C++
113 lines
3.7 KiB
C++
/*
|
|
* Copyright 2018 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.
|
|
*/
|
|
|
|
#include "modules/desktop_capture/linux/wayland/base_capturer_pipewire.h"
|
|
|
|
#include "modules/desktop_capture/desktop_capture_options.h"
|
|
#include "modules/desktop_capture/desktop_capturer.h"
|
|
#include "modules/desktop_capture/linux/wayland/xdg_desktop_portal_utils.h"
|
|
#include "rtc_base/checks.h"
|
|
#include "rtc_base/logging.h"
|
|
|
|
namespace webrtc {
|
|
|
|
namespace {
|
|
|
|
using xdg_portal::RequestResponse;
|
|
using xdg_portal::ScreenCapturePortalInterface;
|
|
using xdg_portal::SessionDetails;
|
|
|
|
} // namespace
|
|
|
|
BaseCapturerPipeWire::BaseCapturerPipeWire(const DesktopCaptureOptions& options)
|
|
: 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() {}
|
|
|
|
void BaseCapturerPipeWire::OnScreenCastRequestResult(RequestResponse result,
|
|
uint32_t stream_node_id,
|
|
int fd) {
|
|
if (result != RequestResponse::kSuccess ||
|
|
!options_.screencast_stream()->StartScreenCastStream(stream_node_id,
|
|
fd)) {
|
|
capturer_failed_ = true;
|
|
RTC_LOG(LS_ERROR) << "ScreenCastPortal failed: "
|
|
<< static_cast<uint>(result);
|
|
}
|
|
}
|
|
|
|
void BaseCapturerPipeWire::OnScreenCastSessionClosed() {
|
|
if (!capturer_failed_) {
|
|
options_.screencast_stream()->StopScreenCastStream();
|
|
}
|
|
}
|
|
|
|
void BaseCapturerPipeWire::Start(Callback* callback) {
|
|
RTC_DCHECK(!callback_);
|
|
RTC_DCHECK(callback);
|
|
|
|
callback_ = callback;
|
|
|
|
portal_->Start();
|
|
}
|
|
|
|
void BaseCapturerPipeWire::CaptureFrame() {
|
|
if (capturer_failed_) {
|
|
callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr);
|
|
return;
|
|
}
|
|
|
|
std::unique_ptr<DesktopFrame> frame =
|
|
options_.screencast_stream()->CaptureFrame();
|
|
|
|
if (!frame || !frame->data()) {
|
|
callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr);
|
|
return;
|
|
}
|
|
|
|
// TODO(julien.isorce): http://crbug.com/945468. Set the icc profile on
|
|
// the frame, see ScreenCapturerX11::CaptureFrame.
|
|
|
|
callback_->OnCaptureResult(Result::SUCCESS, std::move(frame));
|
|
}
|
|
|
|
bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) {
|
|
RTC_DCHECK(sources->size() == 0);
|
|
// List of available screens is already presented by the xdg-desktop-portal,
|
|
// so we just need a (valid) source id for any callers to pass around, even
|
|
// though it doesn't mean anything to us. Until the user selects a source in
|
|
// xdg-desktop-portal we'll just end up returning empty frames. Note that "0"
|
|
// is often treated as a null/placeholder id, so we shouldn't use that.
|
|
// TODO(https://crbug.com/1297671): Reconsider type of ID when plumbing
|
|
// token that will enable stream re-use.
|
|
sources->push_back({1});
|
|
return true;
|
|
}
|
|
|
|
bool BaseCapturerPipeWire::SelectSource(SourceId id) {
|
|
// Screen selection is handled by the xdg-desktop-portal.
|
|
return true;
|
|
}
|
|
|
|
SessionDetails BaseCapturerPipeWire::GetSessionDetails() {
|
|
return portal_->GetSessionDetails();
|
|
}
|
|
|
|
} // namespace webrtc
|