|
1 # HG changeset patch |
|
2 # Parent 5bd7b491505076dc38ba1efc7c406b9c53ba8389 |
|
3 |
1 diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild |
4 diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild |
2 index 2081d0c683a4..641133bf1ea4 100644 |
|
3 --- a/config/system-headers.mozbuild |
5 --- a/config/system-headers.mozbuild |
4 +++ b/config/system-headers.mozbuild |
6 +++ b/config/system-headers.mozbuild |
5 @@ -314,6 +314,7 @@ system_headers = [ |
7 @@ -309,16 +309,17 @@ system_headers = [ |
|
8 'gdk/gdkkeysyms.h', |
|
9 'gdk/gdkprivate.h', |
|
10 'gdk/gdkwayland.h', |
|
11 'gdk/gdkx.h', |
|
12 'gdk-pixbuf/gdk-pixbuf.h', |
6 'Gestalt.h', |
13 'Gestalt.h', |
7 'getopt.h', |
14 'getopt.h', |
8 'gio/gio.h', |
15 'gio/gio.h', |
9 + 'gio/gunixfdlist.h', |
16 + 'gio/gunixfdlist.h', |
10 'glibconfig.h', |
17 'glibconfig.h', |
11 'glib.h', |
18 'glib.h', |
12 'glib-object.h', |
19 'glib-object.h', |
13 @@ -607,6 +608,7 @@ system_headers = [ |
20 'glob.h', |
|
21 'gmodule.h', |
|
22 'gnome.h', |
|
23 'gnu/libc-version.h', |
|
24 'gps.h', |
|
25 @@ -602,16 +603,17 @@ system_headers = [ |
|
26 'pango/pangoxft.h', |
|
27 'pascal.h', |
|
28 'Patches.h', |
|
29 'Path.h', |
|
30 'pcfs/pc_dir.h', |
14 'Pgenerr.h', |
31 'Pgenerr.h', |
15 'PGenErr.h', |
32 'PGenErr.h', |
16 'Ph.h', |
33 'Ph.h', |
17 + 'pipewire/pipewire.h', |
34 + 'pipewire/pipewire.h', |
18 'pixman.h', |
35 'pixman.h', |
19 'pk11func.h', |
36 'pk11func.h', |
20 'pk11pqg.h', |
37 'pk11pqg.h', |
|
38 'pk11priv.h', |
|
39 'pk11pub.h', |
|
40 'pk11sdr.h', |
|
41 'pkcs11f.h', |
|
42 'pkcs11.h', |
21 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn b/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn |
43 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn b/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn |
22 index ba885217b3ba..201d3b755221 100644 |
|
23 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn |
44 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn |
24 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn |
45 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/BUILD.gn |
25 @@ -158,7 +158,7 @@ if (rtc_include_tests) { |
46 @@ -153,17 +153,17 @@ if (rtc_include_tests) { |
|
47 "../../test:test_support", |
|
48 ] |
|
49 } |
|
50 } |
|
51 |
26 if (is_linux) { |
52 if (is_linux) { |
27 if (rtc_use_pipewire) { |
53 if (rtc_use_pipewire) { |
28 pkg_config("pipewire") { |
54 pkg_config("pipewire") { |
29 - packages = [ "libpipewire-0.2" ] |
55 - packages = [ "libpipewire-0.2" ] |
30 + packages = [ "libpipewire-0.3" ] |
56 + packages = [ "libpipewire-0.3" ] |
31 |
57 |
32 defines = [ "WEBRTC_USE_PIPEWIRE" ] |
58 defines = [ "WEBRTC_USE_PIPEWIRE" ] |
33 } |
59 } |
|
60 |
|
61 pkg_config("gio") { |
|
62 packages = [ |
|
63 "gio-2.0", |
|
64 "gio-unix-2.0", |
34 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build |
65 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build |
35 index 90b40431c7e4..d844aa79d591 100644 |
|
36 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build |
66 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build |
37 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build |
67 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build |
38 @@ -194,6 +194,30 @@ if CONFIG["OS_TARGET"] == "Linux": |
68 @@ -112,16 +112,39 @@ if CONFIG["OS_TARGET"] == "DragonFly": |
|
69 "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/x_atom_cache.cc", |
|
70 "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/x_error_trap.cc", |
|
71 "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/x_server_pixel_buffer.cc", |
|
72 "/media/webrtc/trunk/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc", |
|
73 "/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc", |
39 "/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc" |
74 "/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc" |
40 ] |
75 ] |
41 |
76 |
42 +# PipeWire specific files |
77 +# PipeWire specific files |
43 +if CONFIG["OS_TARGET"] == "Linux": |
78 +if CONFIG["OS_TARGET"] == "Linux": |
60 + "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc", |
95 + "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc", |
61 + "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc", |
96 + "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc", |
62 + "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc" |
97 + "/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc" |
63 + ] |
98 + ] |
64 + |
99 + |
65 + |
100 if CONFIG["OS_TARGET"] == "FreeBSD": |
66 if CONFIG["OS_TARGET"] == "NetBSD": |
|
67 |
101 |
68 DEFINES["USE_X11"] = "1" |
102 DEFINES["USE_X11"] = "1" |
|
103 DEFINES["WEBRTC_BSD"] = True |
|
104 DEFINES["WEBRTC_POSIX"] = True |
|
105 DEFINES["_FILE_OFFSET_BITS"] = "64" |
|
106 |
|
107 OS_LIBS += [ |
69 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h |
108 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h |
70 index 1eb8ead26efa..316468eed1fc 100644 |
|
71 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h |
109 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h |
72 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h |
110 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/desktop_capture_options.h |
73 @@ -141,7 +141,7 @@ class DesktopCaptureOptions { |
111 @@ -136,15 +136,15 @@ class DesktopCaptureOptions { |
|
112 #if defined(USE_X11) |
|
113 bool use_update_notifications_ = false; |
|
114 #else |
|
115 bool use_update_notifications_ = true; |
|
116 #endif |
74 bool disable_effects_ = true; |
117 bool disable_effects_ = true; |
75 bool detect_updated_region_ = false; |
118 bool detect_updated_region_ = false; |
76 #if defined(WEBRTC_USE_PIPEWIRE) |
119 #if defined(WEBRTC_USE_PIPEWIRE) |
77 - bool allow_pipewire_ = false; |
120 - bool allow_pipewire_ = false; |
78 + bool allow_pipewire_ = true; |
121 + bool allow_pipewire_ = true; |
79 #endif |
122 #endif |
80 }; |
123 }; |
81 |
124 |
|
125 } // namespace webrtc |
|
126 |
|
127 #endif // MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_ |
82 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc |
128 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc |
83 index 379341c833de..76349f1fbd4d 100644 |
|
84 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc |
129 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc |
85 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc |
130 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc |
86 @@ -15,8 +15,11 @@ |
131 @@ -10,18 +10,21 @@ |
|
132 |
|
133 #include "modules/desktop_capture/linux/base_capturer_pipewire.h" |
|
134 |
|
135 #include <gio/gunixfdlist.h> |
|
136 #include <glib-object.h> |
87 |
137 |
88 #include <spa/param/format-utils.h> |
138 #include <spa/param/format-utils.h> |
89 #include <spa/param/props.h> |
139 #include <spa/param/props.h> |
90 -#include <spa/param/video/raw-utils.h> |
140 -#include <spa/param/video/raw-utils.h> |
91 -#include <spa/support/type-map.h> |
141 -#include <spa/support/type-map.h> |
95 +#include <sys/ioctl.h> |
145 +#include <sys/ioctl.h> |
96 +#include <sys/syscall.h> |
146 +#include <sys/syscall.h> |
97 |
147 |
98 #include <memory> |
148 #include <memory> |
99 #include <utility> |
149 #include <utility> |
100 @@ -36,31 +39,36 @@ const char kSessionInterfaceName[] = "org.freedesktop.portal.Session"; |
150 |
|
151 #include "modules/desktop_capture/desktop_capture_options.h" |
|
152 #include "modules/desktop_capture/desktop_capturer.h" |
|
153 #include "rtc_base/checks.h" |
|
154 #include "rtc_base/logging.h" |
|
155 @@ -31,181 +34,158 @@ namespace webrtc { |
|
156 const char kDesktopBusName[] = "org.freedesktop.portal.Desktop"; |
|
157 const char kDesktopObjectPath[] = "/org/freedesktop/portal/desktop"; |
|
158 const char kDesktopRequestObjectPath[] = |
|
159 "/org/freedesktop/portal/desktop/request"; |
|
160 const char kSessionInterfaceName[] = "org.freedesktop.portal.Session"; |
101 const char kRequestInterfaceName[] = "org.freedesktop.portal.Request"; |
161 const char kRequestInterfaceName[] = "org.freedesktop.portal.Request"; |
102 const char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast"; |
162 const char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast"; |
103 |
163 |
104 -// static |
164 + |
|
165 // static |
105 -void BaseCapturerPipeWire::OnStateChanged(void* data, |
166 -void BaseCapturerPipeWire::OnStateChanged(void* data, |
106 - pw_remote_state old_state, |
167 - pw_remote_state old_state, |
107 - pw_remote_state state, |
168 - pw_remote_state state, |
108 - const char* error_message) { |
169 - const char* error_message) { |
109 - BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); |
170 - BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); |
110 - RTC_DCHECK(that); |
171 - RTC_DCHECK(that); |
|
172 +void BaseCapturerPipeWire::SyncDmaBuf(int fd, uint64_t start_or_end) { |
|
173 + struct dma_buf_sync sync = { 0 }; |
|
174 + |
|
175 + sync.flags = start_or_end | DMA_BUF_SYNC_READ; |
111 |
176 |
112 - switch (state) { |
177 - switch (state) { |
113 - case PW_REMOTE_STATE_ERROR: |
178 - case PW_REMOTE_STATE_ERROR: |
114 - RTC_LOG(LS_ERROR) << "PipeWire remote state error: " << error_message; |
179 - RTC_LOG(LS_ERROR) << "PipeWire remote state error: " << error_message; |
115 - break; |
|
116 - case PW_REMOTE_STATE_CONNECTED: |
|
117 - RTC_LOG(LS_INFO) << "PipeWire remote state: connected."; |
|
118 - that->CreateReceivingStream(); |
|
119 - break; |
|
120 - case PW_REMOTE_STATE_CONNECTING: |
|
121 - RTC_LOG(LS_INFO) << "PipeWire remote state: connecting."; |
|
122 +// static |
|
123 +void BaseCapturerPipeWire::SyncDmaBuf(int fd, uint64_t start_or_end) { |
|
124 + struct dma_buf_sync sync = { 0 }; |
|
125 + |
|
126 + sync.flags = start_or_end | DMA_BUF_SYNC_READ; |
|
127 + |
|
128 + while(true) { |
180 + while(true) { |
129 + int ret; |
181 + int ret; |
130 + ret = ioctl (fd, DMA_BUF_IOCTL_SYNC, &sync); |
182 + ret = ioctl (fd, DMA_BUF_IOCTL_SYNC, &sync); |
131 + if (ret == -1 && errno == EINTR) { |
183 + if (ret == -1 && errno == EINTR) { |
132 + continue; |
184 + continue; |
133 + } else if (ret == -1) { |
185 + } else if (ret == -1) { |
134 + RTC_LOG(LS_ERROR) << "Failed to synchronize DMA buffer: " << g_strerror(errno); |
186 + RTC_LOG(LS_ERROR) << "Failed to synchronize DMA buffer: " << g_strerror(errno); |
135 break; |
187 break; |
|
188 - case PW_REMOTE_STATE_CONNECTED: |
|
189 - RTC_LOG(LS_INFO) << "PipeWire remote state: connected."; |
|
190 - that->CreateReceivingStream(); |
|
191 + } else { |
|
192 break; |
|
193 - case PW_REMOTE_STATE_CONNECTING: |
|
194 - RTC_LOG(LS_INFO) << "PipeWire remote state: connecting."; |
|
195 - break; |
136 - case PW_REMOTE_STATE_UNCONNECTED: |
196 - case PW_REMOTE_STATE_UNCONNECTED: |
137 - RTC_LOG(LS_INFO) << "PipeWire remote state: unconnected."; |
197 - RTC_LOG(LS_INFO) << "PipeWire remote state: unconnected."; |
138 + } else { |
198 - break; |
139 break; |
|
140 + } |
199 + } |
141 } |
200 } |
142 } |
201 } |
143 |
202 |
144 +// static |
203 // static |
145 +void BaseCapturerPipeWire::OnCoreError(void *data, |
204 +void BaseCapturerPipeWire::OnCoreError(void *data, |
146 + uint32_t id, |
205 + uint32_t id, |
147 + int seq, |
206 + int seq, |
148 + int res, |
207 + int res, |
149 + const char *message) { |
208 + const char *message) { |
150 + RTC_LOG(LS_ERROR) << "core error: " << message; |
209 + RTC_LOG(LS_ERROR) << "core error: " << message; |
151 +} |
210 +} |
152 + |
211 + |
153 // static |
212 +// static |
154 void BaseCapturerPipeWire::OnStreamStateChanged(void* data, |
213 void BaseCapturerPipeWire::OnStreamStateChanged(void* data, |
155 pw_stream_state old_state, |
214 pw_stream_state old_state, |
156 @@ -73,76 +81,54 @@ void BaseCapturerPipeWire::OnStreamStateChanged(void* data, |
215 pw_stream_state state, |
|
216 const char* error_message) { |
|
217 BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); |
|
218 RTC_DCHECK(that); |
|
219 |
|
220 switch (state) { |
157 case PW_STREAM_STATE_ERROR: |
221 case PW_STREAM_STATE_ERROR: |
158 RTC_LOG(LS_ERROR) << "PipeWire stream state error: " << error_message; |
222 RTC_LOG(LS_ERROR) << "PipeWire stream state error: " << error_message; |
159 break; |
223 break; |
160 - case PW_STREAM_STATE_CONFIGURE: |
224 - case PW_STREAM_STATE_CONFIGURE: |
161 - pw_stream_set_active(that->pw_stream_, true); |
225 - pw_stream_set_active(that->pw_stream_, true); |
162 - break; |
226 - break; |
163 - case PW_STREAM_STATE_UNCONNECTED: |
227 + case PW_STREAM_STATE_PAUSED: |
164 - case PW_STREAM_STATE_CONNECTING: |
228 + case PW_STREAM_STATE_STREAMING: |
|
229 case PW_STREAM_STATE_UNCONNECTED: |
|
230 case PW_STREAM_STATE_CONNECTING: |
165 - case PW_STREAM_STATE_READY: |
231 - case PW_STREAM_STATE_READY: |
166 case PW_STREAM_STATE_PAUSED: |
232 - case PW_STREAM_STATE_PAUSED: |
167 case PW_STREAM_STATE_STREAMING: |
233 - case PW_STREAM_STATE_STREAMING: |
168 + case PW_STREAM_STATE_UNCONNECTED: |
|
169 + case PW_STREAM_STATE_CONNECTING: |
|
170 break; |
234 break; |
171 } |
235 } |
172 } |
236 } |
173 |
237 |
174 // static |
238 // static |
254 + SPA_PARAM_META_size, SPA_POD_Int (sizeof(struct spa_meta_region)))); |
318 + SPA_PARAM_META_size, SPA_POD_Int (sizeof(struct spa_meta_region)))); |
255 + pw_stream_update_params(that->pw_stream_, params, 3); |
319 + pw_stream_update_params(that->pw_stream_, params, 3); |
256 } |
320 } |
257 |
321 |
258 // static |
322 // static |
259 @@ -150,15 +136,25 @@ void BaseCapturerPipeWire::OnStreamProcess(void* data) { |
323 void BaseCapturerPipeWire::OnStreamProcess(void* data) { |
260 BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); |
324 BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); |
261 RTC_DCHECK(that); |
325 RTC_DCHECK(that); |
262 |
326 |
263 - pw_buffer* buf = nullptr; |
327 - pw_buffer* buf = nullptr; |
264 + struct pw_buffer *next_buffer; |
328 + struct pw_buffer *next_buffer; |
265 + struct pw_buffer *buffer = nullptr; |
329 + struct pw_buffer *buffer = nullptr; |
266 + |
330 |
|
331 - if (!(buf = pw_stream_dequeue_buffer(that->pw_stream_))) { |
267 + next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); |
332 + next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); |
268 + while (next_buffer) { |
333 + while (next_buffer) { |
269 + buffer = next_buffer; |
334 + buffer = next_buffer; |
270 + next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); |
335 + next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); |
271 |
336 + |
272 - if (!(buf = pw_stream_dequeue_buffer(that->pw_stream_))) { |
|
273 + if (next_buffer) |
337 + if (next_buffer) |
274 + pw_stream_queue_buffer (that->pw_stream_, buffer); |
338 + pw_stream_queue_buffer (that->pw_stream_, buffer); |
275 + } |
339 + } |
276 + |
340 + |
277 + if (!buffer) { |
341 + if (!buffer) { |
327 - } |
394 - } |
328 - |
395 - |
329 if (start_request_signal_id_) { |
396 if (start_request_signal_id_) { |
330 g_dbus_connection_signal_unsubscribe(connection_, start_request_signal_id_); |
397 g_dbus_connection_signal_unsubscribe(connection_, start_request_signal_id_); |
331 } |
398 } |
332 @@ -250,27 +230,35 @@ void BaseCapturerPipeWire::InitPortal() { |
399 if (sources_request_signal_id_) { |
|
400 g_dbus_connection_signal_unsubscribe(connection_, |
|
401 sources_request_signal_id_); |
|
402 } |
|
403 if (session_request_signal_id_) { |
|
404 @@ -245,142 +225,220 @@ void BaseCapturerPipeWire::InitPortal() |
|
405 kDesktopBusName, kDesktopObjectPath, kScreenCastInterfaceName, |
|
406 /*cancellable=*/nullptr, |
|
407 reinterpret_cast<GAsyncReadyCallback>(OnProxyRequested), this); |
|
408 } |
|
409 |
333 void BaseCapturerPipeWire::InitPipeWire() { |
410 void BaseCapturerPipeWire::InitPipeWire() { |
334 pw_init(/*argc=*/nullptr, /*argc=*/nullptr); |
411 pw_init(/*argc=*/nullptr, /*argc=*/nullptr); |
335 |
412 |
336 - pw_loop_ = pw_loop_new(/*properties=*/nullptr); |
413 - pw_loop_ = pw_loop_new(/*properties=*/nullptr); |
337 - pw_main_loop_ = pw_thread_loop_new(pw_loop_, "pipewire-main-loop"); |
414 - pw_main_loop_ = pw_thread_loop_new(pw_loop_, "pipewire-main-loop"); |
338 - |
|
339 - pw_core_ = pw_core_new(pw_loop_, /*properties=*/nullptr); |
|
340 - pw_core_type_ = pw_core_get_type(pw_core_); |
|
341 - pw_remote_ = pw_remote_new(pw_core_, nullptr, /*user_data_size=*/0); |
|
342 + pw_main_loop_ = pw_thread_loop_new("pipewire-main-loop", nullptr); |
415 + pw_main_loop_ = pw_thread_loop_new("pipewire-main-loop", nullptr); |
343 + pw_context_ = pw_context_new(pw_thread_loop_get_loop(pw_main_loop_), nullptr, 0); |
416 + pw_context_ = pw_context_new(pw_thread_loop_get_loop(pw_main_loop_), nullptr, 0); |
344 + if (!pw_context_) { |
417 + if (!pw_context_) { |
345 + RTC_LOG(LS_ERROR) << "Failed to create PipeWire context"; |
418 + RTC_LOG(LS_ERROR) << "Failed to create PipeWire context"; |
346 + return; |
419 + return; |
347 + } |
420 + } |
348 |
421 |
|
422 - pw_core_ = pw_core_new(pw_loop_, /*properties=*/nullptr); |
|
423 - pw_core_type_ = pw_core_get_type(pw_core_); |
|
424 - pw_remote_ = pw_remote_new(pw_core_, nullptr, /*user_data_size=*/0); |
|
425 - |
349 - InitPipeWireTypes(); |
426 - InitPipeWireTypes(); |
350 + pw_core_ = pw_context_connect(pw_context_, nullptr, 0); |
427 + pw_core_ = pw_context_connect(pw_context_, nullptr, 0); |
351 + if (!pw_core_) { |
428 + if (!pw_core_) { |
352 + RTC_LOG(LS_ERROR) << "Failed to connect PipeWire context"; |
429 + RTC_LOG(LS_ERROR) << "Failed to connect PipeWire context"; |
353 + return; |
430 + return; |
389 - spa_type_media_type_map(map, &pw_type_->media_type); |
466 - spa_type_media_type_map(map, &pw_type_->media_type); |
390 - spa_type_media_subtype_map(map, &pw_type_->media_subtype); |
467 - spa_type_media_subtype_map(map, &pw_type_->media_subtype); |
391 - spa_type_format_video_map(map, &pw_type_->format_video); |
468 - spa_type_format_video_map(map, &pw_type_->format_video); |
392 - spa_type_video_format_map(map, &pw_type_->video_format); |
469 - spa_type_video_format_map(map, &pw_type_->video_format); |
393 -} |
470 -} |
394 - |
471 +pw_stream* BaseCapturerPipeWire::CreateReceivingStream() { |
|
472 + spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; |
|
473 + spa_rectangle pwMaxScreenBounds = spa_rectangle{INT32_MAX, INT32_MAX}; |
|
474 |
395 -void BaseCapturerPipeWire::CreateReceivingStream() { |
475 -void BaseCapturerPipeWire::CreateReceivingStream() { |
396 +pw_stream* BaseCapturerPipeWire::CreateReceivingStream() { |
476 - spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; |
397 spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; |
|
398 - spa_rectangle pwScreenBounds = |
477 - spa_rectangle pwScreenBounds = |
399 - spa_rectangle{static_cast<uint32_t>(desktop_size_.width()), |
478 - spa_rectangle{static_cast<uint32_t>(desktop_size_.width()), |
400 - static_cast<uint32_t>(desktop_size_.height())}; |
479 - static_cast<uint32_t>(desktop_size_.height())}; |
401 + spa_rectangle pwMaxScreenBounds = spa_rectangle{INT32_MAX, INT32_MAX}; |
480 + auto stream = pw_stream_new(pw_core_, "webrtc-pipewire-stream", nullptr); |
402 |
481 |
403 - spa_fraction pwFrameRateMin = spa_fraction{0, 1}; |
482 - spa_fraction pwFrameRateMin = spa_fraction{0, 1}; |
404 - spa_fraction pwFrameRateMax = spa_fraction{60, 1}; |
483 - spa_fraction pwFrameRateMax = spa_fraction{60, 1}; |
405 + auto stream = pw_stream_new(pw_core_, "webrtc-pipewire-stream", nullptr); |
484 - |
406 |
|
407 - pw_properties* reuseProps = pw_properties_new("pipewire.client.reuse", "1", |
485 - pw_properties* reuseProps = pw_properties_new("pipewire.client.reuse", "1", |
408 - /*end of varargs*/ nullptr); |
486 - /*end of varargs*/ nullptr); |
409 - pw_stream_ = pw_stream_new(pw_remote_, "webrtc-consume-stream", reuseProps); |
487 - pw_stream_ = pw_stream_new(pw_remote_, "webrtc-consume-stream", reuseProps); |
410 + if (!stream) { |
488 + if (!stream) { |
411 + RTC_LOG(LS_ERROR) << "Could not create receiving stream."; |
489 + RTC_LOG(LS_ERROR) << "Could not create receiving stream."; |
437 - // Max frame rate: specified as fraction (F), preferred frame rate is set |
515 - // Max frame rate: specified as fraction (F), preferred frame rate is set |
438 - // to maximum value, then allowed frame rate is defined as range (r) from |
516 - // to maximum value, then allowed frame rate is defined as range (r) from |
439 - // min and max values and it is undecided (u) to allow negotiation |
517 - // min and max values and it is undecided (u) to allow negotiation |
440 - ":", pw_type_->format_video.max_framerate, "Fru", &pwFrameRateMax, 2, |
518 - ":", pw_type_->format_video.max_framerate, "Fru", &pwFrameRateMax, 2, |
441 - &pwFrameRateMin, &pwFrameRateMax)); |
519 - &pwFrameRateMin, &pwFrameRateMax)); |
442 - |
520 + const spa_pod* params[2]; |
|
521 + spa_pod_builder builder = SPA_POD_BUILDER_INIT(buffer, sizeof (buffer)); |
|
522 |
443 - pw_stream_add_listener(pw_stream_, &spa_stream_listener_, &pw_stream_events_, |
523 - pw_stream_add_listener(pw_stream_, &spa_stream_listener_, &pw_stream_events_, |
444 - this); |
524 - this); |
445 + const spa_pod* params[2]; |
|
446 + spa_pod_builder builder = SPA_POD_BUILDER_INIT(buffer, sizeof (buffer)); |
|
447 + |
|
448 + params[0] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder, |
525 + params[0] = reinterpret_cast<spa_pod *>(spa_pod_builder_add_object(&builder, |
449 + SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, |
526 + SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, |
450 + SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), |
527 + SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), |
451 + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), |
528 + SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), |
452 + SPA_FORMAT_VIDEO_format, SPA_POD_CHOICE_ENUM_Id(5, SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx, SPA_VIDEO_FORMAT_RGBA, |
529 + SPA_FORMAT_VIDEO_format, SPA_POD_CHOICE_ENUM_Id(5, SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx, SPA_VIDEO_FORMAT_RGBA, |
492 + |
569 + |
493 + if (map == MAP_FAILED) { |
570 + if (map == MAP_FAILED) { |
494 + RTC_LOG(LS_ERROR) << "Failed to mmap the memory: " << std::strerror(errno); |
571 + RTC_LOG(LS_ERROR) << "Failed to mmap the memory: " << std::strerror(errno); |
495 + return; |
572 + return; |
496 + } |
573 + } |
497 + |
574 |
|
575 - if (!(src = spaBuffer->datas[0].data)) { |
498 + src = SPA_MEMBER(map, spaBuffer->datas[0].mapoffset, uint8_t); |
576 + src = SPA_MEMBER(map, spaBuffer->datas[0].mapoffset, uint8_t); |
499 + } else if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf) { |
577 + } else if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf) { |
500 + int fd; |
578 + int fd; |
501 + fd = spaBuffer->datas[0].fd; |
579 + fd = spaBuffer->datas[0].fd; |
502 |
580 + |
503 - if (!(src = spaBuffer->datas[0].data)) { |
|
504 + map = static_cast<uint8_t*>(mmap( |
581 + map = static_cast<uint8_t*>(mmap( |
505 + nullptr, spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, |
582 + nullptr, spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, |
506 + PROT_READ, MAP_PRIVATE, fd, 0)); |
583 + PROT_READ, MAP_PRIVATE, fd, 0)); |
507 + |
584 + |
508 + if (map == MAP_FAILED) { |
585 + if (map == MAP_FAILED) { |
567 + const int32_t srcStride = spaBuffer->datas[0].chunk->stride; |
644 + const int32_t srcStride = spaBuffer->datas[0].chunk->stride; |
568 + |
645 + |
569 if (srcStride != (desktop_size_.width() * kBytesPerPixel)) { |
646 if (srcStride != (desktop_size_.width() * kBytesPerPixel)) { |
570 RTC_LOG(LS_ERROR) << "Got buffer with stride different from screen stride: " |
647 RTC_LOG(LS_ERROR) << "Got buffer with stride different from screen stride: " |
571 << srcStride |
648 << srcStride |
572 @@ -361,21 +400,40 @@ void BaseCapturerPipeWire::HandleBuffer(pw_buffer* buffer) { |
649 << " != " << (desktop_size_.width() * kBytesPerPixel); |
|
650 portal_init_failed_ = true; |
573 return; |
651 return; |
574 } |
652 } |
575 |
653 |
576 - if (!current_frame_) { |
654 - if (!current_frame_) { |
577 - current_frame_ = static_cast<uint8_t*>(malloc(maxSize)); |
655 - current_frame_ = static_cast<uint8_t*>(malloc(maxSize)); |
|
656 - } |
|
657 - RTC_DCHECK(current_frame_ != nullptr); |
578 + dst = current_frame_.get(); |
658 + dst = current_frame_.get(); |
579 + |
659 |
|
660 - // If both sides decided to go with the RGBx format we need to convert it to |
|
661 - // BGRx to match color format expected by WebRTC. |
|
662 - if (spa_video_format_->format == pw_type_->video_format.RGBx) { |
|
663 - uint8_t* tempFrame = static_cast<uint8_t*>(malloc(maxSize)); |
|
664 - std::memcpy(tempFrame, src, maxSize); |
|
665 - ConvertRGBxToBGRx(tempFrame, maxSize); |
|
666 - std::memcpy(current_frame_, tempFrame, maxSize); |
|
667 - free(tempFrame); |
|
668 - } else { |
|
669 - std::memcpy(current_frame_, src, maxSize); |
580 + // Adjust source content based on crop video position |
670 + // Adjust source content based on crop video position |
581 + if (video_crop_size_initialized_ && |
671 + if (video_crop_size_initialized_ && |
582 + (video_crop->region.position.y + video_crop_size_.height() <= desktop_size_.height())) { |
672 + (video_crop->region.position.y + video_crop_size_.height() <= desktop_size_.height())) { |
583 + for (int i = 0; i < video_crop->region.position.y; ++i) { |
673 + for (int i = 0; i < video_crop->region.position.y; ++i) { |
584 + src += srcStride; |
674 + src += srcStride; |
600 + spa_video_format_.format == SPA_VIDEO_FORMAT_RGBA) { |
690 + spa_video_format_.format == SPA_VIDEO_FORMAT_RGBA) { |
601 + ConvertRGBxToBGRx(dst, dstStride); |
691 + ConvertRGBxToBGRx(dst, dstStride); |
602 + } |
692 + } |
603 + src += srcStride - xOffset; |
693 + src += srcStride - xOffset; |
604 + dst += dstStride; |
694 + dst += dstStride; |
605 } |
695 + } |
606 - RTC_DCHECK(current_frame_ != nullptr); |
696 + |
607 |
|
608 - // If both sides decided to go with the RGBx format we need to convert it to |
|
609 - // BGRx to match color format expected by WebRTC. |
|
610 - if (spa_video_format_->format == pw_type_->video_format.RGBx) { |
|
611 - uint8_t* tempFrame = static_cast<uint8_t*>(malloc(maxSize)); |
|
612 - std::memcpy(tempFrame, src, maxSize); |
|
613 - ConvertRGBxToBGRx(tempFrame, maxSize); |
|
614 - std::memcpy(current_frame_, tempFrame, maxSize); |
|
615 - free(tempFrame); |
|
616 - } else { |
|
617 - std::memcpy(current_frame_, src, maxSize); |
|
618 + if (map) { |
697 + if (map) { |
619 + if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf) { |
698 + if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf) { |
620 + SyncDmaBuf(spaBuffer->datas[0].fd, DMA_BUF_SYNC_END); |
699 + SyncDmaBuf(spaBuffer->datas[0].fd, DMA_BUF_SYNC_END); |
621 + } |
700 + } |
622 + munmap(map, spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset); |
701 + munmap(map, spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset); |
623 } |
702 } |
624 } |
703 } |
625 |
704 |
626 @@ -725,10 +783,7 @@ void BaseCapturerPipeWire::OnStartRequestResponseSignal( |
705 void BaseCapturerPipeWire::ConvertRGBxToBGRx(uint8_t* frame, uint32_t size) { |
|
706 // Change color format for KDE KWin which uses RGBx and not BGRx |
|
707 for (uint32_t i = 0; i < size; i += 4) { |
|
708 uint8_t tempR = frame[i]; |
|
709 uint8_t tempB = frame[i + 2]; |
|
710 @@ -720,20 +778,17 @@ void BaseCapturerPipeWire::OnStartReques |
|
711 guint32 stream_id; |
|
712 gint32 width; |
|
713 gint32 height; |
|
714 GVariant* options; |
|
715 |
627 g_variant_get(variant, "(u@a{sv})", &stream_id, &options); |
716 g_variant_get(variant, "(u@a{sv})", &stream_id, &options); |
628 RTC_DCHECK(options != nullptr); |
717 RTC_DCHECK(options != nullptr); |
629 |
718 |
630 - g_variant_lookup(options, "size", "(ii)", &width, &height); |
719 - g_variant_lookup(options, "size", "(ii)", &width, &height); |
631 - |
720 - |
790 - |
912 - |
791 - static void OnStreamFormatChanged(void* data, const struct spa_pod* format); |
913 - static void OnStreamFormatChanged(void* data, const struct spa_pod* format); |
792 static void OnStreamProcess(void* data); |
914 static void OnStreamProcess(void* data); |
793 static void OnNewBuffer(void* data, uint32_t id); |
915 static void OnNewBuffer(void* data, uint32_t id); |
794 |
916 |
|
917 guint SetupRequestResponseSignal(const gchar* object_path, |
|
918 GDBusSignalCallback callback); |
|
919 |
|
920 static void OnProxyRequested(GObject* object, |
|
921 GAsyncResult* result, |
795 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc |
922 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc |
796 index 26956fc67dc8..3813d697bb38 100644 |
|
797 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc |
923 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc |
798 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc |
924 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc |
799 @@ -15,7 +15,7 @@ |
925 @@ -10,17 +10,17 @@ |
|
926 |
|
927 #include "modules/desktop_capture/linux/screen_capturer_pipewire.h" |
|
928 |
|
929 #include <memory> |
|
930 |
800 namespace webrtc { |
931 namespace webrtc { |
801 |
932 |
802 ScreenCapturerPipeWire::ScreenCapturerPipeWire() |
933 ScreenCapturerPipeWire::ScreenCapturerPipeWire() |
803 - : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Screen) {} |
934 - : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Screen) {} |
804 + : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::kScreen) {} |
935 + : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::kScreen) {} |
805 ScreenCapturerPipeWire::~ScreenCapturerPipeWire() {} |
936 ScreenCapturerPipeWire::~ScreenCapturerPipeWire() {} |
806 |
937 |
807 // static |
938 // static |
|
939 std::unique_ptr<DesktopCapturer> |
|
940 ScreenCapturerPipeWire::CreateRawScreenCapturer( |
|
941 const DesktopCaptureOptions& options) { |
|
942 return std::make_unique<ScreenCapturerPipeWire>(); |
|
943 } |
808 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc |
944 diff --git a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc |
809 index 35436475cb4d..c43a1f1a0c4e 100644 |
|
810 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc |
945 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc |
811 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc |
946 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc |
812 @@ -15,7 +15,7 @@ |
947 @@ -10,17 +10,17 @@ |
|
948 |
|
949 #include "modules/desktop_capture/linux/window_capturer_pipewire.h" |
|
950 |
|
951 #include <memory> |
|
952 |
813 namespace webrtc { |
953 namespace webrtc { |
814 |
954 |
815 WindowCapturerPipeWire::WindowCapturerPipeWire() |
955 WindowCapturerPipeWire::WindowCapturerPipeWire() |
816 - : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Window) {} |
956 - : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Window) {} |
817 + : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::kWindow) {} |
957 + : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::kWindow) {} |
818 WindowCapturerPipeWire::~WindowCapturerPipeWire() {} |
958 WindowCapturerPipeWire::~WindowCapturerPipeWire() {} |
819 |
959 |
820 // static |
960 // static |
|
961 std::unique_ptr<DesktopCapturer> |
|
962 WindowCapturerPipeWire::CreateRawWindowCapturer( |
|
963 const DesktopCaptureOptions& options) { |
|
964 return std::make_unique<WindowCapturerPipeWire>(); |
|
965 } |
821 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 |
966 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 |
822 index cf8a9dd0e0db..d27fab8d28d9 100644 |
|
823 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc |
967 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc |
824 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc |
968 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/screen_capturer_linux.cc |
825 @@ -26,7 +26,7 @@ std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawScreenCapturer( |
969 @@ -21,17 +21,17 @@ |
|
970 |
|
971 namespace webrtc { |
|
972 |
|
973 // static |
|
974 std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawScreenCapturer( |
826 const DesktopCaptureOptions& options) { |
975 const DesktopCaptureOptions& options) { |
827 #if defined(WEBRTC_USE_PIPEWIRE) |
976 #if defined(WEBRTC_USE_PIPEWIRE) |
828 if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { |
977 if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { |
829 - return ScreenCapturerPipeWire::CreateRawScreenCapturer(options); |
978 - return ScreenCapturerPipeWire::CreateRawScreenCapturer(options); |
830 + return BaseCapturerPipeWire::CreateRawScreenCapturer(options); |
979 + return BaseCapturerPipeWire::CreateRawScreenCapturer(options); |
831 } |
980 } |
832 #endif // defined(WEBRTC_USE_PIPEWIRE) |
981 #endif // defined(WEBRTC_USE_PIPEWIRE) |
833 |
982 |
|
983 #if defined(USE_X11) |
|
984 return ScreenCapturerX11::CreateRawScreenCapturer(options); |
|
985 #endif // defined(USE_X11) |
|
986 |
|
987 return nullptr; |
834 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 |
988 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 |
835 index 82359e50c2db..bb9724cf7cc2 100644 |
|
836 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc |
989 --- a/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc |
837 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc |
990 +++ b/media/webrtc/trunk/webrtc/modules/desktop_capture/window_capturer_linux.cc |
838 @@ -26,7 +26,7 @@ std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer( |
991 @@ -21,17 +21,17 @@ |
|
992 |
|
993 namespace webrtc { |
|
994 |
|
995 // static |
|
996 std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer( |
839 const DesktopCaptureOptions& options) { |
997 const DesktopCaptureOptions& options) { |
840 #if defined(WEBRTC_USE_PIPEWIRE) |
998 #if defined(WEBRTC_USE_PIPEWIRE) |
841 if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { |
999 if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { |
842 - return WindowCapturerPipeWire::CreateRawWindowCapturer(options); |
1000 - return WindowCapturerPipeWire::CreateRawWindowCapturer(options); |
843 + return BaseCapturerPipeWire::CreateRawWindowCapturer(options); |
1001 + return BaseCapturerPipeWire::CreateRawWindowCapturer(options); |
844 } |
1002 } |
845 #endif // defined(WEBRTC_USE_PIPEWIRE) |
1003 #endif // defined(WEBRTC_USE_PIPEWIRE) |
846 |
1004 |
|
1005 #if defined(USE_X11) |
|
1006 return WindowCapturerX11::CreateRawWindowCapturer(options); |
|
1007 #endif // defined(USE_X11) |
|
1008 |
|
1009 return nullptr; |