/* * 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::CaptureSourceType::kAnyScreenContent, this)) {} BaseCapturerPipeWire::BaseCapturerPipeWire( const DesktopCaptureOptions& options, std::unique_ptr 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(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 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