diff --git a/firefox-pipewire.patch b/firefox-pipewire.patch index 6ed5801..f4d6c55 100644 --- a/firefox-pipewire.patch +++ b/firefox-pipewire.patch @@ -1,8 +1,11 @@ -PipeWire WebRTC patch from https://github.com/xhorak/firefox-devedition-flatpak -https://bugzilla.mozilla.org/show_bug.cgi?id=1496359 +>From 4709953855a4243ce2d2ec45f63059baf604a499 Mon Sep 17 00:00:00 2001 +From: Jan Grulich +Date: Thu, 18 Oct 2018 10:25:56 +0200 +Subject: PW support + diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild -index 7f17843a37bd..1f4d711e5d39 100644 +index 60967bd51..11eb07a65 100644 --- a/config/system-headers.mozbuild +++ b/config/system-headers.mozbuild @@ -314,6 +314,7 @@ system_headers = [ @@ -22,7 +25,7 @@ index 7f17843a37bd..1f4d711e5d39 100644 'pk11func.h', 'pk11pqg.h', diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn b/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn -index ed12a1521eb0..a9e700ccd3e0 100644 +index ed12a1521..a9e700ccd 100644 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn @@ -213,7 +213,6 @@ rtc_static_library("desktop_capture") { @@ -35,7 +38,7 @@ index ed12a1521eb0..a9e700ccd3e0 100644 "x11/shared_x_util.cc", diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_linux.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_linux.cc new file mode 100644 -index 000000000000..4ac35aa8496b +index 000000000..4ac35aa84 --- /dev/null +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_linux.cc @@ -0,0 +1,55 @@ @@ -95,7 +98,7 @@ index 000000000000..4ac35aa8496b + +} // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_null.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_null.cc -index 5a0b1a28f058..84a7e5951032 100644 +index 5a0b1a28f..84a7e5951 100644 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_null.cc +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_null.cc @@ -7,8 +7,8 @@ @@ -105,12 +108,12 @@ index 5a0b1a28f058..84a7e5951032 100644 -#include "webrtc/modules/desktop_capture/window_capturer.h" #include "webrtc/modules/desktop_capture/app_capturer.h" +#include "webrtc/modules/desktop_capture/desktop_capturer.h" - + #include - + @@ -29,9 +29,11 @@ public: virtual bool BringAppToFront() override; - + // DesktopCapturer interface. - virtual void Start(Callback* callback) override; - virtual void Stop() override; @@ -120,13 +123,13 @@ index 5a0b1a28f058..84a7e5951032 100644 + void CaptureFrame() override; + bool GetSourceList(SourceList* sources) override; + bool SelectSource(SourceId id) override; - + private: Callback* callback_; @@ -61,7 +63,16 @@ bool AppCapturerNull::BringAppToFront() { return false; } - + -// DesktopCapturer interface. +bool AppCapturerNull::GetSourceList(SourceList* sources) { + // Not implemented yet. @@ -144,7 +147,7 @@ index 5a0b1a28f058..84a7e5951032 100644 @@ -73,16 +84,19 @@ void AppCapturerNull::Stop() { callback_ = NULL; } - + -void AppCapturerNull::Capture(const DesktopRegion& region) { - // Not implemented yet: See Bug 1036653 - callback_->OnCaptureCompleted(NULL); @@ -152,9 +155,9 @@ index 5a0b1a28f058..84a7e5951032 100644 + // Not implemented yet. + callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); } - + } // namespace - + +#if not defined(USE_PIPEWIRE) // static -AppCapturer* AppCapturer::Create(const DesktopCaptureOptions& options) { @@ -164,16 +167,16 @@ index 5a0b1a28f058..84a7e5951032 100644 + return std::unique_ptr(new AppCapturerNull()); } +#endif // not defined(USE_PIPEWIRE) - + } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc -index 8215823672b6..5c20ed0a517b 100755 +index 821582367..5c20ed0a5 100755 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc @@ -53,10 +53,13 @@ protected: std::unique_ptr frame_; }; - + -class AppCapturerLinux : public AppCapturer { +class AppCapturerX11 : public AppCapturer { public: @@ -184,12 +187,12 @@ index 8215823672b6..5c20ed0a517b 100755 + + static AppCapturer* Create(const DesktopCaptureOptions& options); + static std::unique_ptr CreateRawAppCapturer(const DesktopCaptureOptions& options); - + // AppCapturer interface. virtual bool GetAppList(AppList* apps) override; @@ -91,10 +94,9 @@ private: Region rgn_background_; - + rtc::scoped_refptr x_display_; - RTC_DISALLOW_COPY_AND_ASSIGN(AppCapturerLinux); + RTC_DISALLOW_COPY_AND_ASSIGN(AppCapturerX11); @@ -203,7 +206,7 @@ index 8215823672b6..5c20ed0a517b 100755 @@ -103,7 +105,7 @@ AppCapturerLinux::AppCapturerLinux(const DesktopCaptureOptions& options) rgn_background_ = XCreateRegion(); } - + -AppCapturerLinux::~AppCapturerLinux() { +AppCapturerX11::~AppCapturerX11() { if (rgn_mask_) { @@ -211,7 +214,7 @@ index 8215823672b6..5c20ed0a517b 100755 } @@ -116,32 +118,32 @@ AppCapturerLinux::~AppCapturerLinux() { } - + // AppCapturer interface. -bool AppCapturerLinux::GetAppList(AppList* apps) { +bool AppCapturerX11::GetAppList(AppList* apps) { @@ -228,163 +231,75 @@ index 8215823672b6..5c20ed0a517b 100755 // Not implemented yet: See Bug 1036653 return true; } - + // DesktopCapturer interface. -void AppCapturerLinux::Start(Callback* callback) { +void AppCapturerX11::Start(Callback* callback) { assert(!callback_); assert(callback); - + callback_ = callback; } - + -void AppCapturerLinux::Stop() { +void AppCapturerX11::Stop() { callback_ = NULL; } - + -void AppCapturerLinux::CaptureFrame() { +void AppCapturerX11::CaptureFrame() { XErrorTrap error_trap(GetDisplay()); - + //Capture screen >> set root window as capture window @@ -169,7 +171,7 @@ void AppCapturerLinux::CaptureFrame() { } } - + -void AppCapturerLinux::FillDesktopFrameRegionWithColor(DesktopFrame* pDesktopFrame, Region rgn, uint32_t color) { +void AppCapturerX11::FillDesktopFrameRegionWithColor(DesktopFrame* pDesktopFrame, Region rgn, uint32_t color) { XErrorTrap error_trap(GetDisplay()); - + if (!pDesktopFrame) { @@ -192,7 +194,7 @@ void AppCapturerLinux::FillDesktopFrameRegionWithColor(DesktopFrame* pDesktopFra } } - + -bool AppCapturerLinux::UpdateRegions() { +bool AppCapturerX11::UpdateRegions() { XErrorTrap error_trap(GetDisplay()); - + XSubtractRegion(rgn_visual_, rgn_visual_, rgn_visual_); @@ -272,18 +274,18 @@ bool AppCapturerLinux::UpdateRegions() { } // namespace - + // static -AppCapturer* AppCapturer::Create(const DesktopCaptureOptions& options) { - return new AppCapturerLinux(options); +AppCapturer* AppCapturerX11::Create(const DesktopCaptureOptions& options) { + return new AppCapturerX11(options); } - + // static -std::unique_ptr DesktopCapturer::CreateRawAppCapturer( +std::unique_ptr AppCapturerX11::CreateRawAppCapturer( const DesktopCaptureOptions& options) { - + if (!options.x_display()) return nullptr; - + - std::unique_ptr capturer(new AppCapturerLinux(options)); + std::unique_ptr capturer(new AppCapturerX11(options)); - + return std::unique_ptr(std::move(capturer)); } -diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build -index d7909d983053..b50b005c300e 100644 ---- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build -+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build -@@ -166,10 +166,6 @@ if CONFIG["OS_TARGET"] == "Linux": - ] - - UNIFIED_SOURCES += [ -- "/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc", -- "/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc", -- "/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.cc", -- "/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc", - "/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.cc", - "/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/shared_x_display.cc", - "/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/shared_x_util.cc", -@@ -177,6 +173,35 @@ if CONFIG["OS_TARGET"] == "Linux": - "/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.cc" - ] - -+# Common stuff between Pipewire and X11 -+if CONFIG["OS_TARGET"] == "Linux": -+ -+ UNIFIED_SOURCES += [ -+ "/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_linux.cc", -+ "/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc", -+ "/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc", -+ "/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc" -+ ] -+ -+# Pipewire -+if CONFIG["OS_TARGET"] == "Linux": -+ -+ DEFINES["USE_PIPEWIRE"] = "1" -+ -+ OS_LIBS += [ -+ "rt", -+ "pipewire-0.2", -+ "glib-2.0", -+ "gio-2.0", -+ "gobject-2.0" -+ ] -+ -+ CXXFLAGS += CONFIG['TK_CFLAGS'] -+ -+ UNIFIED_SOURCES += [ -+ "/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc" -+ ] -+ - if CONFIG["OS_TARGET"] == "NetBSD": - - DEFINES["USE_X11"] = "1" -diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc -index 7510bde47fbb..9dab1eb503f6 100644 ---- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc -+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc -@@ -66,4 +66,17 @@ std::unique_ptr DesktopCapturer::CreateAppCapturer( - return capturer; - } - -+#if defined(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 -+ - } // namespace webrtc -diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h -index eb84d3c3bf50..17cacc5dcac6 100644 ---- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h -+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h -@@ -129,6 +129,10 @@ class DesktopCapturer { - static std::unique_ptr CreateAppCapturer( - const DesktopCaptureOptions& options); - -+#if defined(USE_PIPEWIRE) || defined(USE_X11) -+ static bool IsRunningUnderWayland(); -+#endif -+ - protected: - // CroppingWindowCapturer needs to create raw capturers without wrappers, so - // the following two functions are protected. -diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.cc new file mode 100644 -index 000000000000..f7aaf3dcd6d9 +index 000000000..39c19164d --- /dev/null -+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc -@@ -0,0 +1,44 @@ ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.cc +@@ -0,0 +1,849 @@ +/* -+ * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. ++ * 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 @@ -393,176 +308,23 @@ index 000000000000..f7aaf3dcd6d9 + * be found in the AUTHORS file in the root of the source tree. + */ + -+#include "webrtc/modules/desktop_capture/mouse_cursor_monitor.h" -+ -+#if defined(USE_PIPEWIRE) -+#include "webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc" -+#endif // defined(USE_PIPEWIRE) -+ -+#if defined(USE_X11) -+#include "webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc" -+#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) -+} -+ -+} // namespace webrtc -diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc -index 3a632cc0d9cd..b70b4e2568dc 100644 ---- a/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc -+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc -@@ -14,6 +14,7 @@ - - namespace webrtc { - -+#if not defined(USE_PIPEWIRE) - MouseCursorMonitor* MouseCursorMonitor::CreateForWindow( - const DesktopCaptureOptions& options, - WindowId window) { -@@ -25,5 +26,6 @@ MouseCursorMonitor* MouseCursorMonitor::CreateForScreen( - ScreenId screen) { - return NULL; - } -+#endif // not defined(USE_PIPEWIRE) - - } // namespace webrtc -diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc -index 2dcad5b3887f..a8397f1ec15c 100644 ---- a/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc -+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc -@@ -69,6 +69,9 @@ class MouseCursorMonitorX11 : public MouseCursorMonitor, - void Stop() override; - void Capture() override; - -+ static MouseCursorMonitor* CreateForWindow(const DesktopCaptureOptions& options, WindowId window); -+ static MouseCursorMonitor* CreateForScreen(const DesktopCaptureOptions& options, ScreenId screen); -+ - private: - // SharedXDisplay::XEventHandler interface. - bool HandleXEvent(const XEvent& event) override; -@@ -244,7 +247,7 @@ void MouseCursorMonitorX11::CaptureCursor() { - } - - // static --MouseCursorMonitor* MouseCursorMonitor::CreateForWindow( -+MouseCursorMonitor* MouseCursorMonitorX11::CreateForWindow( - const DesktopCaptureOptions& options, WindowId window) { - if (!options.x_display()) - return NULL; -@@ -254,7 +257,7 @@ MouseCursorMonitor* MouseCursorMonitor::CreateForWindow( - return new MouseCursorMonitorX11(options, outer_window, window); - } - --MouseCursorMonitor* MouseCursorMonitor::CreateForScreen( -+MouseCursorMonitor* MouseCursorMonitorX11::CreateForScreen( - const DesktopCaptureOptions& options, - ScreenId screen) { - if (!options.x_display()) -diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc -new file mode 100644 -index 000000000000..8c155102ed74 ---- /dev/null -+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (c) 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 "webrtc/modules/desktop_capture/desktop_capture_options.h" -+#include "webrtc/modules/desktop_capture/desktop_capturer.h" -+ -+#include -+ -+#if defined(USE_PIPEWIRE) -+#include "webrtc/modules/desktop_capture/screen_capturer_pipewire.cc" -+#endif // defined(USE_PIPEWIRE) -+ -+#if defined(USE_X11) -+#include "webrtc/modules/desktop_capture/screen_capturer_x11.cc" -+#endif // defined(USE_X11) -+ -+namespace webrtc { -+ -+// static -+std::unique_ptr DesktopCapturer::CreateRawScreenCapturer( -+ const DesktopCaptureOptions& options) { -+#if defined(USE_PIPEWIRE) -+ if (DesktopCapturer::IsRunningUnderWayland()) { -+ return ScreenCapturerPipeWire::CreateRawScreenCapturer(options); -+ } -+#endif // defined(USE_PIPEWIRE) -+ -+#if defined(USE_X11) -+ return ScreenCapturerX11::CreateRawScreenCapturer(options); -+#endif // defined(USE_X11) -+ -+ return nullptr; -+} -+ -+} // namespace webrtc -diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc -new file mode 100644 -index 000000000000..ce47ae29eac9 ---- /dev/null -+++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc -@@ -0,0 +1,1003 @@ -+/* -+ * Copyright (c) 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 -+ -+#include ++#include +#include +#include -+#define typeof __typeof__ -+#include + +#include +#include -+#include +#include +#include + -+#include "webrtc/base/checks.h" -+#include "webrtc/base/logging.h" ++#include "webrtc/modules/desktop_capture/base_capturer_pipewire.h" ++ +#include "webrtc/modules/desktop_capture/desktop_capture_options.h" +#include "webrtc/modules/desktop_capture/desktop_capturer.h" ++#include "webrtc/base/checks.h" ++#include "webrtc/base/logging.h" + +namespace webrtc { -+namespace { + +const char kDesktopBusName[] = "org.freedesktop.portal.Desktop"; +const char kDesktopObjectPath[] = "/org/freedesktop/portal/desktop"; @@ -572,150 +334,14 @@ index 000000000000..ce47ae29eac9 +const char kRequestInterfaceName[] = "org.freedesktop.portal.Request"; +const char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast"; + -+const int kBytesPerPixel = 4; -+ -+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 ScreenCapturerPipeWire : public DesktopCapturer { -+ public: -+ ScreenCapturerPipeWire(); -+ ~ScreenCapturerPipeWire() override; -+ -+ static std::unique_ptr CreateRawScreenCapturer( -+ const DesktopCaptureOptions& options); -+ -+ // DesktopCapturer interface. -+ void Start(Callback* delegate) override; -+ void Stop() 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; -+ -+ // <-- 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; -+ -+ void InitPipeWire(); -+ void InitPipeWireTypes(); -+ -+ void CreateReceivingStream(); -+ void HandleBuffer(pw_buffer* buffer); -+ -+ void ConvertRGBxToBGRxIfNeeded(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(ScreenCapturerPipeWire); -+}; ++const int kBytesPerPixelPw = 4; + +// static -+void ScreenCapturerPipeWire::OnStateChanged(void* data, ++void BaseCapturerPipeWire::OnStateChanged(void* data, + pw_remote_state old_state, + pw_remote_state state, + const char* error_message) { -+ ScreenCapturerPipeWire* that = static_cast(data); ++ BaseCapturerPipeWire* that = static_cast(data); + RTC_DCHECK(that); + + switch (state) { @@ -736,11 +362,11 @@ index 000000000000..ce47ae29eac9 +} + +// static -+void ScreenCapturerPipeWire::OnStreamStateChanged(void* data, ++void BaseCapturerPipeWire::OnStreamStateChanged(void* data, + pw_stream_state old_state, + pw_stream_state state, + const char* error_message) { -+ ScreenCapturerPipeWire* that = static_cast(data); ++ BaseCapturerPipeWire* that = static_cast(data); + RTC_DCHECK(that); + + switch (state) { @@ -760,10 +386,10 @@ index 000000000000..ce47ae29eac9 +} + +// static -+void ScreenCapturerPipeWire::OnStreamFormatChanged( ++void BaseCapturerPipeWire::OnStreamFormatChanged( + void* data, + const struct spa_pod* format) { -+ ScreenCapturerPipeWire* that = static_cast(data); ++ BaseCapturerPipeWire* that = static_cast(data); + RTC_DCHECK(that); + + LOG(LS_INFO) << "PipeWire stream format changed."; @@ -780,7 +406,7 @@ index 000000000000..ce47ae29eac9 + + 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 stride = SPA_ROUND_UP_N(width * kBytesPerPixelPw, 4); + auto size = height * stride; + + uint8_t buffer[1024] = {}; @@ -788,34 +414,41 @@ index 000000000000..ce47ae29eac9 + + // Setup buffers and meta header for new format. + const struct spa_pod* params[2]; -+ params[0] = reinterpret_cast(spa_pod_builder_object(&builder, ++ 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, ++ 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 ++ // 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, ++ 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, ++ ":", 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))); ++ ":", 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 ScreenCapturerPipeWire::OnStreamProcess(void* data) { -+ ScreenCapturerPipeWire* that = static_cast(data); ++void BaseCapturerPipeWire::OnStreamProcess(void* data) { ++ BaseCapturerPipeWire* that = static_cast(data); + RTC_DCHECK(that); + + pw_buffer* buf = nullptr; @@ -829,15 +462,14 @@ index 000000000000..ce47ae29eac9 + pw_stream_queue_buffer(that->pw_stream_, buf); +} + -+ScreenCapturerPipeWire::ScreenCapturerPipeWire() { -+ 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); -+} ++BaseCapturerPipeWire::BaseCapturerPipeWire(CaptureSourceType source_type) ++ : capture_source_type_(source_type) {} ++ ++BaseCapturerPipeWire::~BaseCapturerPipeWire() { ++ if (pw_main_loop_) { ++ pw_thread_loop_stop(pw_main_loop_); ++ } + -+ScreenCapturerPipeWire::~ScreenCapturerPipeWire() { + if (pw_type_) { + delete pw_type_; + } @@ -906,13 +538,17 @@ index 000000000000..ce47ae29eac9 + if (proxy_) { + g_clear_object(&proxy_); + } -+ -+ if (connection_) { -+ g_clear_object(&connection_); -+ } +} + -+void ScreenCapturerPipeWire::InitPipeWire() { ++void BaseCapturerPipeWire::InitPortals() { ++ 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); @@ -920,7 +556,7 @@ index 000000000000..ce47ae29eac9 + + 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, 0); ++ pw_remote_ = pw_remote_new(pw_core_, nullptr, /*user_data_size=*/0); + + InitPipeWireTypes(); + @@ -939,10 +575,11 @@ index 000000000000..ce47ae29eac9 + + if (pw_thread_loop_start(pw_main_loop_) < 0) { + LOG(LS_ERROR) << "Failed to start main PipeWire loop"; ++ portal_init_failed_ = true; + } +} + -+void ScreenCapturerPipeWire::InitPipeWireTypes() { ++void BaseCapturerPipeWire::InitPipeWireTypes() { + spa_type_map* map = pw_core_type_->map; + pw_type_ = new PipeWireType(); + @@ -952,7 +589,7 @@ index 000000000000..ce47ae29eac9 + spa_type_video_format_map(map, &pw_type_->video_format); +} + -+void ScreenCapturerPipeWire::CreateReceivingStream() { ++void BaseCapturerPipeWire::CreateReceivingStream() { + spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; + spa_rectangle pwScreenBounds = + spa_rectangle{static_cast(desktop_size_.width()), @@ -968,40 +605,46 @@ index 000000000000..ce47ae29eac9 + 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, ++ 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_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)); ++ // 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, nullptr, flags, params, -+ 1) != 0) { ++ 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) { + LOG(LS_ERROR) << "Could not connect receiving stream."; ++ portal_init_failed_ = true; ++ return; + } +} + -+void ScreenCapturerPipeWire::HandleBuffer(pw_buffer* buffer) { ++void BaseCapturerPipeWire::HandleBuffer(pw_buffer* buffer) { + spa_buffer* spaBuffer = buffer->buffer; + void* src = nullptr; + @@ -1011,44 +654,43 @@ index 000000000000..ce47ae29eac9 + + uint32_t maxSize = spaBuffer->datas[0].maxsize; + int32_t srcStride = spaBuffer->datas[0].chunk->stride; -+ if (srcStride != (desktop_size_.width() * kBytesPerPixel)) { ++ if (srcStride != (desktop_size_.width() * kBytesPerPixelPw)) { + LOG(LS_ERROR) << "Got buffer with stride different from screen stride: " -+ << srcStride -+ << " != " << (desktop_size_.width() * kBytesPerPixel); ++ << srcStride ++ << " != " << (desktop_size_.width() * kBytesPerPixelPw); ++ portal_init_failed_ = true; + return; + } + -+ uint8_t* tempFrame = static_cast(malloc(maxSize)); -+ std::memcpy(tempFrame, src, maxSize); -+ -+ ConvertRGBxToBGRxIfNeeded(tempFrame, maxSize); -+ + if (!current_frame_) { + current_frame_ = static_cast(malloc(maxSize)); + } -+ + RTC_DCHECK(current_frame_ != nullptr); -+ std::memcpy(current_frame_, tempFrame, maxSize); + -+ free(tempFrame); -+} -+ -+void ScreenCapturerPipeWire::ConvertRGBxToBGRxIfNeeded(uint8_t* frame, uint32_t size) -+{ + // 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) { -+ // 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; -+ } ++ 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); + } +} + -+guint ScreenCapturerPipeWire::SetupRequestResponseSignal( ++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( @@ -1058,19 +700,20 @@ index 000000000000..ce47ae29eac9 +} + +// static -+void ScreenCapturerPipeWire::OnProxyRequested(GObject* /*object*/, ++void BaseCapturerPipeWire::OnProxyRequested(GObject* /*object*/, + GAsyncResult* result, + gpointer user_data) { -+ ScreenCapturerPipeWire* that = -+ static_cast(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_) { + LOG(LS_ERROR) << "Failed to create a proxy for the screen cast portal: " -+ << error->message; ++ << error->message; + g_error_free(error); ++ that->portal_init_failed_ = true; + return; + } + that->connection_ = g_dbus_proxy_get_connection(that->proxy_); @@ -1080,7 +723,7 @@ index 000000000000..ce47ae29eac9 +} + +// static -+gchar* ScreenCapturerPipeWire::PrepareSignalHandle(GDBusConnection* connection, ++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++) { @@ -1096,7 +739,7 @@ index 000000000000..ce47ae29eac9 + return handle; +} + -+void ScreenCapturerPipeWire::SessionRequest() { ++void BaseCapturerPipeWire::SessionRequest() { + GVariantBuilder builder; + gchar* variant_string; + @@ -1123,19 +766,20 @@ index 000000000000..ce47ae29eac9 +} + +// static -+void ScreenCapturerPipeWire::OnSessionRequested(GDBusConnection* connection, ++void BaseCapturerPipeWire::OnSessionRequested(GDBusConnection* connection, + GAsyncResult* result, + gpointer user_data) { -+ ScreenCapturerPipeWire* that = -+ static_cast(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) { + LOG(LS_ERROR) << "Failed to create a screen cast session: " -+ << error->message; ++ << error->message; + g_error_free(error); ++ that->portal_init_failed_ = true; + return; + } + LOG(LS_INFO) << "Initializing the screen cast session."; @@ -1150,31 +794,17 @@ index 000000000000..ce47ae29eac9 + that->session_request_signal_id_); + that->session_request_signal_id_ = 0; + } ++ that->portal_init_failed_ = true; + return; + } + -+ // Support for older xdg-desktop-portal version. -+ if (g_strcmp0(that->portal_handle_, handle) != 0) { -+ if (that->session_request_signal_id_) { -+ g_dbus_connection_signal_unsubscribe(connection, -+ that->session_request_signal_id_); -+ that->session_request_signal_id_ = 0; -+ } -+ -+ g_clear_pointer(&that->portal_handle_, g_free); -+ that->portal_handle_ = handle; -+ -+ that->session_request_signal_id_ = that->SetupRequestResponseSignal( -+ that->portal_handle_, OnSessionRequestResponseSignal); -+ } -+ + g_free(handle); + + LOG(LS_INFO) << "Subscribing to the screen cast session."; +} + +// static -+void ScreenCapturerPipeWire::OnSessionRequestResponseSignal( ++void BaseCapturerPipeWire::OnSessionRequestResponseSignal( + GDBusConnection* connection, + const gchar* sender_name, + const gchar* object_path, @@ -1182,11 +812,13 @@ index 000000000000..ce47ae29eac9 + const gchar* signal_name, + GVariant* parameters, + gpointer user_data) { -+ ScreenCapturerPipeWire* that = -+ static_cast(user_data); ++ BaseCapturerPipeWire* that = ++ static_cast(user_data); + RTC_DCHECK(that); + -+ LOG(LS_INFO) << "Received response for the screen cast session subscription."; ++ ++ LOG(LS_INFO) ++ << "Received response for the screen cast session subscription."; + + guint32 portal_response; + GVariant* response_data; @@ -1196,20 +828,23 @@ index 000000000000..ce47ae29eac9 + g_variant_unref(response_data); + + if (!that->session_handle_ || portal_response) { -+ LOG(LS_ERROR) << "Failed to request the screen cast session subscription."; ++ LOG(LS_ERROR) ++ << "Failed to request the screen cast session subscription."; ++ that->portal_init_failed_ = true; + return; + } + + that->SourcesRequest(); +} + -+void ScreenCapturerPipeWire::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(1)); ++ 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)); @@ -1231,11 +866,11 @@ index 000000000000..ce47ae29eac9 +} + +// static -+void ScreenCapturerPipeWire::OnSourcesRequested(GDBusConnection* connection, ++void BaseCapturerPipeWire::OnSourcesRequested(GDBusConnection* connection, + GAsyncResult* result, + gpointer user_data) { -+ ScreenCapturerPipeWire* that = -+ static_cast(user_data); ++ BaseCapturerPipeWire* that = ++ static_cast(user_data); + RTC_DCHECK(that); + + GError* error = nullptr; @@ -1243,6 +878,7 @@ index 000000000000..ce47ae29eac9 + if (!variant) { + LOG(LS_ERROR) << "Failed to request the sources: " << error->message; + g_error_free(error); ++ that->portal_init_failed_ = true; + return; + } + @@ -1258,31 +894,17 @@ index 000000000000..ce47ae29eac9 + that->sources_request_signal_id_); + that->sources_request_signal_id_ = 0; + } ++ that->portal_init_failed_ = true; + return; + } + -+ // Support for older xdg-desktop-portal version. -+ if (g_strcmp0(that->sources_handle_, handle) != 0) { -+ if (that->sources_request_signal_id_) { -+ g_dbus_connection_signal_unsubscribe(connection, -+ that->sources_request_signal_id_); -+ that->sources_request_signal_id_ = 0; -+ } -+ -+ g_clear_pointer(&that->sources_handle_, g_free); -+ that->sources_handle_ = handle; -+ -+ that->sources_request_signal_id_ = that->SetupRequestResponseSignal( -+ that->sources_handle_, OnSourcesRequestResponseSignal); -+ } -+ + g_free(handle); + + LOG(LS_INFO) << "Subscribed to sources signal."; +} + +// static -+void ScreenCapturerPipeWire::OnSourcesRequestResponseSignal( ++void BaseCapturerPipeWire::OnSourcesRequestResponseSignal( + GDBusConnection* connection, + const gchar* sender_name, + const gchar* object_path, @@ -1290,15 +912,24 @@ index 000000000000..ce47ae29eac9 + const gchar* signal_name, + GVariant* parameters, + gpointer user_data) { -+ ScreenCapturerPipeWire* that = -+ static_cast(user_data); ++ BaseCapturerPipeWire* that = ++ static_cast(user_data); + RTC_DCHECK(that); + ++ guint32 portal_response; ++ g_variant_get(parameters, "(u@a{sv})", &portal_response, nullptr); ++ if (portal_response) { ++ LOG(LS_ERROR) ++ << "Failed to select sources for the screen cast session."; ++ that->portal_init_failed_ = true; ++ return; ++ } ++ + LOG(LS_INFO) << "Received sources signal from session."; + that->StartRequest(); +} + -+void ScreenCapturerPipeWire::StartRequest() { ++void BaseCapturerPipeWire::StartRequest() { + GVariantBuilder builder; + gchar* variant_string; + @@ -1324,19 +955,20 @@ index 000000000000..ce47ae29eac9 +} + +// static -+void ScreenCapturerPipeWire::OnStartRequested(GDBusConnection* connection, ++void BaseCapturerPipeWire::OnStartRequested(GDBusConnection* connection, + GAsyncResult* result, + gpointer user_data) { -+ ScreenCapturerPipeWire* that = -+ static_cast(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) { + LOG(LS_ERROR) << "Failed to start the screen cast session: " -+ << error->message; ++ << error->message; + g_error_free(error); ++ that->portal_init_failed_ = true; + return; + } + @@ -1353,31 +985,17 @@ index 000000000000..ce47ae29eac9 + that->start_request_signal_id_); + that->start_request_signal_id_ = 0; + } ++ that->portal_init_failed_ = true; + return; + } + -+ // Support for older xdg-desktop-portal version. -+ if (g_strcmp0(that->start_handle_, handle) != 0) { -+ if (that->start_request_signal_id_) { -+ g_dbus_connection_signal_unsubscribe(connection, -+ that->start_request_signal_id_); -+ that->start_request_signal_id_ = 0; -+ } -+ -+ g_clear_pointer(&that->start_handle_, g_free); -+ that->start_handle_ = handle; -+ -+ that->start_request_signal_id_ = that->SetupRequestResponseSignal( -+ that->start_handle_, OnStartRequestResponseSignal); -+ } -+ + g_free(handle); + + LOG(LS_INFO) << "Subscribed to the start signal."; +} + +// static -+void ScreenCapturerPipeWire::OnStartRequestResponseSignal( ++void BaseCapturerPipeWire::OnStartRequestResponseSignal( + GDBusConnection* connection, + const gchar* sender_name, + const gchar* object_path, @@ -1385,8 +1003,8 @@ index 000000000000..ce47ae29eac9 + const gchar* signal_name, + GVariant* parameters, + gpointer user_data) { -+ ScreenCapturerPipeWire* that = -+ static_cast(user_data); ++ BaseCapturerPipeWire* that = ++ static_cast(user_data); + RTC_DCHECK(that); + + LOG(LS_INFO) << "Start signal received."; @@ -1396,6 +1014,7 @@ index 000000000000..ce47ae29eac9 + g_variant_get(parameters, "(u@a{sv})", &portal_response, &response_data); + if (portal_response || !response_data) { + LOG(LS_ERROR) << "Failed to start the screen cast session."; ++ that->portal_init_failed_ = true; + return; + } + @@ -1428,7 +1047,7 @@ index 000000000000..ce47ae29eac9 + that->OpenPipeWireRemote(); +} + -+void ScreenCapturerPipeWire::OpenPipeWireRemote() { ++void BaseCapturerPipeWire::OpenPipeWireRemote() { + GVariantBuilder builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + @@ -1444,12 +1063,12 @@ index 000000000000..ce47ae29eac9 +} + +// static -+void ScreenCapturerPipeWire::OnOpenPipeWireRemoteRequested( ++void BaseCapturerPipeWire::OnOpenPipeWireRemoteRequested( + GDBusConnection* connection, + GAsyncResult* result, + gpointer user_data) { -+ ScreenCapturerPipeWire* that = -+ static_cast(user_data); ++ BaseCapturerPipeWire* that = ++ static_cast(user_data); + RTC_DCHECK(that); + + GError* error = nullptr; @@ -1457,8 +1076,10 @@ index 000000000000..ce47ae29eac9 + GVariant* variant = g_dbus_proxy_call_with_unix_fd_list_finish( + that->proxy_, &outlist, result, &error); + if (!variant) { -+ LOG(LS_ERROR) << "Failed to open the PipeWire remote: " << error->message; ++ LOG(LS_ERROR) << "Failed to open the PipeWire remote: " ++ << error->message; + g_error_free(error); ++ that->portal_init_failed_ = true; + return; + } + @@ -1467,9 +1088,10 @@ index 000000000000..ce47ae29eac9 + + if ((that->pw_fd_ = g_unix_fd_list_get(outlist, index, &error)) == -1) { + LOG(LS_ERROR) << "Failed to get file descriptor from the list: " -+ << error->message; ++ << error->message; + g_error_free(error); + g_variant_unref(variant); ++ that->portal_init_failed_ = true; + return; + } + @@ -1480,21 +1102,21 @@ index 000000000000..ce47ae29eac9 + LOG(LS_INFO) << "PipeWire remote opened."; +} + -+void ScreenCapturerPipeWire::Start(Callback* callback) { ++void BaseCapturerPipeWire::Start(Callback* callback) { + RTC_DCHECK(!callback_); + RTC_DCHECK(callback); + ++ InitPortals(); ++ + callback_ = callback; +} + -+void ScreenCapturerPipeWire::Stop() { -+ callback_ = nullptr; -+ if (pw_main_loop_) { -+ pw_thread_loop_stop(pw_main_loop_); ++void BaseCapturerPipeWire::CaptureFrame() { ++ if (portal_init_failed_) { ++ callback_->OnCaptureResult(Result::ERROR_PERMANENT, nullptr); ++ return; + } -+} + -+void ScreenCapturerPipeWire::CaptureFrame() { + if (!current_frame_) { + callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); + return; @@ -1502,7 +1124,7 @@ index 000000000000..ce47ae29eac9 + + std::unique_ptr result(new BasicDesktopFrame(desktop_size_)); + result->CopyPixelsFrom( -+ current_frame_, (desktop_size_.width() * kBytesPerPixel), ++ current_frame_, (desktop_size_.width() * kBytesPerPixelPw), + DesktopRect::MakeWH(desktop_size_.width(), desktop_size_.height())); + if (!result) { + callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); @@ -1511,18 +1133,456 @@ index 000000000000..ce47ae29eac9 + callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); +} + -+bool ScreenCapturerPipeWire::GetSourceList(SourceList* sources) { ++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 ScreenCapturerPipeWire::SelectSource(SourceId id) { -+ // TODO ++bool BaseCapturerPipeWire::SelectSource(SourceId id) { ++ // Screen selection is handled by the xdg-desktop-portal. + return true; +} + -+} // namespace ++} // namespace webrtc +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.h b/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.h +new file mode 100644 +index 000000000..4577ddf6b +--- /dev/null ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.h +@@ -0,0 +1,167 @@ ++/* ++ * 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 "webrtc/modules/desktop_capture/desktop_capture_options.h" ++#include "webrtc/modules/desktop_capture/desktop_capturer.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 Stop() override { callback_ = nullptr; } ++ 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 InitPortals(); ++ 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/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build +index ea1726a51..d72fe8161 100644 +--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_gn/moz.build +@@ -166,10 +166,6 @@ if CONFIG["OS_TARGET"] == "Linux": + ] + + UNIFIED_SOURCES += [ +- "/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_x11.cc", +- "/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc", +- "/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.cc", +- "/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc", + "/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/desktop_device_info_x11.cc", + "/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/shared_x_display.cc", + "/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/shared_x_util.cc", +@@ -177,6 +173,38 @@ if CONFIG["OS_TARGET"] == "Linux": + "/media/webrtc/trunk/webrtc/modules/desktop_capture/x11/x_server_pixel_buffer.cc" + ] + ++# Common stuff between Pipewire and X11 ++if CONFIG["OS_TARGET"] == "Linux": ++ ++ UNIFIED_SOURCES += [ ++ "/media/webrtc/trunk/webrtc/modules/desktop_capture/app_capturer_linux.cc", ++ "/media/webrtc/trunk/webrtc/modules/desktop_capture/base_capturer_pipewire.cc", ++ "/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc", ++ "/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc", ++ "/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc", ++ "/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc", ++ "/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.cc", ++ ] ++ ++# Pipewire ++if CONFIG["OS_TARGET"] == "Linux": ++ ++ DEFINES["USE_PIPEWIRE"] = "1" ++ ++ OS_LIBS += [ ++ "rt", ++ "pipewire-0.2", ++ "glib-2.0", ++ "gio-2.0", ++ "gobject-2.0" ++ ] ++ ++ CXXFLAGS += CONFIG['TK_CFLAGS'] ++ ++ UNIFIED_SOURCES += [ ++ "/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc" ++ ] ++ + if CONFIG["OS_TARGET"] == "NetBSD": + + DEFINES["USE_X11"] = "1" +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc +index 7510bde47..9dab1eb50 100644 +--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.cc +@@ -66,4 +66,17 @@ std::unique_ptr DesktopCapturer::CreateAppCapturer( + return capturer; + } + ++#if defined(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 ++ + } // namespace webrtc +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h +index eb84d3c3b..17cacc5dc 100644 +--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capturer.h +@@ -129,6 +129,10 @@ class DesktopCapturer { + static std::unique_ptr CreateAppCapturer( + const DesktopCaptureOptions& options); + ++#if defined(USE_PIPEWIRE) || defined(USE_X11) ++ static bool IsRunningUnderWayland(); ++#endif ++ + protected: + // CroppingWindowCapturer needs to create raw capturers without wrappers, so + // the following two functions are protected. +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc +new file mode 100644 +index 000000000..f7aaf3dcd +--- /dev/null ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc +@@ -0,0 +1,44 @@ ++/* ++ * Copyright (c) 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 "webrtc/modules/desktop_capture/mouse_cursor_monitor.h" ++ ++#if defined(USE_PIPEWIRE) ++#include "webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc" ++#endif // defined(USE_PIPEWIRE) ++ ++#if defined(USE_X11) ++#include "webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc" ++#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) ++} ++ ++} // namespace webrtc +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc +index 3a632cc0d..b70b4e256 100644 +--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_null.cc +@@ -14,6 +14,7 @@ + + namespace webrtc { + ++#if not defined(USE_PIPEWIRE) + MouseCursorMonitor* MouseCursorMonitor::CreateForWindow( + const DesktopCaptureOptions& options, + WindowId window) { +@@ -25,5 +26,6 @@ MouseCursorMonitor* MouseCursorMonitor::CreateForScreen( + ScreenId screen) { + return NULL; + } ++#endif // not defined(USE_PIPEWIRE) + + } // namespace webrtc +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc +index 2dcad5b38..a8397f1ec 100644 +--- a/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_x11.cc +@@ -69,6 +69,9 @@ class MouseCursorMonitorX11 : public MouseCursorMonitor, + void Stop() override; + void Capture() override; + ++ static MouseCursorMonitor* CreateForWindow(const DesktopCaptureOptions& options, WindowId window); ++ static MouseCursorMonitor* CreateForScreen(const DesktopCaptureOptions& options, ScreenId screen); ++ + private: + // SharedXDisplay::XEventHandler interface. + bool HandleXEvent(const XEvent& event) override; +@@ -244,7 +247,7 @@ void MouseCursorMonitorX11::CaptureCursor() { + } + + // static +-MouseCursorMonitor* MouseCursorMonitor::CreateForWindow( ++MouseCursorMonitor* MouseCursorMonitorX11::CreateForWindow( + const DesktopCaptureOptions& options, WindowId window) { + if (!options.x_display()) + return NULL; +@@ -254,7 +257,7 @@ MouseCursorMonitor* MouseCursorMonitor::CreateForWindow( + return new MouseCursorMonitorX11(options, outer_window, window); + } + +-MouseCursorMonitor* MouseCursorMonitor::CreateForScreen( ++MouseCursorMonitor* MouseCursorMonitorX11::CreateForScreen( + const DesktopCaptureOptions& options, + ScreenId screen) { + if (!options.x_display()) +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc +new file mode 100644 +index 000000000..43c4098e2 +--- /dev/null ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc +@@ -0,0 +1,40 @@ ++/* ++ * 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 "webrtc/modules/desktop_capture/desktop_capture_options.h" ++#include "webrtc/modules/desktop_capture/desktop_capturer.h" ++ ++#if defined(USE_PIPEWIRE) ++#include "webrtc/modules/desktop_capture/screen_capturer_pipewire.h" ++#endif // defined(USE_PIPEWIRE) ++ ++#if defined(USE_X11) ++#include "webrtc/modules/desktop_capture/screen_capturer_x11.cc" ++#endif // defined(USE_X11) ++ ++namespace webrtc { ++ ++// static ++std::unique_ptr DesktopCapturer::CreateRawScreenCapturer( ++ const DesktopCaptureOptions& options) { ++#if defined(USE_PIPEWIRE) ++ if (DesktopCapturer::IsRunningUnderWayland()) { ++ return ScreenCapturerPipeWire::CreateRawScreenCapturer(options); ++ } ++#endif // defined(USE_PIPEWIRE) ++ ++#if defined(USE_X11) ++ return ScreenCapturerX11::CreateRawScreenCapturer(options); ++#endif // defined(USE_X11) ++ ++ return nullptr; ++} ++ ++} // namespace webrtc +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc +new file mode 100644 +index 000000000..b506c562f +--- /dev/null ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.cc +@@ -0,0 +1,31 @@ ++/* ++ * 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 "webrtc/modules/desktop_capture/screen_capturer_pipewire.h" ++ ++#include ++ ++namespace webrtc { ++ ++ScreenCapturerPipeWire::ScreenCapturerPipeWire() ++ : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Screen) {} ++ScreenCapturerPipeWire::~ScreenCapturerPipeWire() {} + +// static +std::unique_ptr @@ -1535,14 +1595,53 @@ index 000000000000..ce47ae29eac9 +} + +} // namespace webrtc +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.h b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.h +new file mode 100644 +index 000000000..23cc3a53d +--- /dev/null ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_pipewire.h +@@ -0,0 +1,33 @@ ++/* ++ * 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 "webrtc/modules/desktop_capture/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/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.cc -index 7692f8b70181..ba137853456c 100644 +index 7692f8b70..ba1378534 100644 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.cc +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_x11.cc @@ -34,18 +34,20 @@ namespace webrtc { namespace { - + -// A class to perform video frame capturing for Linux. +// A class to perform video frame capturing for Linux on X11. // @@ -1561,13 +1660,13 @@ index 7692f8b70181..ba137853456c 100644 + ~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); @@ -118,14 +120,13 @@ class ScreenCapturerLinux : public DesktopCapturer, // current with the last buffer used. DesktopRegion last_invalid_region_; - + - RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerLinux); + RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerX11); }; @@ -1576,7 +1675,7 @@ index 7692f8b70181..ba137853456c 100644 +ScreenCapturerX11::ScreenCapturerX11() { helper_.SetLogGridSize(4); } - + -ScreenCapturerLinux::~ScreenCapturerLinux() { +ScreenCapturerX11::~ScreenCapturerX11() { options_.x_display()->RemoveEventHandler(ConfigureNotify, this); @@ -1585,16 +1684,16 @@ index 7692f8b70181..ba137853456c 100644 @@ -134,7 +135,7 @@ ScreenCapturerLinux::~ScreenCapturerLinux() { DeinitXlib(); } - + -bool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) { +bool ScreenCapturerX11::Init(const DesktopCaptureOptions& options) { options_ = options; - + root_window_ = RootWindow(display(), DefaultScreen(display())); @@ -177,7 +178,7 @@ bool ScreenCapturerLinux::Init(const DesktopCaptureOptions& options) { return true; } - + -void ScreenCapturerLinux::InitXDamage() { +void ScreenCapturerX11::InitXDamage() { // Our use of XDamage requires XFixes. @@ -1603,24 +1702,24 @@ index 7692f8b70181..ba137853456c 100644 @@ -218,18 +219,18 @@ void ScreenCapturerLinux::InitXDamage() { LOG(LS_INFO) << "Using XDamage extension."; } - + -void ScreenCapturerLinux::Start(Callback* callback) { +void ScreenCapturerX11::Start(Callback* callback) { RTC_DCHECK(!callback_); RTC_DCHECK(callback); - + callback_ = callback; } - + -void ScreenCapturerLinux::Stop() { +void ScreenCapturerX11::Stop() { callback_ = NULL; } - + -void ScreenCapturerLinux::CaptureFrame() { +void ScreenCapturerX11::CaptureFrame() { int64_t capture_start_time_nanos = rtc::TimeNanos(); - + queue_.MoveToNextFrame(); @@ -243,6 +244,7 @@ void ScreenCapturerLinux::CaptureFrame() { // in a good shape. @@ -1631,7 +1730,7 @@ index 7692f8b70181..ba137853456c 100644 return; } @@ -258,6 +260,7 @@ void ScreenCapturerLinux::CaptureFrame() { - + std::unique_ptr result = CaptureScreen(); if (!result) { + LOG(LS_WARNING) << "Temporarily failed to capture screen."; @@ -1641,7 +1740,7 @@ index 7692f8b70181..ba137853456c 100644 @@ -268,19 +271,19 @@ void ScreenCapturerLinux::CaptureFrame() { callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); } - + -bool ScreenCapturerLinux::GetSourceList(SourceList* sources) { +bool ScreenCapturerX11::GetSourceList(SourceList* sources) { RTC_DCHECK(sources->size() == 0); @@ -1649,13 +1748,13 @@ index 7692f8b70181..ba137853456c 100644 sources->push_back({0}); return true; } - + -bool ScreenCapturerLinux::SelectSource(SourceId id) { +bool ScreenCapturerX11::SelectSource(SourceId id) { // TODO(jiayl): implement screen selection. return true; } - + -bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) { +bool ScreenCapturerX11::HandleXEvent(const XEvent& event) { if (use_damage_ && (event.type == damage_event_base_ + XDamageNotify)) { @@ -1664,12 +1763,12 @@ index 7692f8b70181..ba137853456c 100644 @@ -295,7 +298,7 @@ bool ScreenCapturerLinux::HandleXEvent(const XEvent& event) { return false; } - + -std::unique_ptr ScreenCapturerLinux::CaptureScreen() { +std::unique_ptr ScreenCapturerX11::CaptureScreen() { std::unique_ptr frame = queue_.current_frame()->Share(); RTC_DCHECK(x_server_pixel_buffer_.window_size().equals(frame->size())); - + @@ -345,25 +348,26 @@ std::unique_ptr ScreenCapturerLinux::CaptureScreen() { // Doing full-screen polling, or this is the first capture after a // screen-resolution change. In either case, need a full-screen capture. @@ -1679,15 +1778,15 @@ index 7692f8b70181..ba137853456c 100644 + return nullptr; updated_region->SetRect(screen_rect); } - + return std::move(frame); } - + -void ScreenCapturerLinux::ScreenConfigurationChanged() { +void ScreenCapturerX11::ScreenConfigurationChanged() { // Make sure the frame buffers will be reallocated. queue_.Reset(); - + helper_.ClearInvalidRegion(); if (!x_server_pixel_buffer_.Init(display(), DefaultRootWindow(display()))) { LOG(LS_ERROR) << "Failed to initialize pixel buffer after screen " @@ -1695,7 +1794,7 @@ index 7692f8b70181..ba137853456c 100644 + "configuration change."; } } - + -void ScreenCapturerLinux::SynchronizeFrame() { +void ScreenCapturerX11::SynchronizeFrame() { // Synchronize the current buffer with the previous one since we do not @@ -1704,7 +1803,7 @@ index 7692f8b70181..ba137853456c 100644 @@ -383,7 +387,7 @@ void ScreenCapturerLinux::SynchronizeFrame() { } } - + -void ScreenCapturerLinux::DeinitXlib() { +void ScreenCapturerX11::DeinitXlib() { if (gc_) { @@ -1712,33 +1811,33 @@ index 7692f8b70181..ba137853456c 100644 gc_ = nullptr; @@ -407,17 +411,17 @@ void ScreenCapturerLinux::DeinitXlib() { } // namespace - + // static -std::unique_ptr DesktopCapturer::CreateRawScreenCapturer( +std::unique_ptr ScreenCapturerX11::CreateRawScreenCapturer( const DesktopCaptureOptions& options) { if (!options.x_display()) return nullptr; - + - std::unique_ptr capturer(new ScreenCapturerLinux()); + std::unique_ptr capturer(new ScreenCapturerX11()); if (!capturer.get()->Init(options)) { return nullptr; } - + - return std::unique_ptr(capturer.release()); + return std::move(capturer); } - + } // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc new file mode 100644 -index 000000000000..fde7750c878b +index 000000000..284ccdb7b --- /dev/null +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc @@ -0,0 +1,40 @@ +/* -+ * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. ++ * 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 @@ -1751,12 +1850,12 @@ index 000000000000..fde7750c878b +#include "webrtc/modules/desktop_capture/desktop_capturer.h" + +#if defined(USE_PIPEWIRE) -+#include "webrtc/modules/desktop_capture/window_capturer_null.cc" -+#endif // defined(USE_PIPEWIRE) ++#include "webrtc/modules/desktop_capture/window_capturer_pipewire.h" ++#endif // defined(USE_PIPEWIRE) + +#if defined(USE_X11) +#include "webrtc/modules/desktop_capture/window_capturer_x11.cc" -+#endif // defined(USE_X11) ++#endif // defined(USE_X11) + +namespace webrtc { + @@ -1765,26 +1864,26 @@ index 000000000000..fde7750c878b + const DesktopCaptureOptions& options) { +#if defined(USE_PIPEWIRE) + if (DesktopCapturer::IsRunningUnderWayland()) { -+ return std::unique_ptr(new WindowCapturerNull()); ++ return WindowCapturerPipeWire::CreateRawWindowCapturer(options); + } -+#endif // defined(USE_PIPEWIRE) ++#endif // defined(USE_PIPEWIRE) + +#if defined(USE_X11) + return WindowCapturerX11::CreateRawWindowCapturer(options); -+#endif // defined(USE_X11) ++#endif // defined(USE_X11) + + return nullptr; +} + +} // namespace webrtc diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_null.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_null.cc -index 0f0159bb5f16..f6ef0639a586 100755 +index 0f0159bb5..f6ef0639a 100755 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_null.cc +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_null.cc @@ -67,10 +67,12 @@ void WindowCapturerNull::CaptureFrame() { - + } // namespace - + +#if not defined(USE_PIPEWIRE) // static std::unique_ptr DesktopCapturer::CreateRawWindowCapturer( @@ -1792,16 +1891,89 @@ index 0f0159bb5f16..f6ef0639a586 100755 return std::unique_ptr(new WindowCapturerNull()); } +#endif // not defined(USE_PIPEWIRE) - + } // namespace webrtc +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.cc +new file mode 100644 +index 000000000..4f97e6ac2 +--- /dev/null ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.cc +@@ -0,0 +1,28 @@ ++/* ++ * 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 "webrtc/modules/desktop_capture/window_capturer_pipewire.h" ++ ++namespace webrtc { ++ ++WindowCapturerPipeWire::WindowCapturerPipeWire() ++ : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Window) {} ++WindowCapturerPipeWire::~WindowCapturerPipeWire() {} ++ ++// static ++std::unique_ptr ++WindowCapturerPipeWire::CreateRawWindowCapturer( ++ const DesktopCaptureOptions& options) { ++ std::unique_ptr capturer( ++ new WindowCapturerPipeWire()); ++ ++ return std::move(capturer); ++} ++} // namespace webrtc +diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.h b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.h +new file mode 100644 +index 000000000..e04bc7151 +--- /dev/null ++++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_pipewire.h +@@ -0,0 +1,33 @@ ++/* ++ * 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 "webrtc/modules/desktop_capture/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/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc -index fecb329db546..d478604aa3de 100644 +index fecb329db..d478604aa 100644 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_x11.cc @@ -32,11 +32,13 @@ namespace webrtc { - + namespace { - + -class WindowCapturerLinux : public DesktopCapturer, +class WindowCapturerX11 : public DesktopCapturer, public SharedXDisplay::XEventHandler { @@ -1812,17 +1984,17 @@ index fecb329db546..d478604aa3de 100644 + ~WindowCapturerX11() override; + + static std::unique_ptr CreateRawWindowCapturer(const DesktopCaptureOptions& options); - + // DesktopCapturer interface. void Start(Callback* callback) override; @@ -78,10 +80,10 @@ class WindowCapturerLinux : public DesktopCapturer, ::Window selected_window_ = 0; XServerPixelBuffer x_server_pixel_buffer_; - + - RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerLinux); + RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerX11); }; - + -WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options) +WindowCapturerX11::WindowCapturerX11(const DesktopCaptureOptions& options) : x_display_(options.x_display()) { @@ -1831,61 +2003,61 @@ index fecb329db546..d478604aa3de 100644 @@ -102,11 +104,11 @@ WindowCapturerLinux::WindowCapturerLinux(const DesktopCaptureOptions& options) x_display_->AddEventHandler(ConfigureNotify, this); } - + -WindowCapturerLinux::~WindowCapturerLinux() { +WindowCapturerX11::~WindowCapturerX11() { x_display_->RemoveEventHandler(ConfigureNotify, this); } - + -bool WindowCapturerLinux::GetSourceList(SourceList* sources) { +bool WindowCapturerX11::GetSourceList(SourceList* sources) { SourceList result; - + XErrorTrap error_trap(display()); @@ -159,7 +161,7 @@ bool WindowCapturerLinux::GetSourceList(SourceList* sources) { return true; } - + -bool WindowCapturerLinux::SelectSource(SourceId id) { +bool WindowCapturerX11::SelectSource(SourceId id) { if (!x_server_pixel_buffer_.Init(display(), id)) return false; - + @@ -180,7 +182,7 @@ bool WindowCapturerLinux::SelectSource(SourceId id) { return true; } - + -bool WindowCapturerLinux::FocusOnSelectedSource() { +bool WindowCapturerX11::FocusOnSelectedSource() { if (!selected_window_) return false; - + @@ -229,18 +231,18 @@ bool WindowCapturerLinux::FocusOnSelectedSource() { return true; } - + -void WindowCapturerLinux::Start(Callback* callback) { +void WindowCapturerX11::Start(Callback* callback) { assert(!callback_); assert(callback); - + callback_ = callback; } - + -void WindowCapturerLinux::Stop() { +void WindowCapturerX11::Stop() { callback_ = NULL; } - + -void WindowCapturerLinux::CaptureFrame() { +void WindowCapturerX11::CaptureFrame() { x_display_->ProcessPendingXEvents(); - + if (!x_server_pixel_buffer_.IsWindowValid()) { @@ -274,7 +276,7 @@ void WindowCapturerLinux::CaptureFrame() { callback_->OnCaptureResult(Result::SUCCESS, std::move(frame)); } - + -bool WindowCapturerLinux::HandleXEvent(const XEvent& event) { +bool WindowCapturerX11::HandleXEvent(const XEvent& event) { if (event.type == ConfigureNotify) { @@ -1894,34 +2066,34 @@ index fecb329db546..d478604aa3de 100644 @@ -288,7 +290,7 @@ bool WindowCapturerLinux::HandleXEvent(const XEvent& event) { return false; } - + -::Window WindowCapturerLinux::GetApplicationWindow(::Window window) { +::Window WindowCapturerX11::GetApplicationWindow(::Window window) { // Get WM_STATE property of the window. XWindowProperty window_state(display(), window, wm_state_atom_); - + @@ -326,7 +328,7 @@ bool WindowCapturerLinux::HandleXEvent(const XEvent& event) { return app_window; } - + -bool WindowCapturerLinux::IsDesktopElement(::Window window) { +bool WindowCapturerX11::IsDesktopElement(::Window window) { if (window == 0) return false; - + @@ -361,7 +363,7 @@ bool WindowCapturerLinux::IsDesktopElement(::Window window) { return result; } - + -bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) { +bool WindowCapturerX11::GetWindowTitle(::Window window, std::string* title) { int status; bool result = false; XTextProperty window_name; @@ -392,7 +394,7 @@ bool WindowCapturerLinux::GetWindowTitle(::Window window, std::string* title) { - + } // namespace - + -int WindowCapturerLinux::GetWindowProcessID(::Window window) { +int WindowCapturerX11::GetWindowProcessID(::Window window) { // Get _NET_WM_PID property of the window. @@ -1929,7 +2101,7 @@ index fecb329db546..d478604aa3de 100644 XWindowProperty process_id(display(), window, process_atom); @@ -401,11 +403,11 @@ int WindowCapturerLinux::GetWindowProcessID(::Window window) { } - + // static -std::unique_ptr DesktopCapturer::CreateRawWindowCapturer( +std::unique_ptr WindowCapturerX11::CreateRawWindowCapturer( @@ -1939,5 +2111,5 @@ index fecb329db546..d478604aa3de 100644 - return std::unique_ptr(new WindowCapturerLinux(options)); + return std::unique_ptr(new WindowCapturerX11(options)); } - + } // namespace webrtc