diff --git a/AUTHORS b/AUTHORS index 590a4c0874..06b42233e7 100644 --- a/AUTHORS +++ b/AUTHORS @@ -73,9 +73,6 @@ Sergio Garcia Murillo Maxim Pavlov Yusuke Suzuki Piasy Xu -Tomas Popela -Jan Grulich -Eike Rathke &yet LLC <*@andyet.com> Agora IO <*@agora.io> diff --git a/modules/desktop_capture/BUILD.gn b/modules/desktop_capture/BUILD.gn index 656048ad1c..207f1d45d5 100644 --- a/modules/desktop_capture/BUILD.gn +++ b/modules/desktop_capture/BUILD.gn @@ -6,7 +6,6 @@ # 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/pkg_config.gni") import("//build/config/ui.gni") import("../../webrtc.gni") @@ -166,23 +165,6 @@ if (rtc_include_tests) { } } -if (is_linux) { - if (rtc_use_pipewire) { - pkg_config("pipewire") { - packages = [ "libpipewire-0.2" ] - - defines = [ "WEBRTC_USE_PIPEWIRE" ] - } - - pkg_config("gio") { - packages = [ - "gio-2.0", - "gio-unix-2.0", - ] - } - } -} - rtc_source_set("desktop_capture") { visibility = [ "*" ] public_deps = [ @@ -340,69 +322,39 @@ rtc_static_library("desktop_capture_generic") { ] } - if (rtc_use_x11 || rtc_use_pipewire) { - sources += [ - "mouse_cursor_monitor_linux.cc", - "screen_capturer_linux.cc", - "window_capturer_linux.cc", - ] - - if (build_with_mozilla) { - sources += [ "app_capturer_linux.cc" ] - } - } - if (rtc_use_x11) { sources += [ - "linux/mouse_cursor_monitor_x11.cc", - "linux/mouse_cursor_monitor_x11.h", - "linux/screen_capturer_x11.cc", - "linux/screen_capturer_x11.h", - "linux/shared_x_display.cc", - "linux/shared_x_display.h", - "linux/window_capturer_x11.cc", - "linux/window_capturer_x11.h", - "linux/window_finder_x11.cc", - "linux/window_finder_x11.h", - "linux/window_list_utils.cc", - "linux/window_list_utils.h", - "linux/x_atom_cache.cc", - "linux/x_atom_cache.h", - "linux/x_error_trap.cc", - "linux/x_error_trap.h", - "linux/x_server_pixel_buffer.cc", - "linux/x_server_pixel_buffer.h", + "mouse_cursor_monitor_x11.cc", + "screen_capturer_x11.cc", + "window_capturer_x11.cc", + "window_finder_x11.cc", + "window_finder_x11.h", + "x11/shared_x_display.cc", + "x11/shared_x_display.h", + "x11/window_list_utils.cc", + "x11/window_list_utils.h", + "x11/x_atom_cache.cc", + "x11/x_atom_cache.h", + "x11/x_error_trap.cc", + "x11/x_error_trap.h", + "x11/x_server_pixel_buffer.cc", + "x11/x_server_pixel_buffer.h", ] configs += [ "//build/config/linux:x11" ] if (build_with_mozilla) { sources += [ - "linux/app_capturer_x11.cc", - "linux/desktop_device_info_linux.cc", - "linux/desktop_device_info_linux.h", - "linux/shared_x_util.cc", - "linux/shared_x_util.h", + "app_capturer_x11.cc", + "app_capturer_x11.h", + "x11/desktop_device_info_x11.cc", + "x11/desktop_device_info_x11.h", + "x11/shared_x_util.cc", + "x11/shared_x_util.h", ] } } - if (rtc_use_pipewire) { - sources += [ - "linux/base_capturer_pipewire.cc", - "linux/base_capturer_pipewire.h", - "linux/screen_capturer_pipewire.cc", - "linux/screen_capturer_pipewire.h", - "linux/window_capturer_pipewire.cc", - "linux/window_capturer_pipewire.h", - ] - - configs += [ - ":gio", - ":pipewire", - ] - } - - if (!is_win && !is_mac && !rtc_use_x11 && !rtc_use_pipewire) { + if (!is_win && !is_mac && !rtc_use_x11) { sources += [ "mouse_cursor_monitor_null.cc", "screen_capturer_null.cc", diff --git a/modules/desktop_capture/desktop_capture_options.h b/modules/desktop_capture/desktop_capture_options.h index e9587a3f50..44ba79ddac 100644 --- a/modules/desktop_capture/desktop_capture_options.h +++ b/modules/desktop_capture/desktop_capture_options.h @@ -15,7 +15,7 @@ #include "rtc_base/system/rtc_export.h" #if defined(USE_X11) -#include "modules/desktop_capture/linux/shared_x_display.h" +#include "modules/desktop_capture/x11/shared_x_display.h" #endif #if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS) @@ -115,11 +115,6 @@ class RTC_EXPORT DesktopCaptureOptions { } #endif -#if defined(WEBRTC_USE_PIPEWIRE) - bool allow_pipewire() const { return allow_pipewire_; } - void set_allow_pipewire(bool allow) { allow_pipewire_ = allow; } -#endif - private: #if defined(USE_X11) rtc::scoped_refptr x_display_; @@ -143,9 +138,6 @@ class RTC_EXPORT DesktopCaptureOptions { #endif bool disable_effects_ = true; bool detect_updated_region_ = false; -#if defined(WEBRTC_USE_PIPEWIRE) - bool allow_pipewire_ = false; -#endif }; } // namespace webrtc diff --git a/modules/desktop_capture/desktop_capturer.cc b/modules/desktop_capture/desktop_capturer.cc index d43d571a86..166d97cc52 100644 --- a/modules/desktop_capture/desktop_capturer.cc +++ b/modules/desktop_capture/desktop_capturer.cc @@ -60,17 +60,4 @@ std::unique_ptr DesktopCapturer::CreateScreenCapturer( return capturer; } -#if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) -bool DesktopCapturer::IsRunningUnderWayland() { - const char* xdg_session_type = getenv("XDG_SESSION_TYPE"); - if (!xdg_session_type || strncmp(xdg_session_type, "wayland", 7) != 0) - return false; - - if (!(getenv("WAYLAND_DISPLAY"))) - return false; - - return true; -} -#endif // defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) - } // namespace webrtc diff --git a/modules/desktop_capture/desktop_capturer.h b/modules/desktop_capture/desktop_capturer.h index f9dacc1f7a..effe0df506 100644 --- a/modules/desktop_capture/desktop_capturer.h +++ b/modules/desktop_capture/desktop_capturer.h @@ -135,10 +135,6 @@ class RTC_EXPORT DesktopCapturer { static std::unique_ptr CreateScreenCapturer( const DesktopCaptureOptions& options); -#if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) - static bool IsRunningUnderWayland(); -#endif // defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) - protected: // CroppingWindowCapturer needs to create raw capturers without wrappers, so // the following two functions are protected. diff --git a/modules/desktop_capture/linux/base_capturer_pipewire.cc b/modules/desktop_capture/linux/base_capturer_pipewire.cc deleted file mode 100644 index 62d9994d32..0000000000 --- a/modules/desktop_capture/linux/base_capturer_pipewire.cc +++ /dev/null @@ -1,843 +0,0 @@ -/* - * 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/base_capturer_pipewire.h" - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include "absl/memory/memory.h" -#include "modules/desktop_capture/desktop_capture_options.h" -#include "modules/desktop_capture/desktop_capturer.h" -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" - -namespace webrtc { - -const char kDesktopBusName[] = "org.freedesktop.portal.Desktop"; -const char kDesktopObjectPath[] = "/org/freedesktop/portal/desktop"; -const char kDesktopRequestObjectPath[] = - "/org/freedesktop/portal/desktop/request"; -const char kSessionInterfaceName[] = "org.freedesktop.portal.Session"; -const char kRequestInterfaceName[] = "org.freedesktop.portal.Request"; -const char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast"; - -const int kBytesPerPixel = 4; - -// static -void BaseCapturerPipeWire::OnStateChanged(void* data, - pw_remote_state old_state, - pw_remote_state state, - const char* error_message) { - BaseCapturerPipeWire* that = static_cast(data); - RTC_DCHECK(that); - - switch (state) { - case PW_REMOTE_STATE_ERROR: - RTC_LOG(LS_ERROR) << "PipeWire remote state error: " << error_message; - break; - case PW_REMOTE_STATE_CONNECTED: - RTC_LOG(LS_INFO) << "PipeWire remote state: connected."; - that->CreateReceivingStream(); - break; - case PW_REMOTE_STATE_CONNECTING: - RTC_LOG(LS_INFO) << "PipeWire remote state: connecting."; - break; - case PW_REMOTE_STATE_UNCONNECTED: - RTC_LOG(LS_INFO) << "PipeWire remote state: unconnected."; - break; - } -} - -// static -void BaseCapturerPipeWire::OnStreamStateChanged(void* data, - pw_stream_state old_state, - pw_stream_state state, - const char* error_message) { - BaseCapturerPipeWire* that = static_cast(data); - RTC_DCHECK(that); - - switch (state) { - case PW_STREAM_STATE_ERROR: - RTC_LOG(LS_ERROR) << "PipeWire stream state error: " << error_message; - break; - case PW_STREAM_STATE_CONFIGURE: - pw_stream_set_active(that->pw_stream_, true); - break; - case PW_STREAM_STATE_UNCONNECTED: - case PW_STREAM_STATE_CONNECTING: - case PW_STREAM_STATE_READY: - case PW_STREAM_STATE_PAUSED: - case PW_STREAM_STATE_STREAMING: - break; - } -} - -// static -void BaseCapturerPipeWire::OnStreamFormatChanged(void* data, - const struct spa_pod* format) { - BaseCapturerPipeWire* that = static_cast(data); - RTC_DCHECK(that); - - RTC_LOG(LS_INFO) << "PipeWire stream format changed."; - - if (!format) { - pw_stream_finish_format(that->pw_stream_, /*res=*/0, /*params=*/nullptr, - /*n_params=*/0); - return; - } - - that->spa_video_format_ = new spa_video_info_raw(); - spa_format_video_raw_parse(format, that->spa_video_format_, - &that->pw_type_->format_video); - - auto width = that->spa_video_format_->size.width; - auto height = that->spa_video_format_->size.height; - auto stride = SPA_ROUND_UP_N(width * kBytesPerPixel, 4); - auto size = height * stride; - - uint8_t buffer[1024] = {}; - auto builder = spa_pod_builder{buffer, sizeof(buffer)}; - - // Setup buffers and meta header for new format. - const struct spa_pod* params[2]; - params[0] = reinterpret_cast(spa_pod_builder_object( - &builder, - // id to enumerate buffer requirements - that->pw_core_type_->param.idBuffers, - that->pw_core_type_->param_buffers.Buffers, - // Size: specified as integer (i) and set to specified size - ":", that->pw_core_type_->param_buffers.size, "i", size, - // Stride: specified as integer (i) and set to specified stride - ":", that->pw_core_type_->param_buffers.stride, "i", stride, - // Buffers: specifies how many buffers we want to deal with, set as - // integer (i) where preferred number is 8, then allowed number is defined - // as range (r) from min and max values and it is undecided (u) to allow - // negotiation - ":", that->pw_core_type_->param_buffers.buffers, "iru", 8, - SPA_POD_PROP_MIN_MAX(1, 32), - // Align: memory alignment of the buffer, set as integer (i) to specified - // value - ":", that->pw_core_type_->param_buffers.align, "i", 16)); - params[1] = reinterpret_cast(spa_pod_builder_object( - &builder, - // id to enumerate supported metadata - that->pw_core_type_->param.idMeta, that->pw_core_type_->param_meta.Meta, - // Type: specified as id or enum (I) - ":", that->pw_core_type_->param_meta.type, "I", - that->pw_core_type_->meta.Header, - // Size: size of the metadata, specified as integer (i) - ":", that->pw_core_type_->param_meta.size, "i", - sizeof(struct spa_meta_header))); - - pw_stream_finish_format(that->pw_stream_, /*res=*/0, params, /*n_params=*/2); -} - -// static -void BaseCapturerPipeWire::OnStreamProcess(void* data) { - BaseCapturerPipeWire* that = static_cast(data); - RTC_DCHECK(that); - - pw_buffer* buf = nullptr; - - if (!(buf = pw_stream_dequeue_buffer(that->pw_stream_))) { - return; - } - - that->HandleBuffer(buf); - - pw_stream_queue_buffer(that->pw_stream_, buf); -} - -BaseCapturerPipeWire::BaseCapturerPipeWire(CaptureSourceType source_type) - : capture_source_type_(source_type) {} - -BaseCapturerPipeWire::~BaseCapturerPipeWire() { - if (pw_main_loop_) { - pw_thread_loop_stop(pw_main_loop_); - } - - if (pw_type_) { - delete pw_type_; - } - - if (spa_video_format_) { - delete spa_video_format_; - } - - if (pw_stream_) { - pw_stream_destroy(pw_stream_); - } - - if (pw_remote_) { - pw_remote_destroy(pw_remote_); - } - - if (pw_core_) { - pw_core_destroy(pw_core_); - } - - if (pw_main_loop_) { - pw_thread_loop_destroy(pw_main_loop_); - } - - if (pw_loop_) { - pw_loop_destroy(pw_loop_); - } - - if (current_frame_) { - free(current_frame_); - } - - if (start_request_signal_id_) { - g_dbus_connection_signal_unsubscribe(connection_, start_request_signal_id_); - } - if (sources_request_signal_id_) { - g_dbus_connection_signal_unsubscribe(connection_, - sources_request_signal_id_); - } - if (session_request_signal_id_) { - g_dbus_connection_signal_unsubscribe(connection_, - session_request_signal_id_); - } - - if (session_handle_) { - GDBusMessage* message = g_dbus_message_new_method_call( - kDesktopBusName, session_handle_, kSessionInterfaceName, "Close"); - if (message) { - GError* error = nullptr; - g_dbus_connection_send_message(connection_, message, - G_DBUS_SEND_MESSAGE_FLAGS_NONE, - /*out_serial=*/nullptr, &error); - if (error) { - RTC_LOG(LS_ERROR) << "Failed to close the session: " << error->message; - g_error_free(error); - } - g_object_unref(message); - } - } - - g_free(start_handle_); - g_free(sources_handle_); - g_free(session_handle_); - g_free(portal_handle_); - - if (proxy_) { - g_clear_object(&proxy_); - } -} - -void BaseCapturerPipeWire::InitPortal() { - g_dbus_proxy_new_for_bus( - G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, /*info=*/nullptr, - kDesktopBusName, kDesktopObjectPath, kScreenCastInterfaceName, - /*cancellable=*/nullptr, - reinterpret_cast(OnProxyRequested), this); -} - -void BaseCapturerPipeWire::InitPipeWire() { - pw_init(/*argc=*/nullptr, /*argc=*/nullptr); - - pw_loop_ = pw_loop_new(/*properties=*/nullptr); - pw_main_loop_ = pw_thread_loop_new(pw_loop_, "pipewire-main-loop"); - - pw_core_ = pw_core_new(pw_loop_, /*properties=*/nullptr); - pw_core_type_ = pw_core_get_type(pw_core_); - pw_remote_ = pw_remote_new(pw_core_, nullptr, /*user_data_size=*/0); - - InitPipeWireTypes(); - - // Initialize event handlers, remote end and stream-related. - pw_remote_events_.version = PW_VERSION_REMOTE_EVENTS; - pw_remote_events_.state_changed = &OnStateChanged; - - pw_stream_events_.version = PW_VERSION_STREAM_EVENTS; - pw_stream_events_.state_changed = &OnStreamStateChanged; - pw_stream_events_.format_changed = &OnStreamFormatChanged; - pw_stream_events_.process = &OnStreamProcess; - - pw_remote_add_listener(pw_remote_, &spa_remote_listener_, &pw_remote_events_, - this); - pw_remote_connect_fd(pw_remote_, pw_fd_); - - if (pw_thread_loop_start(pw_main_loop_) < 0) { - RTC_LOG(LS_ERROR) << "Failed to start main PipeWire loop"; - portal_init_failed_ = true; - } -} - -void BaseCapturerPipeWire::InitPipeWireTypes() { - spa_type_map* map = pw_core_type_->map; - pw_type_ = new PipeWireType(); - - spa_type_media_type_map(map, &pw_type_->media_type); - spa_type_media_subtype_map(map, &pw_type_->media_subtype); - spa_type_format_video_map(map, &pw_type_->format_video); - spa_type_video_format_map(map, &pw_type_->video_format); -} - -void BaseCapturerPipeWire::CreateReceivingStream() { - spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; - spa_rectangle pwScreenBounds = - spa_rectangle{static_cast(desktop_size_.width()), - static_cast(desktop_size_.height())}; - - spa_fraction pwFrameRateMin = spa_fraction{0, 1}; - spa_fraction pwFrameRateMax = spa_fraction{60, 1}; - - pw_properties* reuseProps = pw_properties_new("pipewire.client.reuse", "1", - /*end of varargs*/ nullptr); - pw_stream_ = pw_stream_new(pw_remote_, "webrtc-consume-stream", reuseProps); - - uint8_t buffer[1024] = {}; - const spa_pod* params[1]; - spa_pod_builder builder = spa_pod_builder{buffer, sizeof(buffer)}; - params[0] = reinterpret_cast(spa_pod_builder_object( - &builder, - // id to enumerate formats - pw_core_type_->param.idEnumFormat, pw_core_type_->spa_format, "I", - pw_type_->media_type.video, "I", pw_type_->media_subtype.raw, - // Video format: specified as id or enum (I), preferred format is BGRx, - // then allowed formats are enumerated (e) and the format is undecided (u) - // to allow negotiation - ":", pw_type_->format_video.format, "Ieu", pw_type_->video_format.BGRx, - SPA_POD_PROP_ENUM(2, pw_type_->video_format.RGBx, - pw_type_->video_format.BGRx), - // Video size: specified as rectangle (R), preferred size is specified as - // first parameter, then allowed size is defined as range (r) from min and - // max values and the format is undecided (u) to allow negotiation - ":", pw_type_->format_video.size, "Rru", &pwScreenBounds, 2, - &pwMinScreenBounds, &pwScreenBounds, - // Frame rate: specified as fraction (F) and set to minimum frame rate - // value - ":", pw_type_->format_video.framerate, "F", &pwFrameRateMin, - // Max frame rate: specified as fraction (F), preferred frame rate is set - // to maximum value, then allowed frame rate is defined as range (r) from - // min and max values and it is undecided (u) to allow negotiation - ":", pw_type_->format_video.max_framerate, "Fru", &pwFrameRateMax, 2, - &pwFrameRateMin, &pwFrameRateMax)); - - pw_stream_add_listener(pw_stream_, &spa_stream_listener_, &pw_stream_events_, - this); - pw_stream_flags flags = static_cast( - PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE | - PW_STREAM_FLAG_MAP_BUFFERS); - if (pw_stream_connect(pw_stream_, PW_DIRECTION_INPUT, /*port_path=*/nullptr, - flags, params, - /*n_params=*/1) != 0) { - RTC_LOG(LS_ERROR) << "Could not connect receiving stream."; - portal_init_failed_ = true; - return; - } -} - -void BaseCapturerPipeWire::HandleBuffer(pw_buffer* buffer) { - spa_buffer* spaBuffer = buffer->buffer; - void* src = nullptr; - - if (!(src = spaBuffer->datas[0].data)) { - return; - } - - uint32_t maxSize = spaBuffer->datas[0].maxsize; - int32_t srcStride = spaBuffer->datas[0].chunk->stride; - if (srcStride != (desktop_size_.width() * kBytesPerPixel)) { - RTC_LOG(LS_ERROR) << "Got buffer with stride different from screen stride: " - << srcStride - << " != " << (desktop_size_.width() * kBytesPerPixel); - portal_init_failed_ = true; - return; - } - - if (!current_frame_) { - current_frame_ = static_cast(malloc(maxSize)); - } - RTC_DCHECK(current_frame_ != nullptr); - - // If both sides decided to go with the RGBx format we need to convert it to - // BGRx to match color format expected by WebRTC. - if (spa_video_format_->format == pw_type_->video_format.RGBx) { - uint8_t* tempFrame = static_cast(malloc(maxSize)); - std::memcpy(tempFrame, src, maxSize); - ConvertRGBxToBGRx(tempFrame, maxSize); - std::memcpy(current_frame_, tempFrame, maxSize); - free(tempFrame); - } else { - std::memcpy(current_frame_, src, maxSize); - } -} - -void BaseCapturerPipeWire::ConvertRGBxToBGRx(uint8_t* frame, uint32_t size) { - // Change color format for KDE KWin which uses RGBx and not BGRx - for (uint32_t i = 0; i < size; i += 4) { - uint8_t tempR = frame[i]; - uint8_t tempB = frame[i + 2]; - frame[i] = tempB; - frame[i + 2] = tempR; - } -} - -guint BaseCapturerPipeWire::SetupRequestResponseSignal( - const gchar* object_path, - GDBusSignalCallback callback) { - return g_dbus_connection_signal_subscribe( - connection_, kDesktopBusName, kRequestInterfaceName, "Response", - object_path, /*arg0=*/nullptr, G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, - callback, this, /*user_data_free_func=*/nullptr); -} - -// static -void BaseCapturerPipeWire::OnProxyRequested(GObject* /*object*/, - GAsyncResult* result, - gpointer user_data) { - BaseCapturerPipeWire* that = static_cast(user_data); - RTC_DCHECK(that); - - GError* error = nullptr; - that->proxy_ = g_dbus_proxy_new_finish(result, &error); - if (!that->proxy_) { - RTC_LOG(LS_ERROR) << "Failed to create a proxy for the screen cast portal: " - << error->message; - g_error_free(error); - that->portal_init_failed_ = true; - return; - } - that->connection_ = g_dbus_proxy_get_connection(that->proxy_); - - RTC_LOG(LS_INFO) << "Created proxy for the screen cast portal."; - that->SessionRequest(); -} - -// static -gchar* BaseCapturerPipeWire::PrepareSignalHandle(GDBusConnection* connection, - const gchar* token) { - gchar* sender = g_strdup(g_dbus_connection_get_unique_name(connection) + 1); - for (int i = 0; sender[i]; i++) { - if (sender[i] == '.') { - sender[i] = '_'; - } - } - - gchar* handle = g_strconcat(kDesktopRequestObjectPath, "/", sender, "/", - token, /*end of varargs*/ nullptr); - g_free(sender); - - return handle; -} - -void BaseCapturerPipeWire::SessionRequest() { - GVariantBuilder builder; - gchar* variant_string; - - g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); - variant_string = - g_strdup_printf("webrtc_session%d", g_random_int_range(0, G_MAXINT)); - g_variant_builder_add(&builder, "{sv}", "session_handle_token", - g_variant_new_string(variant_string)); - g_free(variant_string); - variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); - g_variant_builder_add(&builder, "{sv}", "handle_token", - g_variant_new_string(variant_string)); - - portal_handle_ = PrepareSignalHandle(connection_, variant_string); - session_request_signal_id_ = SetupRequestResponseSignal( - portal_handle_, OnSessionRequestResponseSignal); - g_free(variant_string); - - RTC_LOG(LS_INFO) << "Screen cast session requested."; - g_dbus_proxy_call( - proxy_, "CreateSession", g_variant_new("(a{sv})", &builder), - G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, /*cancellable=*/nullptr, - reinterpret_cast(OnSessionRequested), this); -} - -// static -void BaseCapturerPipeWire::OnSessionRequested(GDBusConnection* connection, - GAsyncResult* result, - gpointer user_data) { - BaseCapturerPipeWire* that = static_cast(user_data); - RTC_DCHECK(that); - - GError* error = nullptr; - GVariant* variant = g_dbus_proxy_call_finish(that->proxy_, result, &error); - if (!variant) { - RTC_LOG(LS_ERROR) << "Failed to create a screen cast session: " - << error->message; - g_error_free(error); - that->portal_init_failed_ = true; - return; - } - RTC_LOG(LS_INFO) << "Initializing the screen cast session."; - - gchar* handle = nullptr; - g_variant_get_child(variant, 0, "o", &handle); - g_variant_unref(variant); - if (!handle) { - RTC_LOG(LS_ERROR) << "Failed to initialize the screen cast session."; - if (that->session_request_signal_id_) { - g_dbus_connection_signal_unsubscribe(connection, - that->session_request_signal_id_); - that->session_request_signal_id_ = 0; - } - that->portal_init_failed_ = true; - return; - } - - g_free(handle); - - RTC_LOG(LS_INFO) << "Subscribing to the screen cast session."; -} - -// static -void BaseCapturerPipeWire::OnSessionRequestResponseSignal( - GDBusConnection* connection, - const gchar* sender_name, - const gchar* object_path, - const gchar* interface_name, - const gchar* signal_name, - GVariant* parameters, - gpointer user_data) { - BaseCapturerPipeWire* that = static_cast(user_data); - RTC_DCHECK(that); - - RTC_LOG(LS_INFO) - << "Received response for the screen cast session subscription."; - - guint32 portal_response; - GVariant* response_data; - g_variant_get(parameters, "(u@a{sv})", &portal_response, &response_data); - g_variant_lookup(response_data, "session_handle", "s", - &that->session_handle_); - g_variant_unref(response_data); - - if (!that->session_handle_ || portal_response) { - RTC_LOG(LS_ERROR) - << "Failed to request the screen cast session subscription."; - that->portal_init_failed_ = true; - return; - } - - that->SourcesRequest(); -} - -void BaseCapturerPipeWire::SourcesRequest() { - GVariantBuilder builder; - gchar* variant_string; - - g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); - // We want to record monitor content. - g_variant_builder_add(&builder, "{sv}", "types", - g_variant_new_uint32(capture_source_type_)); - // We don't want to allow selection of multiple sources. - g_variant_builder_add(&builder, "{sv}", "multiple", - g_variant_new_boolean(false)); - variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); - g_variant_builder_add(&builder, "{sv}", "handle_token", - g_variant_new_string(variant_string)); - - sources_handle_ = PrepareSignalHandle(connection_, variant_string); - sources_request_signal_id_ = SetupRequestResponseSignal( - sources_handle_, OnSourcesRequestResponseSignal); - g_free(variant_string); - - RTC_LOG(LS_INFO) << "Requesting sources from the screen cast session."; - g_dbus_proxy_call( - proxy_, "SelectSources", - g_variant_new("(oa{sv})", session_handle_, &builder), - G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, /*cancellable=*/nullptr, - reinterpret_cast(OnSourcesRequested), this); -} - -// static -void BaseCapturerPipeWire::OnSourcesRequested(GDBusConnection* connection, - GAsyncResult* result, - gpointer user_data) { - BaseCapturerPipeWire* that = static_cast(user_data); - RTC_DCHECK(that); - - GError* error = nullptr; - GVariant* variant = g_dbus_proxy_call_finish(that->proxy_, result, &error); - if (!variant) { - RTC_LOG(LS_ERROR) << "Failed to request the sources: " << error->message; - g_error_free(error); - that->portal_init_failed_ = true; - return; - } - - RTC_LOG(LS_INFO) << "Sources requested from the screen cast session."; - - gchar* handle = nullptr; - g_variant_get_child(variant, 0, "o", &handle); - g_variant_unref(variant); - if (!handle) { - RTC_LOG(LS_ERROR) << "Failed to initialize the screen cast session."; - if (that->sources_request_signal_id_) { - g_dbus_connection_signal_unsubscribe(connection, - that->sources_request_signal_id_); - that->sources_request_signal_id_ = 0; - } - that->portal_init_failed_ = true; - return; - } - - g_free(handle); - - RTC_LOG(LS_INFO) << "Subscribed to sources signal."; -} - -// static -void BaseCapturerPipeWire::OnSourcesRequestResponseSignal( - GDBusConnection* connection, - const gchar* sender_name, - const gchar* object_path, - const gchar* interface_name, - const gchar* signal_name, - GVariant* parameters, - gpointer user_data) { - BaseCapturerPipeWire* that = static_cast(user_data); - RTC_DCHECK(that); - - RTC_LOG(LS_INFO) << "Received sources signal from session."; - - guint32 portal_response; - g_variant_get(parameters, "(u@a{sv})", &portal_response, nullptr); - if (portal_response) { - RTC_LOG(LS_ERROR) - << "Failed to select sources for the screen cast session."; - that->portal_init_failed_ = true; - return; - } - - that->StartRequest(); -} - -void BaseCapturerPipeWire::StartRequest() { - GVariantBuilder builder; - gchar* variant_string; - - g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); - variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); - g_variant_builder_add(&builder, "{sv}", "handle_token", - g_variant_new_string(variant_string)); - - start_handle_ = PrepareSignalHandle(connection_, variant_string); - start_request_signal_id_ = - SetupRequestResponseSignal(start_handle_, OnStartRequestResponseSignal); - g_free(variant_string); - - // "Identifier for the application window", this is Wayland, so not "x11:...". - const gchar parent_window[] = ""; - - RTC_LOG(LS_INFO) << "Starting the screen cast session."; - g_dbus_proxy_call( - proxy_, "Start", - g_variant_new("(osa{sv})", session_handle_, parent_window, &builder), - G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, /*cancellable=*/nullptr, - reinterpret_cast(OnStartRequested), this); -} - -// static -void BaseCapturerPipeWire::OnStartRequested(GDBusConnection* connection, - GAsyncResult* result, - gpointer user_data) { - BaseCapturerPipeWire* that = static_cast(user_data); - RTC_DCHECK(that); - - GError* error = nullptr; - GVariant* variant = g_dbus_proxy_call_finish(that->proxy_, result, &error); - if (!variant) { - RTC_LOG(LS_ERROR) << "Failed to start the screen cast session: " - << error->message; - g_error_free(error); - that->portal_init_failed_ = true; - return; - } - - RTC_LOG(LS_INFO) << "Initializing the start of the screen cast session."; - - gchar* handle = nullptr; - g_variant_get_child(variant, 0, "o", &handle); - g_variant_unref(variant); - if (!handle) { - RTC_LOG(LS_ERROR) - << "Failed to initialize the start of the screen cast session."; - if (that->start_request_signal_id_) { - g_dbus_connection_signal_unsubscribe(connection, - that->start_request_signal_id_); - that->start_request_signal_id_ = 0; - } - that->portal_init_failed_ = true; - return; - } - - g_free(handle); - - RTC_LOG(LS_INFO) << "Subscribed to the start signal."; -} - -// static -void BaseCapturerPipeWire::OnStartRequestResponseSignal( - GDBusConnection* connection, - const gchar* sender_name, - const gchar* object_path, - const gchar* interface_name, - const gchar* signal_name, - GVariant* parameters, - gpointer user_data) { - BaseCapturerPipeWire* that = static_cast(user_data); - RTC_DCHECK(that); - - RTC_LOG(LS_INFO) << "Start signal received."; - guint32 portal_response; - GVariant* response_data; - GVariantIter* iter = nullptr; - g_variant_get(parameters, "(u@a{sv})", &portal_response, &response_data); - if (portal_response || !response_data) { - RTC_LOG(LS_ERROR) << "Failed to start the screen cast session."; - that->portal_init_failed_ = true; - return; - } - - // Array of PipeWire streams. See - // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml - // documentation for . - if (g_variant_lookup(response_data, "streams", "a(ua{sv})", &iter)) { - GVariant* variant; - - while (g_variant_iter_next(iter, "@(ua{sv})", &variant)) { - guint32 stream_id; - gint32 width; - gint32 height; - GVariant* options; - - g_variant_get(variant, "(u@a{sv})", &stream_id, &options); - RTC_DCHECK(options != nullptr); - - g_variant_lookup(options, "size", "(ii)", &width, &height); - - that->desktop_size_.set(width, height); - - g_variant_unref(options); - g_variant_unref(variant); - } - } - g_variant_iter_free(iter); - g_variant_unref(response_data); - - that->OpenPipeWireRemote(); -} - -void BaseCapturerPipeWire::OpenPipeWireRemote() { - GVariantBuilder builder; - g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); - - RTC_LOG(LS_INFO) << "Opening the PipeWire remote."; - - g_dbus_proxy_call_with_unix_fd_list( - proxy_, "OpenPipeWireRemote", - g_variant_new("(oa{sv})", session_handle_, &builder), - G_DBUS_CALL_FLAGS_NONE, /*timeout=*/-1, /*fd_list=*/nullptr, - /*cancellable=*/nullptr, - reinterpret_cast(OnOpenPipeWireRemoteRequested), - this); -} - -// static -void BaseCapturerPipeWire::OnOpenPipeWireRemoteRequested( - GDBusConnection* connection, - GAsyncResult* result, - gpointer user_data) { - BaseCapturerPipeWire* that = static_cast(user_data); - RTC_DCHECK(that); - - GError* error = nullptr; - GUnixFDList* outlist = nullptr; - GVariant* variant = g_dbus_proxy_call_with_unix_fd_list_finish( - that->proxy_, &outlist, result, &error); - if (!variant) { - RTC_LOG(LS_ERROR) << "Failed to open the PipeWire remote: " - << error->message; - g_error_free(error); - that->portal_init_failed_ = true; - return; - } - - gint32 index; - g_variant_get(variant, "(h)", &index); - - if ((that->pw_fd_ = g_unix_fd_list_get(outlist, index, &error)) == -1) { - RTC_LOG(LS_ERROR) << "Failed to get file descriptor from the list: " - << error->message; - g_error_free(error); - g_variant_unref(variant); - that->portal_init_failed_ = true; - return; - } - - g_variant_unref(variant); - g_object_unref(outlist); - - that->InitPipeWire(); - RTC_LOG(LS_INFO) << "PipeWire remote opened."; -} - -void BaseCapturerPipeWire::Start(Callback* callback) { - RTC_DCHECK(!callback_); - RTC_DCHECK(callback); - - InitPortal(); - - callback_ = callback; -} - -void BaseCapturerPipeWire::CaptureFrame() { - if (portal_init_failed_) { - callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); - return; - } - - if (!current_frame_) { - callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); - return; - } - - std::unique_ptr result(new BasicDesktopFrame(desktop_size_)); - result->CopyPixelsFrom( - current_frame_, (desktop_size_.width() * kBytesPerPixel), - DesktopRect::MakeWH(desktop_size_.width(), desktop_size_.height())); - if (!result) { - callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); - return; - } - callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); -} - -bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) { - RTC_DCHECK(sources->size() == 0); - // List of available screens is already presented by the xdg-desktop-portal. - // But we have to add an empty source as the code expects it. - sources->push_back({0}); - return true; -} - -bool BaseCapturerPipeWire::SelectSource(SourceId id) { - // Screen selection is handled by the xdg-desktop-portal. - return true; -} - -} // namespace webrtc diff --git a/modules/desktop_capture/linux/base_capturer_pipewire.h b/modules/desktop_capture/linux/base_capturer_pipewire.h deleted file mode 100644 index 56b101acba..0000000000 --- a/modules/desktop_capture/linux/base_capturer_pipewire.h +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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. - */ - -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ - -#include -#define typeof __typeof__ -#include -#include - -#include "modules/desktop_capture/desktop_capture_options.h" -#include "modules/desktop_capture/desktop_capturer.h" -#include "rtc_base/constructormagic.h" - -namespace webrtc { - -class PipeWireType { - public: - spa_type_media_type media_type; - spa_type_media_subtype media_subtype; - spa_type_format_video format_video; - spa_type_video_format video_format; -}; - -class BaseCapturerPipeWire : public DesktopCapturer { - public: - enum CaptureSourceType { Screen = 1, Window }; - - explicit BaseCapturerPipeWire(CaptureSourceType source_type); - ~BaseCapturerPipeWire() override; - - // DesktopCapturer interface. - void Start(Callback* delegate) override; - void CaptureFrame() override; - bool GetSourceList(SourceList* sources) override; - bool SelectSource(SourceId id) override; - - private: - // PipeWire types --> - pw_core* pw_core_ = nullptr; - pw_type* pw_core_type_ = nullptr; - pw_stream* pw_stream_ = nullptr; - pw_remote* pw_remote_ = nullptr; - pw_loop* pw_loop_ = nullptr; - pw_thread_loop* pw_main_loop_ = nullptr; - PipeWireType* pw_type_ = nullptr; - - spa_hook spa_stream_listener_ = {}; - spa_hook spa_remote_listener_ = {}; - - pw_stream_events pw_stream_events_ = {}; - pw_remote_events pw_remote_events_ = {}; - - spa_video_info_raw* spa_video_format_ = nullptr; - - gint32 pw_fd_ = -1; - - CaptureSourceType capture_source_type_ = - BaseCapturerPipeWire::CaptureSourceType::Screen; - - // <-- end of PipeWire types - - GDBusConnection* connection_ = nullptr; - GDBusProxy* proxy_ = nullptr; - gchar* portal_handle_ = nullptr; - gchar* session_handle_ = nullptr; - gchar* sources_handle_ = nullptr; - gchar* start_handle_ = nullptr; - guint session_request_signal_id_ = 0; - guint sources_request_signal_id_ = 0; - guint start_request_signal_id_ = 0; - - DesktopSize desktop_size_ = {}; - DesktopCaptureOptions options_ = {}; - - uint8_t* current_frame_ = nullptr; - Callback* callback_ = nullptr; - - bool portal_init_failed_ = false; - - void InitPortal(); - void InitPipeWire(); - void InitPipeWireTypes(); - - void CreateReceivingStream(); - void HandleBuffer(pw_buffer* buffer); - - void ConvertRGBxToBGRx(uint8_t* frame, uint32_t size); - - static void OnStateChanged(void* data, - pw_remote_state old_state, - pw_remote_state state, - const char* error); - static void OnStreamStateChanged(void* data, - pw_stream_state old_state, - pw_stream_state state, - const char* error_message); - - static void OnStreamFormatChanged(void* data, const struct spa_pod* format); - static void OnStreamProcess(void* data); - static void OnNewBuffer(void* data, uint32_t id); - - guint SetupRequestResponseSignal(const gchar* object_path, - GDBusSignalCallback callback); - - static void OnProxyRequested(GObject* object, - GAsyncResult* result, - gpointer user_data); - - static gchar* PrepareSignalHandle(GDBusConnection* connection, - const gchar* token); - - void SessionRequest(); - static void OnSessionRequested(GDBusConnection* connection, - GAsyncResult* result, - gpointer user_data); - static void OnSessionRequestResponseSignal(GDBusConnection* connection, - const gchar* sender_name, - const gchar* object_path, - const gchar* interface_name, - const gchar* signal_name, - GVariant* parameters, - gpointer user_data); - - void SourcesRequest(); - static void OnSourcesRequested(GDBusConnection* connection, - GAsyncResult* result, - gpointer user_data); - static void OnSourcesRequestResponseSignal(GDBusConnection* connection, - const gchar* sender_name, - const gchar* object_path, - const gchar* interface_name, - const gchar* signal_name, - GVariant* parameters, - gpointer user_data); - - void StartRequest(); - static void OnStartRequested(GDBusConnection* connection, - GAsyncResult* result, - gpointer user_data); - static void OnStartRequestResponseSignal(GDBusConnection* connection, - const gchar* sender_name, - const gchar* object_path, - const gchar* interface_name, - const gchar* signal_name, - GVariant* parameters, - gpointer user_data); - - void OpenPipeWireRemote(); - static void OnOpenPipeWireRemoteRequested(GDBusConnection* connection, - GAsyncResult* result, - gpointer user_data); - - RTC_DISALLOW_COPY_AND_ASSIGN(BaseCapturerPipeWire); -}; - -} // namespace webrtc - -#endif // MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ diff --git a/modules/desktop_capture/linux/mouse_cursor_monitor_x11.h b/modules/desktop_capture/linux/mouse_cursor_monitor_x11.h deleted file mode 100644 index 3e8e0ca78c..0000000000 --- a/modules/desktop_capture/linux/mouse_cursor_monitor_x11.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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. - */ - -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_MOUSE_CURSOR_MONITOR_X11_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_MOUSE_CURSOR_MONITOR_X11_H_ - -#include - -#include - -#include "modules/desktop_capture/linux/shared_x_display.h" -#include "modules/desktop_capture/mouse_cursor_monitor.h" - -namespace webrtc { - -class MouseCursorMonitorX11 : public MouseCursorMonitor, - public SharedXDisplay::XEventHandler { - public: - MouseCursorMonitorX11(const DesktopCaptureOptions& options, Window window); - ~MouseCursorMonitorX11() override; - - static MouseCursorMonitor* CreateForWindow( - const DesktopCaptureOptions& options, - WindowId window); - static MouseCursorMonitor* CreateForScreen( - const DesktopCaptureOptions& options, - ScreenId screen); - static std::unique_ptr Create( - const DesktopCaptureOptions& options); - - void Init(Callback* callback, Mode mode) override; - void Capture() override; - - private: - // SharedXDisplay::XEventHandler interface. - bool HandleXEvent(const XEvent& event) override; - - Display* display() { return x_display_->display(); } - - // Captures current cursor shape and stores it in |cursor_shape_|. - void CaptureCursor(); - - rtc::scoped_refptr x_display_; - Callback* callback_; - Mode mode_; - Window window_; - - bool have_xfixes_; - int xfixes_event_base_; - int xfixes_error_base_; - - std::unique_ptr cursor_shape_; -}; - -} // namespace webrtc - -#endif // MODULES_DESKTOP_CAPTURE_LINUX_MOUSE_CURSOR_MONITOR_X11_H_ diff --git a/modules/desktop_capture/linux/screen_capturer_pipewire.cc b/modules/desktop_capture/linux/screen_capturer_pipewire.cc deleted file mode 100644 index 724d8537d3..0000000000 --- a/modules/desktop_capture/linux/screen_capturer_pipewire.cc +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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/screen_capturer_pipewire.h" - -#include - -#include "absl/memory/memory.h" - -namespace webrtc { - -ScreenCapturerPipeWire::ScreenCapturerPipeWire() - : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Screen) {} -ScreenCapturerPipeWire::~ScreenCapturerPipeWire() {} - -// static -std::unique_ptr -ScreenCapturerPipeWire::CreateRawScreenCapturer( - const DesktopCaptureOptions& options) { - return absl::make_unique(); -} - -} // namespace webrtc diff --git a/modules/desktop_capture/linux/screen_capturer_pipewire.h b/modules/desktop_capture/linux/screen_capturer_pipewire.h deleted file mode 100644 index 66dcd680e0..0000000000 --- a/modules/desktop_capture/linux/screen_capturer_pipewire.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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. - */ - -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_PIPEWIRE_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_PIPEWIRE_H_ - -#include - -#include "modules/desktop_capture/linux/base_capturer_pipewire.h" - -namespace webrtc { - -class ScreenCapturerPipeWire : public BaseCapturerPipeWire { - public: - ScreenCapturerPipeWire(); - ~ScreenCapturerPipeWire() override; - - static std::unique_ptr CreateRawScreenCapturer( - const DesktopCaptureOptions& options); - - RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerPipeWire); -}; - -} // namespace webrtc - -#endif // MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_PIPEWIRE_H_ diff --git a/modules/desktop_capture/linux/screen_capturer_x11.h b/modules/desktop_capture/linux/screen_capturer_x11.h deleted file mode 100644 index 9f3b60c3d8..0000000000 --- a/modules/desktop_capture/linux/screen_capturer_x11.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * 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. - */ - -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_X11_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_X11_H_ - -#include -#include - -#include -#include -#include - -#include "modules/desktop_capture/desktop_capture_options.h" -#include "modules/desktop_capture/desktop_capturer.h" -#include "modules/desktop_capture/desktop_frame.h" -#include "modules/desktop_capture/linux/x_server_pixel_buffer.h" -#include "modules/desktop_capture/screen_capture_frame_queue.h" -#include "modules/desktop_capture/screen_capturer_helper.h" -#include "modules/desktop_capture/shared_desktop_frame.h" -#include "rtc_base/constructormagic.h" - -namespace webrtc { - -// A class to perform video frame capturing for Linux on X11. -// -// If XDamage is used, this class sets DesktopFrame::updated_region() according -// to the areas reported by XDamage. Otherwise this class does not detect -// DesktopFrame::updated_region(), the field is always set to the entire frame -// rectangle. ScreenCapturerDifferWrapper should be used if that functionality -// is necessary. -class ScreenCapturerX11 : public DesktopCapturer, - public SharedXDisplay::XEventHandler { - public: - ScreenCapturerX11(); - ~ScreenCapturerX11() override; - - static std::unique_ptr CreateRawScreenCapturer( - const DesktopCaptureOptions& options); - - // TODO(ajwong): Do we really want this to be synchronous? - bool Init(const DesktopCaptureOptions& options); - - // DesktopCapturer interface. - void Start(Callback* delegate) override; - void CaptureFrame() override; - bool GetSourceList(SourceList* sources) override; - bool SelectSource(SourceId id) override; - - private: - Display* display() { return options_.x_display()->display(); } - - // SharedXDisplay::XEventHandler interface. - bool HandleXEvent(const XEvent& event) override; - - void InitXDamage(); - - // Capture screen pixels to the current buffer in the queue. In the DAMAGE - // case, the ScreenCapturerHelper already holds the list of invalid rectangles - // from HandleXEvent(). In the non-DAMAGE case, this captures the - // whole screen, then calculates some invalid rectangles that include any - // differences between this and the previous capture. - std::unique_ptr CaptureScreen(); - - // Called when the screen configuration is changed. - void ScreenConfigurationChanged(); - - // Synchronize the current buffer with |last_buffer_|, by copying pixels from - // the area of |last_invalid_rects|. - // Note this only works on the assumption that kNumBuffers == 2, as - // |last_invalid_rects| holds the differences from the previous buffer and - // the one prior to that (which will then be the current buffer). - void SynchronizeFrame(); - - void DeinitXlib(); - - DesktopCaptureOptions options_; - - Callback* callback_ = nullptr; - - // X11 graphics context. - GC gc_ = nullptr; - Window root_window_ = BadValue; - - // XFixes. - bool has_xfixes_ = false; - int xfixes_event_base_ = -1; - int xfixes_error_base_ = -1; - - // XDamage information. - bool use_damage_ = false; - Damage damage_handle_ = 0; - int damage_event_base_ = -1; - int damage_error_base_ = -1; - XserverRegion damage_region_ = 0; - - // Access to the X Server's pixel buffer. - XServerPixelBuffer x_server_pixel_buffer_; - - // A thread-safe list of invalid rectangles, and the size of the most - // recently captured screen. - ScreenCapturerHelper helper_; - - // Queue of the frames buffers. - ScreenCaptureFrameQueue queue_; - - // Invalid region from the previous capture. This is used to synchronize the - // current with the last buffer used. - DesktopRegion last_invalid_region_; - - RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerX11); -}; - -} // namespace webrtc - -#endif // MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_X11_H_ diff --git a/modules/desktop_capture/linux/window_capturer_pipewire.cc b/modules/desktop_capture/linux/window_capturer_pipewire.cc deleted file mode 100644 index 1c195aaf4a..0000000000 --- a/modules/desktop_capture/linux/window_capturer_pipewire.cc +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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/window_capturer_pipewire.h" - -#include - -#include "absl/memory/memory.h" - -namespace webrtc { - -WindowCapturerPipeWire::WindowCapturerPipeWire() - : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Window) {} -WindowCapturerPipeWire::~WindowCapturerPipeWire() {} - -// static -std::unique_ptr -WindowCapturerPipeWire::CreateRawWindowCapturer( - const DesktopCaptureOptions& options) { - return absl::make_unique(); -} - -} // namespace webrtc diff --git a/modules/desktop_capture/linux/window_capturer_pipewire.h b/modules/desktop_capture/linux/window_capturer_pipewire.h deleted file mode 100644 index 7f184ef299..0000000000 --- a/modules/desktop_capture/linux/window_capturer_pipewire.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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. - */ - -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_PIPEWIRE_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_PIPEWIRE_H_ - -#include - -#include "modules/desktop_capture/linux/base_capturer_pipewire.h" - -namespace webrtc { - -class WindowCapturerPipeWire : public BaseCapturerPipeWire { - public: - WindowCapturerPipeWire(); - ~WindowCapturerPipeWire() override; - - static std::unique_ptr CreateRawWindowCapturer( - const DesktopCaptureOptions& options); - - RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerPipeWire); -}; - -} // namespace webrtc - -#endif // MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_PIPEWIRE_H_ diff --git a/modules/desktop_capture/linux/window_capturer_x11.h b/modules/desktop_capture/linux/window_capturer_x11.h deleted file mode 100644 index 4cd2c97cb9..0000000000 --- a/modules/desktop_capture/linux/window_capturer_x11.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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. - */ - -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_X11_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_X11_H_ - -#include -#include - -#include "modules/desktop_capture/desktop_capture_options.h" -#include "modules/desktop_capture/desktop_capturer.h" -#include "modules/desktop_capture/linux/window_finder_x11.h" -#include "modules/desktop_capture/linux/x_atom_cache.h" -#include "modules/desktop_capture/linux/x_server_pixel_buffer.h" -#include "rtc_base/constructormagic.h" - -namespace webrtc { - -class WindowCapturerX11 : public DesktopCapturer, - public SharedXDisplay::XEventHandler { - public: - explicit WindowCapturerX11(const DesktopCaptureOptions& options); - ~WindowCapturerX11() override; - - static std::unique_ptr CreateRawWindowCapturer( - const DesktopCaptureOptions& options); - - // DesktopCapturer interface. - void Start(Callback* callback) override; - void CaptureFrame() override; - bool GetSourceList(SourceList* sources) override; - bool SelectSource(SourceId id) override; - bool FocusOnSelectedSource() override; - bool IsOccluded(const DesktopVector& pos) override; - - // SharedXDisplay::XEventHandler interface. - bool HandleXEvent(const XEvent& event) override; - - private: - Display* display() { return x_display_->display(); } - - // Returns window title for the specified X |window|. - bool GetWindowTitle(::Window window, std::string* title); - - Callback* callback_ = nullptr; - - rtc::scoped_refptr x_display_; - - bool has_composite_extension_ = false; - - ::Window selected_window_ = 0; - XServerPixelBuffer x_server_pixel_buffer_; - XAtomCache atom_cache_; - WindowFinderX11 window_finder_; - - RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerX11); -}; - -} // namespace webrtc - -#endif // MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_X11_H_ diff --git a/modules/desktop_capture/mouse_cursor_monitor_linux.cc b/modules/desktop_capture/mouse_cursor_monitor_linux.cc deleted file mode 100644 index def344ef40..0000000000 --- a/modules/desktop_capture/mouse_cursor_monitor_linux.cc +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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/mouse_cursor_monitor.h" - -#if defined(USE_X11) -#include "modules/desktop_capture/linux/mouse_cursor_monitor_x11.h" -#endif // defined(USE_X11) - -namespace webrtc { - -// static -MouseCursorMonitor* MouseCursorMonitor::CreateForWindow( - const DesktopCaptureOptions& options, - WindowId window) { -#if defined(USE_X11) - return MouseCursorMonitorX11::CreateForWindow(options, window); -#else - return nullptr; -#endif // defined(USE_X11) -} - -// static -MouseCursorMonitor* MouseCursorMonitor::CreateForScreen( - const DesktopCaptureOptions& options, - ScreenId screen) { -#if defined(USE_X11) - return MouseCursorMonitorX11::CreateForScreen(options, screen); -#else - return nullptr; -#endif // defined(USE_X11) -} - -// static -std::unique_ptr MouseCursorMonitor::Create( - const DesktopCaptureOptions& options) { -#if defined(USE_X11) - return MouseCursorMonitorX11::Create(options); -#else - return nullptr; -#endif // defined(USE_X11) -} - -} // namespace webrtc diff --git a/modules/desktop_capture/linux/mouse_cursor_monitor_x11.cc b/modules/desktop_capture/mouse_cursor_monitor_x11.cc similarity index 86% rename from modules/desktop_capture/linux/mouse_cursor_monitor_x11.cc rename to modules/desktop_capture/mouse_cursor_monitor_x11.cc index f7503822bc..41749bd284 100644 --- a/modules/desktop_capture/linux/mouse_cursor_monitor_x11.cc +++ b/modules/desktop_capture/mouse_cursor_monitor_x11.cc @@ -8,20 +8,19 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/desktop_capture/linux/mouse_cursor_monitor_x11.h" +#include +#include "modules/desktop_capture/mouse_cursor_monitor.h" + +#include #include #include -#include -#include - #include "modules/desktop_capture/desktop_capture_options.h" #include "modules/desktop_capture/desktop_capture_types.h" #include "modules/desktop_capture/desktop_frame.h" -#include "modules/desktop_capture/linux/x_error_trap.h" #include "modules/desktop_capture/mouse_cursor.h" -#include "modules/desktop_capture/mouse_cursor_monitor.h" +#include "modules/desktop_capture/x11/x_error_trap.h" #include "rtc_base/logging.h" namespace { @@ -60,6 +59,36 @@ Window GetTopLevelWindow(Display* display, Window window) { namespace webrtc { +class MouseCursorMonitorX11 : public MouseCursorMonitor, + public SharedXDisplay::XEventHandler { + public: + MouseCursorMonitorX11(const DesktopCaptureOptions& options, Window window); + ~MouseCursorMonitorX11() override; + + void Init(Callback* callback, Mode mode) override; + void Capture() override; + + private: + // SharedXDisplay::XEventHandler interface. + bool HandleXEvent(const XEvent& event) override; + + Display* display() { return x_display_->display(); } + + // Captures current cursor shape and stores it in |cursor_shape_|. + void CaptureCursor(); + + rtc::scoped_refptr x_display_; + Callback* callback_; + Mode mode_; + Window window_; + + bool have_xfixes_; + int xfixes_event_base_; + int xfixes_error_base_; + + std::unique_ptr cursor_shape_; +}; + MouseCursorMonitorX11::MouseCursorMonitorX11( const DesktopCaptureOptions& options, Window window) @@ -202,11 +231,12 @@ void MouseCursorMonitorX11::CaptureCursor() { std::unique_ptr image( new BasicDesktopFrame(DesktopSize(img->width, img->height))); - uint64_t* src = reinterpret_cast(img->pixels); + // Xlib stores 32-bit data in longs, even if longs are 64-bits long. + unsigned long* src = img->pixels; uint32_t* dst = reinterpret_cast(image->data()); uint32_t* dst_end = dst + (img->width * img->height); while (dst < dst_end) { - *dst++ = *src++; + *dst++ = static_cast(*src++); } DesktopVector hotspot(std::min(img->width, img->xhot), @@ -218,7 +248,7 @@ void MouseCursorMonitorX11::CaptureCursor() { } // static -MouseCursorMonitor* MouseCursorMonitorX11::CreateForWindow( +MouseCursorMonitor* MouseCursorMonitor::CreateForWindow( const DesktopCaptureOptions& options, WindowId window) { if (!options.x_display()) @@ -229,7 +259,7 @@ MouseCursorMonitor* MouseCursorMonitorX11::CreateForWindow( return new MouseCursorMonitorX11(options, window); } -MouseCursorMonitor* MouseCursorMonitorX11::CreateForScreen( +MouseCursorMonitor* MouseCursorMonitor::CreateForScreen( const DesktopCaptureOptions& options, ScreenId screen) { if (!options.x_display()) @@ -238,7 +268,7 @@ MouseCursorMonitor* MouseCursorMonitorX11::CreateForScreen( options, DefaultRootWindow(options.x_display()->display())); } -std::unique_ptr MouseCursorMonitorX11::Create( +std::unique_ptr MouseCursorMonitor::Create( const DesktopCaptureOptions& options) { return std::unique_ptr( CreateForScreen(options, kFullDesktopScreenId)); diff --git a/modules/desktop_capture/screen_capturer_linux.cc b/modules/desktop_capture/screen_capturer_linux.cc deleted file mode 100644 index cf8a9dd0e0..0000000000 --- a/modules/desktop_capture/screen_capturer_linux.cc +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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/desktop_capture_options.h" -#include "modules/desktop_capture/desktop_capturer.h" - -#if defined(WEBRTC_USE_PIPEWIRE) -#include "modules/desktop_capture/linux/screen_capturer_pipewire.h" -#endif // defined(WEBRTC_USE_PIPEWIRE) - -#if defined(USE_X11) -#include "modules/desktop_capture/linux/screen_capturer_x11.h" -#endif // defined(USE_X11) - -namespace webrtc { - -// static -std::unique_ptr DesktopCapturer::CreateRawScreenCapturer( - const DesktopCaptureOptions& options) { -#if defined(WEBRTC_USE_PIPEWIRE) - if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { - return ScreenCapturerPipeWire::CreateRawScreenCapturer(options); - } -#endif // defined(WEBRTC_USE_PIPEWIRE) - -#if defined(USE_X11) - return ScreenCapturerX11::CreateRawScreenCapturer(options); -#endif // defined(USE_X11) - - return nullptr; -} - -} // namespace webrtc diff --git a/modules/desktop_capture/linux/screen_capturer_x11.cc b/modules/desktop_capture/screen_capturer_x11.cc similarity index 71% rename from modules/desktop_capture/linux/screen_capturer_x11.cc rename to modules/desktop_capture/screen_capturer_x11.cc index 9d6a085b65..e95fccc208 100644 --- a/modules/desktop_capture/linux/screen_capturer_x11.cc +++ b/modules/desktop_capture/screen_capturer_x11.cc @@ -8,38 +8,124 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/desktop_capture/linux/screen_capturer_x11.h" - #include +#include +#include +#include + #include #include #include #include -#include -#include -#include - #include "modules/desktop_capture/desktop_capture_options.h" #include "modules/desktop_capture/desktop_capturer.h" #include "modules/desktop_capture/desktop_frame.h" -#include "modules/desktop_capture/linux/x_server_pixel_buffer.h" #include "modules/desktop_capture/screen_capture_frame_queue.h" #include "modules/desktop_capture/screen_capturer_helper.h" #include "modules/desktop_capture/shared_desktop_frame.h" +#include "modules/desktop_capture/x11/x_server_pixel_buffer.h" #include "rtc_base/checks.h" +#include "rtc_base/constructormagic.h" #include "rtc_base/logging.h" #include "rtc_base/timeutils.h" #include "rtc_base/trace_event.h" namespace webrtc { +namespace { -ScreenCapturerX11::ScreenCapturerX11() { +// A class to perform video frame capturing for Linux. +// +// If XDamage is used, this class sets DesktopFrame::updated_region() according +// to the areas reported by XDamage. Otherwise this class does not detect +// DesktopFrame::updated_region(), the field is always set to the entire frame +// rectangle. ScreenCapturerDifferWrapper should be used if that functionality +// is necessary. +class ScreenCapturerLinux : public DesktopCapturer, + public SharedXDisplay::XEventHandler { + public: + ScreenCapturerLinux(); + ~ScreenCapturerLinux() override; + + // TODO(ajwong): Do we really want this to be synchronous? + bool Init(const DesktopCaptureOptions& options); + + // DesktopCapturer interface. + void Start(Callback* delegate) override; + void CaptureFrame() override; + bool GetSourceList(SourceList* sources) override; + bool SelectSource(SourceId id) override; + + private: + Display* display() { return options_.x_display()->display(); } + + // SharedXDisplay::XEventHandler interface. + bool HandleXEvent(const XEvent& event) override; + + void InitXDamage(); + + // Capture screen pixels to the current buffer in the queue. In the DAMAGE + // case, the ScreenCapturerHelper already holds the list of invalid rectangles + // from HandleXEvent(). In the non-DAMAGE case, this captures the + // whole screen, then calculates some invalid rectangles that include any + // differences between this and the previous capture. + std::unique_ptr CaptureScreen(); + + // Called when the screen configuration is changed. + void ScreenConfigurationChanged(); + + // Synchronize the current buffer with |last_buffer_|, by copying pixels from + // the area of |last_invalid_rects|. + // Note this only works on the assumption that kNumBuffers == 2, as + // |last_invalid_rects| holds the differences from the previous buffer and + // the one prior to that (which will then be the current buffer). + void SynchronizeFrame(); + + void DeinitXlib(); + + DesktopCaptureOptions options_; + + Callback* callback_ = nullptr; + + // X11 graphics context. + GC gc_ = nullptr; + Window root_window_ = BadValue; + + // XFixes. + bool has_xfixes_ = false; + int xfixes_event_base_ = -1; + int xfixes_error_base_ = -1; + + // XDamage information. + bool use_damage_ = false; + Damage damage_handle_ = 0; + int damage_event_base_ = -1; + int damage_error_base_ = -1; + XserverRegion damage_region_ = 0; + + // Access to the X Server's pixel buffer. + XServerPixelBuffer x_server_pixel_buffer_; + + // A thread-safe list of invalid rectangles, and the size of the most + // recently captured screen. + ScreenCapturerHelper helper_; + + // Queue of the frames buffers. + ScreenCaptureFrameQueue queue_; + + // Invalid region from the previous capture. This is used to synchronize the + // current with the last buffer used. + DesktopRegion last_invalid_region_; + + RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux); +}; + +ScreenCapturerLinux::ScreenCapturerLinux() { helper_.SetLogGridSize(4); } -ScreenCapturerX11::~ScreenCapturerX11() { +ScreenCapturerLinux::~ScreenCapturerLinux() { options_.x_display()->RemoveEventHandler(ConfigureNotify, this); if (use_damage_) { options_.x_display()->RemoveEventHandler(damage_event_base_ + XDamageNotify, @@ -48,8 +134,8 @@ ScreenCapturerX11::~ScreenCapturerX11() { DeinitXlib(); } -bool ScreenCapturerX11::Init(const DesktopCaptureOptions& options) { - TRACE_EVENT0("webrtc", "ScreenCapturerX11::Init"); +bool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) { + TRACE_EVENT0("webrtc", "ScreenCapturerLinux::Init"); options_ = options; root_window_ = RootWindow(display(), DefaultScreen(display())); @@ -92,7 +178,7 @@ bool ScreenCapturerX11::Init(const DesktopCaptureOptions& options) { return true; } -void ScreenCapturerX11::InitXDamage() { +void ScreenCapturerLinux::InitXDamage() { // Our use of XDamage requires XFixes. if (!has_xfixes_) { return; @@ -133,15 +219,15 @@ void ScreenCapturerX11::InitXDamage() { RTC_LOG(LS_INFO) << "Using XDamage extension."; } -void ScreenCapturerX11::Start(Callback* callback) { +void ScreenCapturerLinux::Start(Callback* callback) { RTC_DCHECK(!callback_); RTC_DCHECK(callback); callback_ = callback; } -void ScreenCapturerX11::CaptureFrame() { - TRACE_EVENT0("webrtc", "ScreenCapturerX11::CaptureFrame"); +void ScreenCapturerLinux::CaptureFrame() { + TRACE_EVENT0("webrtc", "ScreenCapturerLinux::CaptureFrame"); int64_t capture_start_time_nanos = rtc::TimeNanos(); queue_.MoveToNextFrame(); @@ -182,19 +268,19 @@ void ScreenCapturerX11::CaptureFrame() { callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); } -bool ScreenCapturerX11::GetSourceList(SourceList* sources) { +bool ScreenCapturerLinux::GetSourceList(SourceList* sources) { RTC_DCHECK(sources->size() == 0); // TODO(jiayl): implement screen enumeration. sources->push_back({0}); return true; } -bool ScreenCapturerX11::SelectSource(SourceId id) { +bool ScreenCapturerLinux::SelectSource(SourceId id) { // TODO(jiayl): implement screen selection. return true; } -bool ScreenCapturerX11::HandleXEvent(const XEvent& event) { +bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) { if (use_damage_ && (event.type == damage_event_base_ + XDamageNotify)) { const XDamageNotifyEvent* damage_event = reinterpret_cast(&event); @@ -209,7 +295,7 @@ bool ScreenCapturerX11::HandleXEvent(const XEvent& event) { return false; } -std::unique_ptr ScreenCapturerX11::CaptureScreen() { +std::unique_ptr ScreenCapturerLinux::CaptureScreen() { std::unique_ptr frame = queue_.current_frame()->Share(); RTC_DCHECK(x_server_pixel_buffer_.window_size().equals(frame->size())); @@ -267,8 +353,8 @@ std::unique_ptr ScreenCapturerX11::CaptureScreen() { return std::move(frame); } -void ScreenCapturerX11::ScreenConfigurationChanged() { - TRACE_EVENT0("webrtc", "ScreenCapturerX11::ScreenConfigurationChanged"); +void ScreenCapturerLinux::ScreenConfigurationChanged() { + TRACE_EVENT0("webrtc", "ScreenCapturerLinux::ScreenConfigurationChanged"); // Make sure the frame buffers will be reallocated. queue_.Reset(); @@ -279,7 +365,7 @@ void ScreenCapturerX11::ScreenConfigurationChanged() { } } -void ScreenCapturerX11::SynchronizeFrame() { +void ScreenCapturerLinux::SynchronizeFrame() { // Synchronize the current buffer with the previous one since we do not // capture the entire desktop. Note that encoder may be reading from the // previous buffer at this time so thread access complaints are false @@ -299,7 +385,7 @@ void ScreenCapturerX11::SynchronizeFrame() { } } -void ScreenCapturerX11::DeinitXlib() { +void ScreenCapturerLinux::DeinitXlib() { if (gc_) { XFreeGC(display(), gc_); gc_ = nullptr; @@ -320,13 +406,15 @@ void ScreenCapturerX11::DeinitXlib() { } } +} // namespace + // static -std::unique_ptr ScreenCapturerX11::CreateRawScreenCapturer( +std::unique_ptr DesktopCapturer::CreateRawScreenCapturer( const DesktopCaptureOptions& options) { if (!options.x_display()) return nullptr; - std::unique_ptr capturer(new ScreenCapturerX11()); + std::unique_ptr capturer(new ScreenCapturerLinux()); if (!capturer.get()->Init(options)) { return nullptr; } diff --git a/modules/desktop_capture/screen_drawer_linux.cc b/modules/desktop_capture/screen_drawer_linux.cc index 2ab5e74891..39ceca7dc6 100644 --- a/modules/desktop_capture/screen_drawer_linux.cc +++ b/modules/desktop_capture/screen_drawer_linux.cc @@ -14,9 +14,9 @@ #include #include "absl/memory/memory.h" -#include "modules/desktop_capture/linux/shared_x_display.h" #include "modules/desktop_capture/screen_drawer.h" #include "modules/desktop_capture/screen_drawer_lock_posix.h" +#include "modules/desktop_capture/x11/shared_x_display.h" #include "rtc_base/checks.h" #include "system_wrappers/include/sleep.h" diff --git a/modules/desktop_capture/window_capturer_linux.cc b/modules/desktop_capture/window_capturer_linux.cc deleted file mode 100644 index 82359e50c2..0000000000 --- a/modules/desktop_capture/window_capturer_linux.cc +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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/desktop_capture_options.h" -#include "modules/desktop_capture/desktop_capturer.h" - -#if defined(WEBRTC_USE_PIPEWIRE) -#include "modules/desktop_capture/linux/window_capturer_pipewire.h" -#endif // defined(WEBRTC_USE_PIPEWIRE) - -#if defined(USE_X11) -#include "modules/desktop_capture/linux/window_capturer_x11.h" -#endif // defined(USE_X11) - -namespace webrtc { - -// static -std::unique_ptr DesktopCapturer::CreateRawWindowCapturer( - const DesktopCaptureOptions& options) { -#if defined(WEBRTC_USE_PIPEWIRE) - if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { - return WindowCapturerPipeWire::CreateRawWindowCapturer(options); - } -#endif // defined(WEBRTC_USE_PIPEWIRE) - -#if defined(USE_X11) - return WindowCapturerX11::CreateRawWindowCapturer(options); -#endif // defined(USE_X11) - - return nullptr; -} - -} // namespace webrtc diff --git a/modules/desktop_capture/linux/window_capturer_x11.cc b/modules/desktop_capture/window_capturer_x11.cc similarity index 74% rename from modules/desktop_capture/linux/window_capturer_x11.cc rename to modules/desktop_capture/window_capturer_x11.cc index 4ef7c5cb38..c4ca3ae5e8 100644 --- a/modules/desktop_capture/linux/window_capturer_x11.cc +++ b/modules/desktop_capture/window_capturer_x11.cc @@ -8,28 +8,70 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/desktop_capture/linux/window_capturer_x11.h" +#include #include #include #include -#include -#include #include +#include "modules/desktop_capture/desktop_capture_options.h" +#include "modules/desktop_capture/desktop_capturer.h" #include "modules/desktop_capture/desktop_frame.h" -#include "modules/desktop_capture/linux/shared_x_display.h" -#include "modules/desktop_capture/linux/window_finder_x11.h" -#include "modules/desktop_capture/linux/window_list_utils.h" +#include "modules/desktop_capture/window_finder_x11.h" +#include "modules/desktop_capture/x11/shared_x_display.h" +#include "modules/desktop_capture/x11/window_list_utils.h" +#include "modules/desktop_capture/x11/x_atom_cache.h" +#include "modules/desktop_capture/x11/x_server_pixel_buffer.h" #include "rtc_base/checks.h" +#include "rtc_base/constructormagic.h" #include "rtc_base/logging.h" #include "rtc_base/scoped_ref_ptr.h" #include "rtc_base/trace_event.h" namespace webrtc { -WindowCapturerX11::WindowCapturerX11(const DesktopCaptureOptions& options) +namespace { + +class WindowCapturerLinux : public DesktopCapturer, + public SharedXDisplay::XEventHandler { + public: + WindowCapturerLinux(const DesktopCaptureOptions& options); + ~WindowCapturerLinux() override; + + // DesktopCapturer interface. + void Start(Callback* callback) override; + void CaptureFrame() override; + bool GetSourceList(SourceList* sources) override; + bool SelectSource(SourceId id) override; + bool FocusOnSelectedSource() override; + bool IsOccluded(const DesktopVector& pos) override; + + // SharedXDisplay::XEventHandler interface. + bool HandleXEvent(const XEvent& event) override; + + private: + Display* display() { return x_display_->display(); } + + // Returns window title for the specified X |window|. + bool GetWindowTitle(::Window window, std::string* title); + + Callback* callback_ = nullptr; + + rtc::scoped_refptr x_display_; + + bool has_composite_extension_ = false; + + ::Window selected_window_ = 0; + XServerPixelBuffer x_server_pixel_buffer_; + XAtomCache atom_cache_; + WindowFinderX11 window_finder_; + + RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux); +}; + +WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options) : x_display_(options.x_display()), atom_cache_(display()), window_finder_(&atom_cache_) { @@ -46,11 +88,11 @@ WindowCapturerX11::WindowCapturerX11(const DesktopCaptureOptions& options) x_display_->AddEventHandler(ConfigureNotify, this); } -WindowCapturerX11::~WindowCapturerX11() { +WindowCapturerLinux::~WindowCapturerLinux() { x_display_->RemoveEventHandler(ConfigureNotify, this); } -bool WindowCapturerX11::GetSourceList(SourceList* sources) { +bool WindowCapturerLinux::GetSourceList(SourceList* sources) { return GetWindowList(&atom_cache_, [this, sources](::Window window) { Source w; w.id = window; @@ -61,7 +103,7 @@ bool WindowCapturerX11::GetSourceList(SourceList* sources) { }); } -bool WindowCapturerX11::SelectSource(SourceId id) { +bool WindowCapturerLinux::SelectSource(SourceId id) { if (!x_server_pixel_buffer_.Init(display(), id)) return false; @@ -82,7 +124,7 @@ bool WindowCapturerX11::SelectSource(SourceId id) { return true; } -bool WindowCapturerX11::FocusOnSelectedSource() { +bool WindowCapturerLinux::FocusOnSelectedSource() { if (!selected_window_) return false; @@ -128,15 +170,15 @@ bool WindowCapturerX11::FocusOnSelectedSource() { return true; } -void WindowCapturerX11::Start(Callback* callback) { +void WindowCapturerLinux::Start(Callback* callback) { RTC_DCHECK(!callback_); RTC_DCHECK(callback); callback_ = callback; } -void WindowCapturerX11::CaptureFrame() { - TRACE_EVENT0("webrtc", "WindowCapturerX11::CaptureFrame"); +void WindowCapturerLinux::CaptureFrame() { + TRACE_EVENT0("webrtc", "WindowCapturerLinux::CaptureFrame"); if (!x_server_pixel_buffer_.IsWindowValid()) { RTC_LOG(LS_ERROR) << "The window is no longer valid."; @@ -181,12 +223,12 @@ void WindowCapturerX11::CaptureFrame() { callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); } -bool WindowCapturerX11::IsOccluded(const DesktopVector& pos) { +bool WindowCapturerLinux::IsOccluded(const DesktopVector& pos) { return window_finder_.GetWindowUnderPoint(pos) != static_cast(selected_window_); } -bool WindowCapturerX11::HandleXEvent(const XEvent& event) { +bool WindowCapturerLinux::HandleXEvent(const XEvent& event) { if (event.type == ConfigureNotify) { XConfigureEvent xce = event.xconfigure; if (xce.window == selected_window_) { @@ -204,7 +246,7 @@ bool WindowCapturerX11::HandleXEvent(const XEvent& event) { return false; } -bool WindowCapturerX11::GetWindowTitle(::Window window, std::string* title) { +bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) { int status; bool result = false; XTextProperty window_name; @@ -233,12 +275,14 @@ bool WindowCapturerX11::GetWindowTitle(::Window window, std::string* title) { return result; } +} // namespace + // static -std::unique_ptr WindowCapturerX11::CreateRawWindowCapturer( +std::unique_ptr DesktopCapturer::CreateRawWindowCapturer( const DesktopCaptureOptions& options) { if (!options.x_display()) return nullptr; - return std::unique_ptr(new WindowCapturerX11(options)); + return std::unique_ptr(new WindowCapturerLinux(options)); } } // namespace webrtc diff --git a/modules/desktop_capture/window_finder_unittest.cc b/modules/desktop_capture/window_finder_unittest.cc index df9067ef2c..88327aaac5 100644 --- a/modules/desktop_capture/window_finder_unittest.cc +++ b/modules/desktop_capture/window_finder_unittest.cc @@ -21,8 +21,8 @@ #if defined(USE_X11) #include "absl/memory/memory.h" -#include "modules/desktop_capture/linux/shared_x_display.h" -#include "modules/desktop_capture/linux/x_atom_cache.h" +#include "modules/desktop_capture/x11/shared_x_display.h" +#include "modules/desktop_capture/x11/x_atom_cache.h" #endif #if defined(WEBRTC_WIN) diff --git a/modules/desktop_capture/linux/window_finder_x11.cc b/modules/desktop_capture/window_finder_x11.cc similarity index 89% rename from modules/desktop_capture/linux/window_finder_x11.cc rename to modules/desktop_capture/window_finder_x11.cc index 46fadc2c6f..03694326d2 100644 --- a/modules/desktop_capture/linux/window_finder_x11.cc +++ b/modules/desktop_capture/window_finder_x11.cc @@ -8,12 +8,10 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/desktop_capture/linux/window_finder_x11.h" - -#include +#include "modules/desktop_capture/window_finder_x11.h" #include "absl/memory/memory.h" -#include "modules/desktop_capture/linux/window_list_utils.h" +#include "modules/desktop_capture/x11/window_list_utils.h" #include "rtc_base/checks.h" namespace webrtc { diff --git a/modules/desktop_capture/linux/window_finder_x11.h b/modules/desktop_capture/window_finder_x11.h similarity index 82% rename from modules/desktop_capture/linux/window_finder_x11.h rename to modules/desktop_capture/window_finder_x11.h index d0bba8697b..38c30c4670 100644 --- a/modules/desktop_capture/linux/window_finder_x11.h +++ b/modules/desktop_capture/window_finder_x11.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_FINDER_X11_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_FINDER_X11_H_ +#ifndef MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_X11_H_ +#define MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_X11_H_ #include "modules/desktop_capture/window_finder.h" @@ -32,4 +32,4 @@ class WindowFinderX11 final : public WindowFinder { } // namespace webrtc -#endif // MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_FINDER_X11_H_ +#endif // MODULES_DESKTOP_CAPTURE_WINDOW_FINDER_X11_H_ diff --git a/modules/desktop_capture/linux/shared_x_display.cc b/modules/desktop_capture/x11/shared_x_display.cc similarity index 97% rename from modules/desktop_capture/linux/shared_x_display.cc rename to modules/desktop_capture/x11/shared_x_display.cc index c475db6e78..db6a64b81d 100644 --- a/modules/desktop_capture/linux/shared_x_display.cc +++ b/modules/desktop_capture/x11/shared_x_display.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/desktop_capture/linux/shared_x_display.h" +#include "modules/desktop_capture/x11/shared_x_display.h" #include diff --git a/modules/desktop_capture/linux/shared_x_display.h b/modules/desktop_capture/x11/shared_x_display.h similarity index 92% rename from modules/desktop_capture/linux/shared_x_display.h rename to modules/desktop_capture/x11/shared_x_display.h index a14f41fab8..4d93b3b175 100644 --- a/modules/desktop_capture/linux/shared_x_display.h +++ b/modules/desktop_capture/x11/shared_x_display.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_SHARED_X_DISPLAY_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_SHARED_X_DISPLAY_H_ +#ifndef MODULES_DESKTOP_CAPTURE_X11_SHARED_X_DISPLAY_H_ +#define MODULES_DESKTOP_CAPTURE_X11_SHARED_X_DISPLAY_H_ #include #include @@ -78,4 +78,4 @@ class SharedXDisplay : public rtc::RefCountedBase { } // namespace webrtc -#endif // MODULES_DESKTOP_CAPTURE_LINUX_SHARED_X_DISPLAY_H_ +#endif // MODULES_DESKTOP_CAPTURE_X11_SHARED_X_DISPLAY_H_ diff --git a/modules/desktop_capture/linux/window_list_utils.cc b/modules/desktop_capture/x11/window_list_utils.cc similarity index 98% rename from modules/desktop_capture/linux/window_list_utils.cc rename to modules/desktop_capture/x11/window_list_utils.cc index fd8f5f72cd..fe070d8878 100644 --- a/modules/desktop_capture/linux/window_list_utils.cc +++ b/modules/desktop_capture/x11/window_list_utils.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/desktop_capture/linux/window_list_utils.h" +#include "modules/desktop_capture/x11/window_list_utils.h" #include #include @@ -17,7 +17,7 @@ #include -#include "modules/desktop_capture/linux/x_error_trap.h" +#include "modules/desktop_capture/x11/x_error_trap.h" #include "rtc_base/checks.h" #include "rtc_base/constructormagic.h" #include "rtc_base/logging.h" diff --git a/modules/desktop_capture/linux/window_list_utils.h b/modules/desktop_capture/x11/window_list_utils.h similarity index 89% rename from modules/desktop_capture/linux/window_list_utils.h rename to modules/desktop_capture/x11/window_list_utils.h index 2057c99b84..72d2a70d21 100644 --- a/modules/desktop_capture/linux/window_list_utils.h +++ b/modules/desktop_capture/x11/window_list_utils.h @@ -8,13 +8,13 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_LIST_UTILS_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_LIST_UTILS_H_ +#ifndef MODULES_DESKTOP_CAPTURE_X11_WINDOW_LIST_UTILS_H_ +#define MODULES_DESKTOP_CAPTURE_X11_WINDOW_LIST_UTILS_H_ #include #include "modules/desktop_capture/desktop_geometry.h" -#include "modules/desktop_capture/linux/x_atom_cache.h" +#include "modules/desktop_capture/x11/x_atom_cache.h" #include "rtc_base/function_view.h" namespace webrtc { @@ -51,4 +51,4 @@ DesktopRect DesktopRectFromXAttributes(const T& attributes) { } // namespace webrtc -#endif // MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_LIST_UTILS_H_ +#endif // MODULES_DESKTOP_CAPTURE_X11_WINDOW_LIST_UTILS_H_ diff --git a/modules/desktop_capture/linux/x_atom_cache.cc b/modules/desktop_capture/x11/x_atom_cache.cc similarity index 95% rename from modules/desktop_capture/linux/x_atom_cache.cc rename to modules/desktop_capture/x11/x_atom_cache.cc index 832e6166cb..fa3a1fdebd 100644 --- a/modules/desktop_capture/linux/x_atom_cache.cc +++ b/modules/desktop_capture/x11/x_atom_cache.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/desktop_capture/linux/x_atom_cache.h" +#include "modules/desktop_capture/x11/x_atom_cache.h" #include "rtc_base/checks.h" diff --git a/modules/desktop_capture/linux/x_atom_cache.h b/modules/desktop_capture/x11/x_atom_cache.h similarity index 86% rename from modules/desktop_capture/linux/x_atom_cache.h rename to modules/desktop_capture/x11/x_atom_cache.h index 71789f0512..5246c2bb5c 100644 --- a/modules/desktop_capture/linux/x_atom_cache.h +++ b/modules/desktop_capture/x11/x_atom_cache.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_X_ATOM_CACHE_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_X_ATOM_CACHE_H_ +#ifndef MODULES_DESKTOP_CAPTURE_X11_X_ATOM_CACHE_H_ +#define MODULES_DESKTOP_CAPTURE_X11_X_ATOM_CACHE_H_ #include #include @@ -40,4 +40,4 @@ class XAtomCache final { } // namespace webrtc -#endif // MODULES_DESKTOP_CAPTURE_LINUX_X_ATOM_CACHE_H_ +#endif // MODULES_DESKTOP_CAPTURE_X11_X_ATOM_CACHE_H_ diff --git a/modules/desktop_capture/linux/x_error_trap.cc b/modules/desktop_capture/x11/x_error_trap.cc similarity index 97% rename from modules/desktop_capture/linux/x_error_trap.cc rename to modules/desktop_capture/x11/x_error_trap.cc index bb5ca4512d..6559c3dbe9 100644 --- a/modules/desktop_capture/linux/x_error_trap.cc +++ b/modules/desktop_capture/x11/x_error_trap.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/desktop_capture/linux/x_error_trap.h" +#include "modules/desktop_capture/x11/x_error_trap.h" #include diff --git a/modules/desktop_capture/linux/x_error_trap.h b/modules/desktop_capture/x11/x_error_trap.h similarity index 85% rename from modules/desktop_capture/linux/x_error_trap.h rename to modules/desktop_capture/x11/x_error_trap.h index a9d059a0bc..ea9ebf670b 100644 --- a/modules/desktop_capture/linux/x_error_trap.h +++ b/modules/desktop_capture/x11/x_error_trap.h @@ -8,8 +8,8 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_X_ERROR_TRAP_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_X_ERROR_TRAP_H_ +#ifndef MODULES_DESKTOP_CAPTURE_X11_X_ERROR_TRAP_H_ +#define MODULES_DESKTOP_CAPTURE_X11_X_ERROR_TRAP_H_ #include @@ -36,4 +36,4 @@ class XErrorTrap { } // namespace webrtc -#endif // MODULES_DESKTOP_CAPTURE_LINUX_X_ERROR_TRAP_H_ +#endif // MODULES_DESKTOP_CAPTURE_X11_X_ERROR_TRAP_H_ diff --git a/modules/desktop_capture/linux/x_server_pixel_buffer.cc b/modules/desktop_capture/x11/x_server_pixel_buffer.cc similarity index 98% rename from modules/desktop_capture/linux/x_server_pixel_buffer.cc rename to modules/desktop_capture/x11/x_server_pixel_buffer.cc index 19dd1398c9..e327d3fc7d 100644 --- a/modules/desktop_capture/linux/x_server_pixel_buffer.cc +++ b/modules/desktop_capture/x11/x_server_pixel_buffer.cc @@ -8,14 +8,14 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "modules/desktop_capture/linux/x_server_pixel_buffer.h" +#include "modules/desktop_capture/x11/x_server_pixel_buffer.h" #include #include #include "modules/desktop_capture/desktop_frame.h" -#include "modules/desktop_capture/linux/window_list_utils.h" -#include "modules/desktop_capture/linux/x_error_trap.h" +#include "modules/desktop_capture/x11/window_list_utils.h" +#include "modules/desktop_capture/x11/x_error_trap.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h" diff --git a/modules/desktop_capture/linux/x_server_pixel_buffer.h b/modules/desktop_capture/x11/x_server_pixel_buffer.h similarity index 93% rename from modules/desktop_capture/linux/x_server_pixel_buffer.h rename to modules/desktop_capture/x11/x_server_pixel_buffer.h index a9398dac99..7e20945f3d 100644 --- a/modules/desktop_capture/linux/x_server_pixel_buffer.h +++ b/modules/desktop_capture/x11/x_server_pixel_buffer.h @@ -10,15 +10,15 @@ // Don't include this file in any .h files because it pulls in some X headers. -#ifndef MODULES_DESKTOP_CAPTURE_LINUX_X_SERVER_PIXEL_BUFFER_H_ -#define MODULES_DESKTOP_CAPTURE_LINUX_X_SERVER_PIXEL_BUFFER_H_ - -#include -#include +#ifndef MODULES_DESKTOP_CAPTURE_X11_X_SERVER_PIXEL_BUFFER_H_ +#define MODULES_DESKTOP_CAPTURE_X11_X_SERVER_PIXEL_BUFFER_H_ #include "modules/desktop_capture/desktop_geometry.h" #include "rtc_base/constructormagic.h" +#include +#include + namespace webrtc { class DesktopFrame; @@ -81,4 +81,4 @@ class XServerPixelBuffer { } // namespace webrtc -#endif // MODULES_DESKTOP_CAPTURE_LINUX_X_SERVER_PIXEL_BUFFER_H_ +#endif // MODULES_DESKTOP_CAPTURE_X11_X_SERVER_PIXEL_BUFFER_H_ diff --git a/webrtc.gni b/webrtc.gni index f09ed643b1..bba336912d 100644 --- a/webrtc.gni +++ b/webrtc.gni @@ -9,7 +9,6 @@ import("//build/config/arm.gni") import("//build/config/features.gni") import("//build/config/mips.gni") import("//build/config/sanitizers/sanitizers.gni") -import("//build/config/sysroot.gni") import("//build/config/ui.gni") import("//build_overrides/build.gni") @@ -108,9 +107,6 @@ declare_args() { # Set this to false to skip building code that requires X11. rtc_use_x11 = use_x11 - # Set this to use PipeWire on the Wayland display server. - rtc_use_pipewire = false - # Enable to use the Mozilla internal settings. build_with_mozilla = false @@ -233,8 +229,7 @@ rtc_libvpx_dir = "//third_party/libvpx" rtc_opus_dir = "//third_party/opus" # Desktop capturer is supported only on Windows, OSX and Linux. -rtc_desktop_capture_supported = - is_win || is_mac || (is_linux && (rtc_use_x11 || rtc_use_pipewire)) +rtc_desktop_capture_supported = is_win || is_mac || (is_linux && rtc_use_x11) ############################################################################### # Templates