1 |
Fix build with pipewire 0.3 |
2 |
Origin: ArchLinux, https://github.com/archlinux/svntogit-packages/tree/packages/qt5-webengine/trunk |
3 |
|
4 |
--- |
5 |
.../webrtc/modules/desktop_capture/BUILD.gn | 42 +- |
6 |
.../linux/base_capturer_pipewire.cc | 770 ++++++++++++++---- |
7 |
.../linux/base_capturer_pipewire.h | 58 +- |
8 |
.../linux/{pipewire.sigs => pipewire02.sigs} | 3 + |
9 |
.../desktop_capture/linux/pipewire03.sigs | 46 ++ |
10 |
.../linux/screen_capturer_pipewire.cc | 29 - |
11 |
.../linux/screen_capturer_pipewire.h | 33 - |
12 |
.../linux/window_capturer_pipewire.cc | 29 - |
13 |
.../linux/window_capturer_pipewire.h | 33 - |
14 |
.../desktop_capture/screen_capturer_linux.cc | 4 +- |
15 |
.../desktop_capture/window_capturer_linux.cc | 4 +- |
16 |
.../chromium/third_party/webrtc/webrtc.gni | 4 + |
17 |
12 files changed, 750 insertions(+), 305 deletions(-) |
18 |
rename src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/{pipewire.sigs => pipewire02.sigs} (91%) |
19 |
create mode 100644 src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire03.sigs |
20 |
delete mode 100644 src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc |
21 |
delete mode 100644 src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.h |
22 |
delete mode 100644 src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc |
23 |
delete mode 100644 src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.h |
24 |
|
25 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/BUILD.gn b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/BUILD.gn |
26 |
index 5235512..8259442 100644 |
27 |
--- a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/BUILD.gn |
28 |
+++ b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/BUILD.gn |
29 |
@@ -11,6 +11,11 @@ import("//build/config/ui.gni") |
30 |
import("//tools/generate_stubs/rules.gni") |
31 |
import("../../webrtc.gni") |
32 |
|
33 |
+if (rtc_use_pipewire) { |
34 |
+ assert(rtc_pipewire_version == "0.2" || rtc_pipewire_version == "0.3", |
35 |
+ "Unsupported PipeWire version") |
36 |
+} |
37 |
+ |
38 |
use_desktop_capture_differ_sse2 = current_cpu == "x86" || current_cpu == "x64" |
39 |
|
40 |
config("x11_config") { |
41 |
@@ -200,22 +205,41 @@ if (is_linux || is_chromeos) { |
42 |
] |
43 |
} |
44 |
|
45 |
- if (rtc_link_pipewire) { |
46 |
+ if (rtc_pipewire_version == "0.3") { |
47 |
pkg_config("pipewire") { |
48 |
- packages = [ "libpipewire-0.2" ] |
49 |
+ packages = [ "libpipewire-0.3" ] |
50 |
+ if (!rtc_link_pipewire) { |
51 |
+ ignore_libs = true |
52 |
+ } |
53 |
} |
54 |
} else { |
55 |
+ pkg_config("pipewire") { |
56 |
+ packages = [ "libpipewire-0.2" ] |
57 |
+ if (!rtc_link_pipewire) { |
58 |
+ ignore_libs = true |
59 |
+ } |
60 |
+ } |
61 |
+ } |
62 |
+ |
63 |
+ if (!rtc_link_pipewire) { |
64 |
# When libpipewire is not directly linked, use stubs to allow for dlopening of |
65 |
# the binary. |
66 |
generate_stubs("pipewire_stubs") { |
67 |
- configs = [ "../../:common_config" ] |
68 |
+ configs = [ |
69 |
+ "../../:common_config", |
70 |
+ ":pipewire", |
71 |
+ ] |
72 |
deps = [ "../../rtc_base" ] |
73 |
extra_header = "linux/pipewire_stub_header.fragment" |
74 |
logging_function = "RTC_LOG(LS_VERBOSE)" |
75 |
logging_include = "rtc_base/logging.h" |
76 |
output_name = "linux/pipewire_stubs" |
77 |
path_from_source = "modules/desktop_capture/linux" |
78 |
- sigs = [ "linux/pipewire.sigs" ] |
79 |
+ if (rtc_pipewire_version == "0.3") { |
80 |
+ sigs = [ "linux/pipewire03.sigs" ] |
81 |
+ } else { |
82 |
+ sigs = [ "linux/pipewire02.sigs" ] |
83 |
+ } |
84 |
} |
85 |
} |
86 |
|
87 |
@@ -506,6 +530,7 @@ rtc_library("desktop_capture_generic") { |
88 |
absl_deps = [ |
89 |
"//third_party/abseil-cpp/absl/memory", |
90 |
"//third_party/abseil-cpp/absl/strings", |
91 |
+ "//third_party/abseil-cpp/absl/types:optional", |
92 |
] |
93 |
|
94 |
if (rtc_use_x11_extensions) { |
95 |
@@ -526,20 +551,15 @@ rtc_library("desktop_capture_generic") { |
96 |
sources += [ |
97 |
"linux/base_capturer_pipewire.cc", |
98 |
"linux/base_capturer_pipewire.h", |
99 |
- "linux/screen_capturer_pipewire.cc", |
100 |
- "linux/screen_capturer_pipewire.h", |
101 |
- "linux/window_capturer_pipewire.cc", |
102 |
- "linux/window_capturer_pipewire.h", |
103 |
] |
104 |
|
105 |
configs += [ |
106 |
":pipewire_config", |
107 |
":gio", |
108 |
+ ":pipewire", |
109 |
] |
110 |
|
111 |
- if (rtc_link_pipewire) { |
112 |
- configs += [ ":pipewire" ] |
113 |
- } else { |
114 |
+ if (!rtc_link_pipewire) { |
115 |
deps += [ ":pipewire_stubs" ] |
116 |
} |
117 |
} |
118 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc |
119 |
index 2640e93..c302a08 100644 |
120 |
--- a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc |
121 |
+++ b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc |
122 |
@@ -14,8 +14,14 @@ |
123 |
#include <glib-object.h> |
124 |
#include <spa/param/format-utils.h> |
125 |
#include <spa/param/props.h> |
126 |
+#if !PW_CHECK_VERSION(0, 3, 0) |
127 |
#include <spa/param/video/raw-utils.h> |
128 |
#include <spa/support/type-map.h> |
129 |
+#endif |
130 |
+ |
131 |
+#include <sys/ioctl.h> |
132 |
+#include <sys/mman.h> |
133 |
+#include <sys/syscall.h> |
134 |
|
135 |
#include <memory> |
136 |
#include <utility> |
137 |
@@ -30,7 +36,11 @@ |
138 |
#include "modules/desktop_capture/linux/pipewire_stubs.h" |
139 |
|
140 |
using modules_desktop_capture_linux::InitializeStubs; |
141 |
-using modules_desktop_capture_linux::kModulePipewire; |
142 |
+#if PW_CHECK_VERSION(0, 3, 0) |
143 |
+using modules_desktop_capture_linux::kModulePipewire03; |
144 |
+#else |
145 |
+using modules_desktop_capture_linux::kModulePipewire02; |
146 |
+#endif |
147 |
using modules_desktop_capture_linux::StubPathMap; |
148 |
#endif // defined(WEBRTC_DLOPEN_PIPEWIRE) |
149 |
|
150 |
@@ -47,9 +57,156 @@ const char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast"; |
151 |
const int kBytesPerPixel = 4; |
152 |
|
153 |
#if defined(WEBRTC_DLOPEN_PIPEWIRE) |
154 |
+#if PW_CHECK_VERSION(0, 3, 0) |
155 |
+const char kPipeWireLib[] = "libpipewire-0.3.so.0"; |
156 |
+#else |
157 |
const char kPipeWireLib[] = "libpipewire-0.2.so.1"; |
158 |
#endif |
159 |
+#endif |
160 |
|
161 |
+// static |
162 |
+struct dma_buf_sync { |
163 |
+ uint64_t flags; |
164 |
+}; |
165 |
+#define DMA_BUF_SYNC_READ (1 << 0) |
166 |
+#define DMA_BUF_SYNC_START (0 << 2) |
167 |
+#define DMA_BUF_SYNC_END (1 << 2) |
168 |
+#define DMA_BUF_BASE 'b' |
169 |
+#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) |
170 |
+ |
171 |
+static void SyncDmaBuf(int fd, uint64_t start_or_end) { |
172 |
+ struct dma_buf_sync sync = {0}; |
173 |
+ |
174 |
+ sync.flags = start_or_end | DMA_BUF_SYNC_READ; |
175 |
+ |
176 |
+ while (true) { |
177 |
+ int ret; |
178 |
+ ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync); |
179 |
+ if (ret == -1 && errno == EINTR) { |
180 |
+ continue; |
181 |
+ } else if (ret == -1) { |
182 |
+ RTC_LOG(LS_ERROR) << "Failed to synchronize DMA buffer: " |
183 |
+ << g_strerror(errno); |
184 |
+ break; |
185 |
+ } else { |
186 |
+ break; |
187 |
+ } |
188 |
+ } |
189 |
+} |
190 |
+ |
191 |
+class ScopedBuf { |
192 |
+ public: |
193 |
+ ScopedBuf() {} |
194 |
+ ScopedBuf(unsigned char* map, int map_size, bool is_dma_buf, int fd) |
195 |
+ : map_(map), map_size_(map_size), is_dma_buf_(is_dma_buf), fd_(fd) {} |
196 |
+ ~ScopedBuf() { |
197 |
+ if (map_ != MAP_FAILED) { |
198 |
+ if (is_dma_buf_) { |
199 |
+ SyncDmaBuf(fd_, DMA_BUF_SYNC_END); |
200 |
+ } |
201 |
+ munmap(map_, map_size_); |
202 |
+ } |
203 |
+ } |
204 |
+ |
205 |
+ operator bool() { return map_ != MAP_FAILED; } |
206 |
+ |
207 |
+ void initialize(unsigned char* map, int map_size, bool is_dma_buf, int fd) { |
208 |
+ map_ = map; |
209 |
+ map_size_ = map_size; |
210 |
+ is_dma_buf_ = is_dma_buf; |
211 |
+ fd_ = fd; |
212 |
+ } |
213 |
+ |
214 |
+ unsigned char* get() { return map_; } |
215 |
+ |
216 |
+ protected: |
217 |
+ unsigned char* map_ = nullptr; |
218 |
+ int map_size_; |
219 |
+ bool is_dma_buf_; |
220 |
+ int fd_; |
221 |
+}; |
222 |
+ |
223 |
+template <class T> |
224 |
+class Scoped { |
225 |
+ public: |
226 |
+ Scoped() {} |
227 |
+ explicit Scoped(T* val) { ptr_ = val; } |
228 |
+ ~Scoped() { RTC_NOTREACHED(); } |
229 |
+ |
230 |
+ T* operator->() { return ptr_; } |
231 |
+ |
232 |
+ bool operator!() { return ptr_ == nullptr; } |
233 |
+ |
234 |
+ T* get() { return ptr_; } |
235 |
+ |
236 |
+ T** receive() { |
237 |
+ RTC_CHECK(!ptr_); |
238 |
+ return &ptr_; |
239 |
+ } |
240 |
+ |
241 |
+ Scoped& operator=(T* val) { |
242 |
+ ptr_ = val; |
243 |
+ return *this; |
244 |
+ } |
245 |
+ |
246 |
+ protected: |
247 |
+ T* ptr_ = nullptr; |
248 |
+}; |
249 |
+ |
250 |
+template <> |
251 |
+Scoped<GError>::~Scoped() { |
252 |
+ if (ptr_) { |
253 |
+ g_error_free(ptr_); |
254 |
+ } |
255 |
+} |
256 |
+ |
257 |
+template <> |
258 |
+Scoped<gchar>::~Scoped() { |
259 |
+ if (ptr_) { |
260 |
+ g_free(ptr_); |
261 |
+ } |
262 |
+} |
263 |
+ |
264 |
+template <> |
265 |
+Scoped<GVariant>::~Scoped() { |
266 |
+ if (ptr_) { |
267 |
+ g_variant_unref(ptr_); |
268 |
+ } |
269 |
+} |
270 |
+ |
271 |
+template <> |
272 |
+Scoped<GVariantIter>::~Scoped() { |
273 |
+ if (ptr_) { |
274 |
+ g_variant_iter_free(ptr_); |
275 |
+ } |
276 |
+} |
277 |
+ |
278 |
+template <> |
279 |
+Scoped<GDBusMessage>::~Scoped() { |
280 |
+ if (ptr_) { |
281 |
+ g_object_unref(ptr_); |
282 |
+ } |
283 |
+} |
284 |
+ |
285 |
+template <> |
286 |
+Scoped<GUnixFDList>::~Scoped() { |
287 |
+ if (ptr_) { |
288 |
+ g_object_unref(ptr_); |
289 |
+ } |
290 |
+} |
291 |
+ |
292 |
+#if PW_CHECK_VERSION(0, 3, 0) |
293 |
+void BaseCapturerPipeWire::OnCoreError(void* data, |
294 |
+ uint32_t id, |
295 |
+ int seq, |
296 |
+ int res, |
297 |
+ const char* message) { |
298 |
+ BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); |
299 |
+ RTC_DCHECK(that); |
300 |
+ |
301 |
+ RTC_LOG(LS_ERROR) << "PipeWire remote error: " << message; |
302 |
+} |
303 |
+#else |
304 |
// static |
305 |
void BaseCapturerPipeWire::OnStateChanged(void* data, |
306 |
pw_remote_state old_state, |
307 |
@@ -64,7 +221,7 @@ void BaseCapturerPipeWire::OnStateChanged(void* data, |
308 |
break; |
309 |
case PW_REMOTE_STATE_CONNECTED: |
310 |
RTC_LOG(LS_INFO) << "PipeWire remote state: connected."; |
311 |
- that->CreateReceivingStream(); |
312 |
+ that->pw_stream_ = that->CreateReceivingStream(); |
313 |
break; |
314 |
case PW_REMOTE_STATE_CONNECTING: |
315 |
RTC_LOG(LS_INFO) << "PipeWire remote state: connecting."; |
316 |
@@ -74,6 +231,7 @@ void BaseCapturerPipeWire::OnStateChanged(void* data, |
317 |
break; |
318 |
} |
319 |
} |
320 |
+#endif |
321 |
|
322 |
// static |
323 |
void BaseCapturerPipeWire::OnStreamStateChanged(void* data, |
324 |
@@ -83,6 +241,18 @@ void BaseCapturerPipeWire::OnStreamStateChanged(void* data, |
325 |
BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); |
326 |
RTC_DCHECK(that); |
327 |
|
328 |
+#if PW_CHECK_VERSION(0, 3, 0) |
329 |
+ switch (state) { |
330 |
+ case PW_STREAM_STATE_ERROR: |
331 |
+ RTC_LOG(LS_ERROR) << "PipeWire stream state error: " << error_message; |
332 |
+ break; |
333 |
+ case PW_STREAM_STATE_PAUSED: |
334 |
+ case PW_STREAM_STATE_STREAMING: |
335 |
+ case PW_STREAM_STATE_UNCONNECTED: |
336 |
+ case PW_STREAM_STATE_CONNECTING: |
337 |
+ break; |
338 |
+ } |
339 |
+#else |
340 |
switch (state) { |
341 |
case PW_STREAM_STATE_ERROR: |
342 |
RTC_LOG(LS_ERROR) << "PipeWire stream state error: " << error_message; |
343 |
@@ -97,36 +267,74 @@ void BaseCapturerPipeWire::OnStreamStateChanged(void* data, |
344 |
case PW_STREAM_STATE_STREAMING: |
345 |
break; |
346 |
} |
347 |
+#endif |
348 |
} |
349 |
|
350 |
// static |
351 |
+#if PW_CHECK_VERSION(0, 3, 0) |
352 |
+void BaseCapturerPipeWire::OnStreamParamChanged(void* data, |
353 |
+ uint32_t id, |
354 |
+ const struct spa_pod* format) { |
355 |
+#else |
356 |
void BaseCapturerPipeWire::OnStreamFormatChanged(void* data, |
357 |
const struct spa_pod* format) { |
358 |
+#endif |
359 |
BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); |
360 |
RTC_DCHECK(that); |
361 |
|
362 |
RTC_LOG(LS_INFO) << "PipeWire stream format changed."; |
363 |
|
364 |
+#if PW_CHECK_VERSION(0, 3, 0) |
365 |
+ if (!format || id != SPA_PARAM_Format) { |
366 |
+#else |
367 |
if (!format) { |
368 |
pw_stream_finish_format(that->pw_stream_, /*res=*/0, /*params=*/nullptr, |
369 |
/*n_params=*/0); |
370 |
+#endif |
371 |
return; |
372 |
} |
373 |
|
374 |
+#if PW_CHECK_VERSION(0, 3, 0) |
375 |
+ spa_format_video_raw_parse(format, &that->spa_video_format_); |
376 |
+#else |
377 |
that->spa_video_format_ = new spa_video_info_raw(); |
378 |
spa_format_video_raw_parse(format, that->spa_video_format_, |
379 |
&that->pw_type_->format_video); |
380 |
+#endif |
381 |
|
382 |
+#if PW_CHECK_VERSION(0, 3, 0) |
383 |
+ auto width = that->spa_video_format_.size.width; |
384 |
+ auto height = that->spa_video_format_.size.height; |
385 |
+#else |
386 |
auto width = that->spa_video_format_->size.width; |
387 |
auto height = that->spa_video_format_->size.height; |
388 |
+#endif |
389 |
auto stride = SPA_ROUND_UP_N(width * kBytesPerPixel, 4); |
390 |
auto size = height * stride; |
391 |
|
392 |
+ that->desktop_size_ = DesktopSize(width, height); |
393 |
+ |
394 |
uint8_t buffer[1024] = {}; |
395 |
auto builder = spa_pod_builder{buffer, sizeof(buffer)}; |
396 |
|
397 |
// Setup buffers and meta header for new format. |
398 |
- const struct spa_pod* params[2]; |
399 |
+ const struct spa_pod* params[3]; |
400 |
+#if PW_CHECK_VERSION(0, 3, 0) |
401 |
+ params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_add_object( |
402 |
+ &builder, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, |
403 |
+ SPA_PARAM_BUFFERS_size, SPA_POD_Int(size), SPA_PARAM_BUFFERS_stride, |
404 |
+ SPA_POD_Int(stride), SPA_PARAM_BUFFERS_buffers, |
405 |
+ SPA_POD_CHOICE_RANGE_Int(8, 1, 32))); |
406 |
+ params[1] = reinterpret_cast<spa_pod*>(spa_pod_builder_add_object( |
407 |
+ &builder, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, |
408 |
+ SPA_POD_Id(SPA_META_Header), SPA_PARAM_META_size, |
409 |
+ SPA_POD_Int(sizeof(struct spa_meta_header)))); |
410 |
+ params[2] = reinterpret_cast<spa_pod*>(spa_pod_builder_add_object( |
411 |
+ &builder, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, |
412 |
+ SPA_POD_Id(SPA_META_VideoCrop), SPA_PARAM_META_size, |
413 |
+ SPA_POD_Int(sizeof(struct spa_meta_region)))); |
414 |
+ pw_stream_update_params(that->pw_stream_, params, 3); |
415 |
+#else |
416 |
params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_object( |
417 |
&builder, |
418 |
// id to enumerate buffer requirements |
419 |
@@ -155,8 +363,18 @@ void BaseCapturerPipeWire::OnStreamFormatChanged(void* data, |
420 |
// Size: size of the metadata, specified as integer (i) |
421 |
":", that->pw_core_type_->param_meta.size, "i", |
422 |
sizeof(struct spa_meta_header))); |
423 |
- |
424 |
- pw_stream_finish_format(that->pw_stream_, /*res=*/0, params, /*n_params=*/2); |
425 |
+ params[2] = reinterpret_cast<spa_pod*>(spa_pod_builder_object( |
426 |
+ &builder, |
427 |
+ // id to enumerate supported metadata |
428 |
+ that->pw_core_type_->param.idMeta, that->pw_core_type_->param_meta.Meta, |
429 |
+ // Type: specified as id or enum (I) |
430 |
+ ":", that->pw_core_type_->param_meta.type, "I", |
431 |
+ that->pw_core_type_->meta.VideoCrop, |
432 |
+ // Size: size of the metadata, specified as integer (i) |
433 |
+ ":", that->pw_core_type_->param_meta.size, "i", |
434 |
+ sizeof(struct spa_meta_video_crop))); |
435 |
+ pw_stream_finish_format(that->pw_stream_, /*res=*/0, params, /*n_params=*/3); |
436 |
+#endif |
437 |
} |
438 |
|
439 |
// static |
440 |
@@ -164,15 +382,26 @@ void BaseCapturerPipeWire::OnStreamProcess(void* data) { |
441 |
BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); |
442 |
RTC_DCHECK(that); |
443 |
|
444 |
- pw_buffer* buf = nullptr; |
445 |
+ struct pw_buffer* next_buffer; |
446 |
+ struct pw_buffer* buffer = nullptr; |
447 |
+ |
448 |
+ next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); |
449 |
+ while (next_buffer) { |
450 |
+ buffer = next_buffer; |
451 |
+ next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); |
452 |
|
453 |
- if (!(buf = pw_stream_dequeue_buffer(that->pw_stream_))) { |
454 |
+ if (next_buffer) { |
455 |
+ pw_stream_queue_buffer(that->pw_stream_, buffer); |
456 |
+ } |
457 |
+ } |
458 |
+ |
459 |
+ if (!buffer) { |
460 |
return; |
461 |
} |
462 |
|
463 |
- that->HandleBuffer(buf); |
464 |
+ that->HandleBuffer(buffer); |
465 |
|
466 |
- pw_stream_queue_buffer(that->pw_stream_, buf); |
467 |
+ pw_stream_queue_buffer(that->pw_stream_, buffer); |
468 |
} |
469 |
|
470 |
BaseCapturerPipeWire::BaseCapturerPipeWire(CaptureSourceType source_type) |
471 |
@@ -183,6 +412,7 @@ BaseCapturerPipeWire::~BaseCapturerPipeWire() { |
472 |
pw_thread_loop_stop(pw_main_loop_); |
473 |
} |
474 |
|
475 |
+#if !PW_CHECK_VERSION(0, 3, 0) |
476 |
if (pw_type_) { |
477 |
delete pw_type_; |
478 |
} |
479 |
@@ -190,30 +420,41 @@ BaseCapturerPipeWire::~BaseCapturerPipeWire() { |
480 |
if (spa_video_format_) { |
481 |
delete spa_video_format_; |
482 |
} |
483 |
+#endif |
484 |
|
485 |
if (pw_stream_) { |
486 |
pw_stream_destroy(pw_stream_); |
487 |
} |
488 |
|
489 |
+#if !PW_CHECK_VERSION(0, 3, 0) |
490 |
if (pw_remote_) { |
491 |
pw_remote_destroy(pw_remote_); |
492 |
} |
493 |
+#endif |
494 |
|
495 |
+#if PW_CHECK_VERSION(0, 3, 0) |
496 |
+ if (pw_core_) { |
497 |
+ pw_core_disconnect(pw_core_); |
498 |
+ } |
499 |
+ |
500 |
+ if (pw_context_) { |
501 |
+ pw_context_destroy(pw_context_); |
502 |
+ } |
503 |
+#else |
504 |
if (pw_core_) { |
505 |
pw_core_destroy(pw_core_); |
506 |
} |
507 |
+#endif |
508 |
|
509 |
if (pw_main_loop_) { |
510 |
pw_thread_loop_destroy(pw_main_loop_); |
511 |
} |
512 |
|
513 |
+#if !PW_CHECK_VERSION(0, 3, 0) |
514 |
if (pw_loop_) { |
515 |
pw_loop_destroy(pw_loop_); |
516 |
} |
517 |
- |
518 |
- if (current_frame_) { |
519 |
- free(current_frame_); |
520 |
- } |
521 |
+#endif |
522 |
|
523 |
if (start_request_signal_id_) { |
524 |
g_dbus_connection_signal_unsubscribe(connection_, start_request_signal_id_); |
525 |
@@ -228,18 +469,16 @@ BaseCapturerPipeWire::~BaseCapturerPipeWire() { |
526 |
} |
527 |
|
528 |
if (session_handle_) { |
529 |
- GDBusMessage* message = g_dbus_message_new_method_call( |
530 |
- kDesktopBusName, session_handle_, kSessionInterfaceName, "Close"); |
531 |
- if (message) { |
532 |
- GError* error = nullptr; |
533 |
- g_dbus_connection_send_message(connection_, message, |
534 |
+ Scoped<GDBusMessage> message(g_dbus_message_new_method_call( |
535 |
+ kDesktopBusName, session_handle_, kSessionInterfaceName, "Close")); |
536 |
+ if (message.get()) { |
537 |
+ Scoped<GError> error; |
538 |
+ g_dbus_connection_send_message(connection_, message.get(), |
539 |
G_DBUS_SEND_MESSAGE_FLAGS_NONE, |
540 |
- /*out_serial=*/nullptr, &error); |
541 |
- if (error) { |
542 |
+ /*out_serial=*/nullptr, error.receive()); |
543 |
+ if (error.get()) { |
544 |
RTC_LOG(LS_ERROR) << "Failed to close the session: " << error->message; |
545 |
- g_error_free(error); |
546 |
} |
547 |
- g_object_unref(message); |
548 |
} |
549 |
} |
550 |
|
551 |
@@ -274,7 +513,11 @@ void BaseCapturerPipeWire::InitPipeWire() { |
552 |
StubPathMap paths; |
553 |
|
554 |
// Check if the PipeWire library is available. |
555 |
- paths[kModulePipewire].push_back(kPipeWireLib); |
556 |
+#if PW_CHECK_VERSION(0, 3, 0) |
557 |
+ paths[kModulePipewire03].push_back(kPipeWireLib); |
558 |
+#else |
559 |
+ paths[kModulePipewire02].push_back(kPipeWireLib); |
560 |
+#endif |
561 |
if (!InitializeStubs(paths)) { |
562 |
RTC_LOG(LS_ERROR) << "Failed to load the PipeWire library and symbols."; |
563 |
portal_init_failed_ = true; |
564 |
@@ -284,16 +527,46 @@ void BaseCapturerPipeWire::InitPipeWire() { |
565 |
|
566 |
pw_init(/*argc=*/nullptr, /*argc=*/nullptr); |
567 |
|
568 |
+#if PW_CHECK_VERSION(0, 3, 0) |
569 |
+ pw_main_loop_ = pw_thread_loop_new("pipewire-main-loop", nullptr); |
570 |
+ |
571 |
+ pw_thread_loop_lock(pw_main_loop_); |
572 |
+ |
573 |
+ pw_context_ = |
574 |
+ pw_context_new(pw_thread_loop_get_loop(pw_main_loop_), nullptr, 0); |
575 |
+ if (!pw_context_) { |
576 |
+ RTC_LOG(LS_ERROR) << "Failed to create PipeWire context"; |
577 |
+ return; |
578 |
+ } |
579 |
+ |
580 |
+ pw_core_ = pw_context_connect(pw_context_, nullptr, 0); |
581 |
+ if (!pw_core_) { |
582 |
+ RTC_LOG(LS_ERROR) << "Failed to connect PipeWire context"; |
583 |
+ return; |
584 |
+ } |
585 |
+#else |
586 |
pw_loop_ = pw_loop_new(/*properties=*/nullptr); |
587 |
pw_main_loop_ = pw_thread_loop_new(pw_loop_, "pipewire-main-loop"); |
588 |
|
589 |
+ pw_thread_loop_lock(pw_main_loop_); |
590 |
+ |
591 |
pw_core_ = pw_core_new(pw_loop_, /*properties=*/nullptr); |
592 |
pw_core_type_ = pw_core_get_type(pw_core_); |
593 |
pw_remote_ = pw_remote_new(pw_core_, nullptr, /*user_data_size=*/0); |
594 |
|
595 |
InitPipeWireTypes(); |
596 |
+#endif |
597 |
|
598 |
// Initialize event handlers, remote end and stream-related. |
599 |
+#if PW_CHECK_VERSION(0, 3, 0) |
600 |
+ pw_core_events_.version = PW_VERSION_CORE_EVENTS; |
601 |
+ pw_core_events_.error = &OnCoreError; |
602 |
+ |
603 |
+ pw_stream_events_.version = PW_VERSION_STREAM_EVENTS; |
604 |
+ pw_stream_events_.state_changed = &OnStreamStateChanged; |
605 |
+ pw_stream_events_.param_changed = &OnStreamParamChanged; |
606 |
+ pw_stream_events_.process = &OnStreamProcess; |
607 |
+#else |
608 |
pw_remote_events_.version = PW_VERSION_REMOTE_EVENTS; |
609 |
pw_remote_events_.state_changed = &OnStateChanged; |
610 |
|
611 |
@@ -301,19 +574,33 @@ void BaseCapturerPipeWire::InitPipeWire() { |
612 |
pw_stream_events_.state_changed = &OnStreamStateChanged; |
613 |
pw_stream_events_.format_changed = &OnStreamFormatChanged; |
614 |
pw_stream_events_.process = &OnStreamProcess; |
615 |
+#endif |
616 |
|
617 |
+#if PW_CHECK_VERSION(0, 3, 0) |
618 |
+ pw_core_add_listener(pw_core_, &spa_core_listener_, &pw_core_events_, this); |
619 |
+ |
620 |
+ pw_stream_ = CreateReceivingStream(); |
621 |
+ if (!pw_stream_) { |
622 |
+ RTC_LOG(LS_ERROR) << "Failed to create PipeWire stream"; |
623 |
+ return; |
624 |
+ } |
625 |
+#else |
626 |
pw_remote_add_listener(pw_remote_, &spa_remote_listener_, &pw_remote_events_, |
627 |
this); |
628 |
pw_remote_connect_fd(pw_remote_, pw_fd_); |
629 |
+#endif |
630 |
|
631 |
if (pw_thread_loop_start(pw_main_loop_) < 0) { |
632 |
RTC_LOG(LS_ERROR) << "Failed to start main PipeWire loop"; |
633 |
portal_init_failed_ = true; |
634 |
} |
635 |
|
636 |
+ pw_thread_loop_unlock(pw_main_loop_); |
637 |
+ |
638 |
RTC_LOG(LS_INFO) << "PipeWire remote opened."; |
639 |
} |
640 |
|
641 |
+#if !PW_CHECK_VERSION(0, 3, 0) |
642 |
void BaseCapturerPipeWire::InitPipeWireTypes() { |
643 |
spa_type_map* map = pw_core_type_->map; |
644 |
pw_type_ = new PipeWireType(); |
645 |
@@ -323,23 +610,44 @@ void BaseCapturerPipeWire::InitPipeWireTypes() { |
646 |
spa_type_format_video_map(map, &pw_type_->format_video); |
647 |
spa_type_video_format_map(map, &pw_type_->video_format); |
648 |
} |
649 |
+#endif |
650 |
|
651 |
-void BaseCapturerPipeWire::CreateReceivingStream() { |
652 |
+pw_stream* BaseCapturerPipeWire::CreateReceivingStream() { |
653 |
+#if !PW_CHECK_VERSION(0, 3, 0) |
654 |
+ if (pw_remote_get_state(pw_remote_, nullptr) != PW_REMOTE_STATE_CONNECTED) { |
655 |
+ RTC_LOG(LS_ERROR) << "Cannot create pipewire stream"; |
656 |
+ return nullptr; |
657 |
+ } |
658 |
+#endif |
659 |
spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; |
660 |
- spa_rectangle pwScreenBounds = |
661 |
- spa_rectangle{static_cast<uint32_t>(desktop_size_.width()), |
662 |
- static_cast<uint32_t>(desktop_size_.height())}; |
663 |
- |
664 |
- spa_fraction pwFrameRateMin = spa_fraction{0, 1}; |
665 |
- spa_fraction pwFrameRateMax = spa_fraction{60, 1}; |
666 |
+ spa_rectangle pwMaxScreenBounds = spa_rectangle{UINT32_MAX, UINT32_MAX}; |
667 |
|
668 |
pw_properties* reuseProps = |
669 |
pw_properties_new_string("pipewire.client.reuse=1"); |
670 |
- pw_stream_ = pw_stream_new(pw_remote_, "webrtc-consume-stream", reuseProps); |
671 |
+#if PW_CHECK_VERSION(0, 3, 0) |
672 |
+ auto stream = pw_stream_new(pw_core_, "webrtc-consume-stream", reuseProps); |
673 |
+#else |
674 |
+ auto stream = pw_stream_new(pw_remote_, "webrtc-consume-stream", reuseProps); |
675 |
+#endif |
676 |
|
677 |
uint8_t buffer[1024] = {}; |
678 |
const spa_pod* params[1]; |
679 |
spa_pod_builder builder = spa_pod_builder{buffer, sizeof(buffer)}; |
680 |
+ |
681 |
+#if PW_CHECK_VERSION(0, 3, 0) |
682 |
+ params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_add_object( |
683 |
+ &builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, |
684 |
+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), |
685 |
+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), |
686 |
+ SPA_FORMAT_VIDEO_format, |
687 |
+ SPA_POD_CHOICE_ENUM_Id(5, SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx, |
688 |
+ SPA_VIDEO_FORMAT_RGBA, SPA_VIDEO_FORMAT_BGRx, |
689 |
+ SPA_VIDEO_FORMAT_BGRA), |
690 |
+ SPA_FORMAT_VIDEO_size, |
691 |
+ SPA_POD_CHOICE_RANGE_Rectangle(&pwMinScreenBounds, &pwMinScreenBounds, |
692 |
+ &pwMaxScreenBounds), |
693 |
+ 0)); |
694 |
+#else |
695 |
params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_object( |
696 |
&builder, |
697 |
// id to enumerate formats |
698 |
@@ -349,69 +657,218 @@ void BaseCapturerPipeWire::CreateReceivingStream() { |
699 |
// then allowed formats are enumerated (e) and the format is undecided (u) |
700 |
// to allow negotiation |
701 |
":", pw_type_->format_video.format, "Ieu", pw_type_->video_format.BGRx, |
702 |
- SPA_POD_PROP_ENUM(2, pw_type_->video_format.RGBx, |
703 |
- pw_type_->video_format.BGRx), |
704 |
+ SPA_POD_PROP_ENUM( |
705 |
+ 4, pw_type_->video_format.RGBx, pw_type_->video_format.BGRx, |
706 |
+ pw_type_->video_format.RGBA, pw_type_->video_format.BGRA), |
707 |
// Video size: specified as rectangle (R), preferred size is specified as |
708 |
// first parameter, then allowed size is defined as range (r) from min and |
709 |
// max values and the format is undecided (u) to allow negotiation |
710 |
- ":", pw_type_->format_video.size, "Rru", &pwScreenBounds, 2, |
711 |
- &pwMinScreenBounds, &pwScreenBounds, |
712 |
- // Frame rate: specified as fraction (F) and set to minimum frame rate |
713 |
- // value |
714 |
- ":", pw_type_->format_video.framerate, "F", &pwFrameRateMin, |
715 |
- // Max frame rate: specified as fraction (F), preferred frame rate is set |
716 |
- // to maximum value, then allowed frame rate is defined as range (r) from |
717 |
- // min and max values and it is undecided (u) to allow negotiation |
718 |
- ":", pw_type_->format_video.max_framerate, "Fru", &pwFrameRateMax, 2, |
719 |
- &pwFrameRateMin, &pwFrameRateMax)); |
720 |
- |
721 |
- pw_stream_add_listener(pw_stream_, &spa_stream_listener_, &pw_stream_events_, |
722 |
+ ":", pw_type_->format_video.size, "Rru", &pwMinScreenBounds, |
723 |
+ SPA_POD_PROP_MIN_MAX(&pwMinScreenBounds, &pwMaxScreenBounds))); |
724 |
+#endif |
725 |
+ |
726 |
+ pw_stream_add_listener(stream, &spa_stream_listener_, &pw_stream_events_, |
727 |
this); |
728 |
+#if PW_CHECK_VERSION(0, 3, 0) |
729 |
+ if (pw_stream_connect(stream, PW_DIRECTION_INPUT, pw_stream_node_id_, |
730 |
+ PW_STREAM_FLAG_AUTOCONNECT, params, 1) != 0) { |
731 |
+#else |
732 |
pw_stream_flags flags = static_cast<pw_stream_flags>( |
733 |
- PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE | |
734 |
- PW_STREAM_FLAG_MAP_BUFFERS); |
735 |
- if (pw_stream_connect(pw_stream_, PW_DIRECTION_INPUT, /*port_path=*/nullptr, |
736 |
+ PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE); |
737 |
+ if (pw_stream_connect(stream, PW_DIRECTION_INPUT, /*port_path=*/nullptr, |
738 |
flags, params, |
739 |
/*n_params=*/1) != 0) { |
740 |
+#endif |
741 |
RTC_LOG(LS_ERROR) << "Could not connect receiving stream."; |
742 |
portal_init_failed_ = true; |
743 |
- return; |
744 |
+ return nullptr; |
745 |
} |
746 |
+ |
747 |
+ return stream; |
748 |
} |
749 |
|
750 |
void BaseCapturerPipeWire::HandleBuffer(pw_buffer* buffer) { |
751 |
spa_buffer* spaBuffer = buffer->buffer; |
752 |
- void* src = nullptr; |
753 |
+ ScopedBuf map; |
754 |
+ uint8_t* src = nullptr; |
755 |
+ |
756 |
+ if (spaBuffer->datas[0].chunk->size == 0) { |
757 |
+ RTC_LOG(LS_ERROR) << "Failed to get video stream: Zero size."; |
758 |
+ return; |
759 |
+ } |
760 |
+ |
761 |
+#if PW_CHECK_VERSION(0, 3, 0) |
762 |
+ if (spaBuffer->datas[0].type == SPA_DATA_MemFd || |
763 |
+ spaBuffer->datas[0].type == SPA_DATA_DmaBuf) { |
764 |
+#else |
765 |
+ if (spaBuffer->datas[0].type == pw_core_type_->data.MemFd || |
766 |
+ spaBuffer->datas[0].type == pw_core_type_->data.DmaBuf) { |
767 |
+#endif |
768 |
+ map.initialize( |
769 |
+ static_cast<uint8_t*>( |
770 |
+ mmap(nullptr, |
771 |
+ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, |
772 |
+ PROT_READ, MAP_PRIVATE, spaBuffer->datas[0].fd, 0)), |
773 |
+ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, |
774 |
+#if PW_CHECK_VERSION(0, 3, 0) |
775 |
+ spaBuffer->datas[0].type == SPA_DATA_DmaBuf, |
776 |
+#else |
777 |
+ spaBuffer->datas[0].type == pw_core_type_->data.DmaBuf, |
778 |
+#endif |
779 |
+ spaBuffer->datas[0].fd); |
780 |
+ |
781 |
+ if (!map) { |
782 |
+ RTC_LOG(LS_ERROR) << "Failed to mmap the memory: " |
783 |
+ << std::strerror(errno); |
784 |
+ return; |
785 |
+ } |
786 |
+ |
787 |
+#if PW_CHECK_VERSION(0, 3, 0) |
788 |
+ if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf) { |
789 |
+#else |
790 |
+ if (spaBuffer->datas[0].type == pw_core_type_->data.DmaBuf) { |
791 |
+#endif |
792 |
+ SyncDmaBuf(spaBuffer->datas[0].fd, DMA_BUF_SYNC_START); |
793 |
+ } |
794 |
+ |
795 |
+ src = SPA_MEMBER(map.get(), spaBuffer->datas[0].mapoffset, uint8_t); |
796 |
+#if PW_CHECK_VERSION(0, 3, 0) |
797 |
+ } else if (spaBuffer->datas[0].type == SPA_DATA_MemPtr) { |
798 |
+#else |
799 |
+ } else if (spaBuffer->datas[0].type == pw_core_type_->data.MemPtr) { |
800 |
+#endif |
801 |
+ src = static_cast<uint8_t*>(spaBuffer->datas[0].data); |
802 |
+ } |
803 |
|
804 |
- if (!(src = spaBuffer->datas[0].data)) { |
805 |
+ if (!src) { |
806 |
+ return; |
807 |
+ } |
808 |
+ |
809 |
+#if PW_CHECK_VERSION(0, 3, 0) |
810 |
+ struct spa_meta_region* video_metadata = |
811 |
+ static_cast<struct spa_meta_region*>(spa_buffer_find_meta_data( |
812 |
+ spaBuffer, SPA_META_VideoCrop, sizeof(*video_metadata))); |
813 |
+#else |
814 |
+ struct spa_meta_video_crop* video_metadata = |
815 |
+ static_cast<struct spa_meta_video_crop*>( |
816 |
+ spa_buffer_find_meta(spaBuffer, pw_core_type_->meta.VideoCrop)); |
817 |
+#endif |
818 |
+ |
819 |
+ // Video size from metadata is bigger than an actual video stream size. |
820 |
+ // The metadata are wrong or we should up-scale the video...in both cases |
821 |
+ // just quit now. |
822 |
+#if PW_CHECK_VERSION(0, 3, 0) |
823 |
+ if (video_metadata && (video_metadata->region.size.width > |
824 |
+ static_cast<uint32_t>(desktop_size_.width()) || |
825 |
+ video_metadata->region.size.height > |
826 |
+ static_cast<uint32_t>(desktop_size_.height()))) { |
827 |
+#else |
828 |
+ if (video_metadata && (video_metadata->width > desktop_size_.width() || |
829 |
+ video_metadata->height > desktop_size_.height())) { |
830 |
+#endif |
831 |
+ RTC_LOG(LS_ERROR) << "Stream metadata sizes are wrong!"; |
832 |
return; |
833 |
} |
834 |
|
835 |
- uint32_t maxSize = spaBuffer->datas[0].maxsize; |
836 |
- int32_t srcStride = spaBuffer->datas[0].chunk->stride; |
837 |
- if (srcStride != (desktop_size_.width() * kBytesPerPixel)) { |
838 |
+ // Use video metadata when video size from metadata is set and smaller than |
839 |
+ // video stream size, so we need to adjust it. |
840 |
+ bool video_is_full_width = true; |
841 |
+ bool video_is_full_height = true; |
842 |
+#if PW_CHECK_VERSION(0, 3, 0) |
843 |
+ if (video_metadata && video_metadata->region.size.width != 0 && |
844 |
+ video_metadata->region.size.height != 0) { |
845 |
+ if (video_metadata->region.size.width < |
846 |
+ static_cast<uint32_t>(desktop_size_.width())) { |
847 |
+ video_is_full_width = false; |
848 |
+ } else if (video_metadata->region.size.height < |
849 |
+ static_cast<uint32_t>(desktop_size_.height())) { |
850 |
+ video_is_full_height = false; |
851 |
+ } |
852 |
+ } |
853 |
+#else |
854 |
+ if (video_metadata && video_metadata->width != 0 && |
855 |
+ video_metadata->height != 0) { |
856 |
+ if (video_metadata->width < desktop_size_.width()) { |
857 |
+ } else if (video_metadata->height < desktop_size_.height()) { |
858 |
+ video_is_full_height = false; |
859 |
+ } |
860 |
+ } |
861 |
+#endif |
862 |
+ |
863 |
+ DesktopSize video_size_prev = video_size_; |
864 |
+ if (!video_is_full_height || !video_is_full_width) { |
865 |
+#if PW_CHECK_VERSION(0, 3, 0) |
866 |
+ video_size_ = DesktopSize(video_metadata->region.size.width, |
867 |
+ video_metadata->region.size.height); |
868 |
+#else |
869 |
+ video_size_ = DesktopSize(video_metadata->width, video_metadata->height); |
870 |
+#endif |
871 |
+ } else { |
872 |
+ video_size_ = desktop_size_; |
873 |
+ } |
874 |
+ |
875 |
+ webrtc::MutexLock lock(¤t_frame_lock_); |
876 |
+ if (!current_frame_ || !video_size_.equals(video_size_prev)) { |
877 |
+ current_frame_ = std::make_unique<uint8_t[]>( |
878 |
+ video_size_.width() * video_size_.height() * kBytesPerPixel); |
879 |
+ } |
880 |
+ |
881 |
+ const int32_t dst_stride = video_size_.width() * kBytesPerPixel; |
882 |
+ const int32_t src_stride = spaBuffer->datas[0].chunk->stride; |
883 |
+ |
884 |
+ if (src_stride != (desktop_size_.width() * kBytesPerPixel)) { |
885 |
RTC_LOG(LS_ERROR) << "Got buffer with stride different from screen stride: " |
886 |
- << srcStride |
887 |
+ << src_stride |
888 |
<< " != " << (desktop_size_.width() * kBytesPerPixel); |
889 |
portal_init_failed_ = true; |
890 |
+ |
891 |
return; |
892 |
} |
893 |
|
894 |
- if (!current_frame_) { |
895 |
- current_frame_ = static_cast<uint8_t*>(malloc(maxSize)); |
896 |
- } |
897 |
- RTC_DCHECK(current_frame_ != nullptr); |
898 |
- |
899 |
- // If both sides decided to go with the RGBx format we need to convert it to |
900 |
- // BGRx to match color format expected by WebRTC. |
901 |
- if (spa_video_format_->format == pw_type_->video_format.RGBx) { |
902 |
- uint8_t* tempFrame = static_cast<uint8_t*>(malloc(maxSize)); |
903 |
- std::memcpy(tempFrame, src, maxSize); |
904 |
- ConvertRGBxToBGRx(tempFrame, maxSize); |
905 |
- std::memcpy(current_frame_, tempFrame, maxSize); |
906 |
- free(tempFrame); |
907 |
- } else { |
908 |
- std::memcpy(current_frame_, src, maxSize); |
909 |
+ // Adjust source content based on metadata video position |
910 |
+#if PW_CHECK_VERSION(0, 3, 0) |
911 |
+ if (!video_is_full_height && |
912 |
+ (video_metadata->region.position.y + video_size_.height() <= |
913 |
+ desktop_size_.height())) { |
914 |
+ src += src_stride * video_metadata->region.position.y; |
915 |
+ } |
916 |
+ const int x_offset = |
917 |
+ !video_is_full_width && |
918 |
+ (video_metadata->region.position.x + video_size_.width() <= |
919 |
+ desktop_size_.width()) |
920 |
+ ? video_metadata->region.position.x * kBytesPerPixel |
921 |
+ : 0; |
922 |
+#else |
923 |
+ if (!video_is_full_height && |
924 |
+ (video_metadata->y + video_size_.height() <= desktop_size_.height())) { |
925 |
+ src += src_stride * video_metadata->y; |
926 |
+ } |
927 |
+ |
928 |
+ const int x_offset = |
929 |
+ !video_is_full_width && |
930 |
+ (video_metadata->x + video_size_.width() <= desktop_size_.width()) |
931 |
+ ? video_metadata->x * kBytesPerPixel |
932 |
+ : 0; |
933 |
+#endif |
934 |
+ |
935 |
+ uint8_t* dst = current_frame_.get(); |
936 |
+ for (int i = 0; i < video_size_.height(); ++i) { |
937 |
+ // Adjust source content based on crop video position if needed |
938 |
+ src += x_offset; |
939 |
+ std::memcpy(dst, src, dst_stride); |
940 |
+ // If both sides decided to go with the RGBx format we need to convert it to |
941 |
+ // BGRx to match color format expected by WebRTC. |
942 |
+#if PW_CHECK_VERSION(0, 3, 0) |
943 |
+ if (spa_video_format_.format == SPA_VIDEO_FORMAT_RGBx || |
944 |
+ spa_video_format_.format == SPA_VIDEO_FORMAT_RGBA) { |
945 |
+#else |
946 |
+ if (spa_video_format_->format == pw_type_->video_format.RGBx || |
947 |
+ spa_video_format_->format == pw_type_->video_format.RGBA) { |
948 |
+#endif |
949 |
+ ConvertRGBxToBGRx(dst, dst_stride); |
950 |
+ } |
951 |
+ src += src_stride - x_offset; |
952 |
+ dst += dst_stride; |
953 |
} |
954 |
} |
955 |
|
956 |
@@ -441,14 +898,13 @@ void BaseCapturerPipeWire::OnProxyRequested(GObject* /*object*/, |
957 |
BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(user_data); |
958 |
RTC_DCHECK(that); |
959 |
|
960 |
- GError* error = nullptr; |
961 |
- GDBusProxy *proxy = g_dbus_proxy_new_finish(result, &error); |
962 |
+ Scoped<GError> error; |
963 |
+ GDBusProxy* proxy = g_dbus_proxy_new_finish(result, error.receive()); |
964 |
if (!proxy) { |
965 |
- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
966 |
+ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
967 |
return; |
968 |
RTC_LOG(LS_ERROR) << "Failed to create a proxy for the screen cast portal: " |
969 |
<< error->message; |
970 |
- g_error_free(error); |
971 |
that->portal_init_failed_ = true; |
972 |
return; |
973 |
} |
974 |
@@ -462,38 +918,36 @@ void BaseCapturerPipeWire::OnProxyRequested(GObject* /*object*/, |
975 |
// static |
976 |
gchar* BaseCapturerPipeWire::PrepareSignalHandle(GDBusConnection* connection, |
977 |
const gchar* token) { |
978 |
- gchar* sender = g_strdup(g_dbus_connection_get_unique_name(connection) + 1); |
979 |
- for (int i = 0; sender[i]; i++) { |
980 |
- if (sender[i] == '.') { |
981 |
- sender[i] = '_'; |
982 |
+ Scoped<gchar> sender( |
983 |
+ g_strdup(g_dbus_connection_get_unique_name(connection) + 1)); |
984 |
+ for (int i = 0; sender.get()[i]; i++) { |
985 |
+ if (sender.get()[i] == '.') { |
986 |
+ sender.get()[i] = '_'; |
987 |
} |
988 |
} |
989 |
|
990 |
- gchar* handle = g_strconcat(kDesktopRequestObjectPath, "/", sender, "/", |
991 |
+ gchar* handle = g_strconcat(kDesktopRequestObjectPath, "/", sender.get(), "/", |
992 |
token, /*end of varargs*/ nullptr); |
993 |
- g_free(sender); |
994 |
|
995 |
return handle; |
996 |
} |
997 |
|
998 |
void BaseCapturerPipeWire::SessionRequest() { |
999 |
GVariantBuilder builder; |
1000 |
- gchar* variant_string; |
1001 |
+ Scoped<gchar> variant_string; |
1002 |
|
1003 |
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); |
1004 |
variant_string = |
1005 |
g_strdup_printf("webrtc_session%d", g_random_int_range(0, G_MAXINT)); |
1006 |
g_variant_builder_add(&builder, "{sv}", "session_handle_token", |
1007 |
- g_variant_new_string(variant_string)); |
1008 |
- g_free(variant_string); |
1009 |
+ g_variant_new_string(variant_string.get())); |
1010 |
variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); |
1011 |
g_variant_builder_add(&builder, "{sv}", "handle_token", |
1012 |
- g_variant_new_string(variant_string)); |
1013 |
+ g_variant_new_string(variant_string.get())); |
1014 |
|
1015 |
- portal_handle_ = PrepareSignalHandle(connection_, variant_string); |
1016 |
+ portal_handle_ = PrepareSignalHandle(connection_, variant_string.get()); |
1017 |
session_request_signal_id_ = SetupRequestResponseSignal( |
1018 |
portal_handle_, OnSessionRequestResponseSignal); |
1019 |
- g_free(variant_string); |
1020 |
|
1021 |
RTC_LOG(LS_INFO) << "Screen cast session requested."; |
1022 |
g_dbus_proxy_call( |
1023 |
@@ -509,22 +963,21 @@ void BaseCapturerPipeWire::OnSessionRequested(GDBusProxy *proxy, |
1024 |
BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(user_data); |
1025 |
RTC_DCHECK(that); |
1026 |
|
1027 |
- GError* error = nullptr; |
1028 |
- GVariant* variant = g_dbus_proxy_call_finish(proxy, result, &error); |
1029 |
+ Scoped<GError> error; |
1030 |
+ Scoped<GVariant> variant( |
1031 |
+ g_dbus_proxy_call_finish(proxy, result, error.receive())); |
1032 |
if (!variant) { |
1033 |
- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1034 |
+ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1035 |
return; |
1036 |
RTC_LOG(LS_ERROR) << "Failed to create a screen cast session: " |
1037 |
<< error->message; |
1038 |
- g_error_free(error); |
1039 |
that->portal_init_failed_ = true; |
1040 |
return; |
1041 |
} |
1042 |
RTC_LOG(LS_INFO) << "Initializing the screen cast session."; |
1043 |
|
1044 |
- gchar* handle = nullptr; |
1045 |
- g_variant_get_child(variant, 0, "o", &handle); |
1046 |
- g_variant_unref(variant); |
1047 |
+ Scoped<gchar> handle; |
1048 |
+ g_variant_get_child(variant.get(), 0, "o", &handle); |
1049 |
if (!handle) { |
1050 |
RTC_LOG(LS_ERROR) << "Failed to initialize the screen cast session."; |
1051 |
if (that->session_request_signal_id_) { |
1052 |
@@ -536,8 +989,6 @@ void BaseCapturerPipeWire::OnSessionRequested(GDBusProxy *proxy, |
1053 |
return; |
1054 |
} |
1055 |
|
1056 |
- g_free(handle); |
1057 |
- |
1058 |
RTC_LOG(LS_INFO) << "Subscribing to the screen cast session."; |
1059 |
} |
1060 |
|
1061 |
@@ -557,11 +1008,11 @@ void BaseCapturerPipeWire::OnSessionRequestResponseSignal( |
1062 |
<< "Received response for the screen cast session subscription."; |
1063 |
|
1064 |
guint32 portal_response; |
1065 |
- GVariant* response_data; |
1066 |
- g_variant_get(parameters, "(u@a{sv})", &portal_response, &response_data); |
1067 |
- g_variant_lookup(response_data, "session_handle", "s", |
1068 |
+ Scoped<GVariant> response_data; |
1069 |
+ g_variant_get(parameters, "(u@a{sv})", &portal_response, |
1070 |
+ response_data.receive()); |
1071 |
+ g_variant_lookup(response_data.get(), "session_handle", "s", |
1072 |
&that->session_handle_); |
1073 |
- g_variant_unref(response_data); |
1074 |
|
1075 |
if (!that->session_handle_ || portal_response) { |
1076 |
RTC_LOG(LS_ERROR) |
1077 |
@@ -575,23 +1026,23 @@ void BaseCapturerPipeWire::OnSessionRequestResponseSignal( |
1078 |
|
1079 |
void BaseCapturerPipeWire::SourcesRequest() { |
1080 |
GVariantBuilder builder; |
1081 |
- gchar* variant_string; |
1082 |
+ Scoped<gchar> variant_string; |
1083 |
|
1084 |
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); |
1085 |
// We want to record monitor content. |
1086 |
- g_variant_builder_add(&builder, "{sv}", "types", |
1087 |
- g_variant_new_uint32(capture_source_type_)); |
1088 |
+ g_variant_builder_add( |
1089 |
+ &builder, "{sv}", "types", |
1090 |
+ g_variant_new_uint32(static_cast<uint32_t>(capture_source_type_))); |
1091 |
// We don't want to allow selection of multiple sources. |
1092 |
g_variant_builder_add(&builder, "{sv}", "multiple", |
1093 |
g_variant_new_boolean(false)); |
1094 |
variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); |
1095 |
g_variant_builder_add(&builder, "{sv}", "handle_token", |
1096 |
- g_variant_new_string(variant_string)); |
1097 |
+ g_variant_new_string(variant_string.get())); |
1098 |
|
1099 |
- sources_handle_ = PrepareSignalHandle(connection_, variant_string); |
1100 |
+ sources_handle_ = PrepareSignalHandle(connection_, variant_string.get()); |
1101 |
sources_request_signal_id_ = SetupRequestResponseSignal( |
1102 |
sources_handle_, OnSourcesRequestResponseSignal); |
1103 |
- g_free(variant_string); |
1104 |
|
1105 |
RTC_LOG(LS_INFO) << "Requesting sources from the screen cast session."; |
1106 |
g_dbus_proxy_call( |
1107 |
@@ -608,22 +1059,21 @@ void BaseCapturerPipeWire::OnSourcesRequested(GDBusProxy *proxy, |
1108 |
BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(user_data); |
1109 |
RTC_DCHECK(that); |
1110 |
|
1111 |
- GError* error = nullptr; |
1112 |
- GVariant* variant = g_dbus_proxy_call_finish(proxy, result, &error); |
1113 |
+ Scoped<GError> error; |
1114 |
+ Scoped<GVariant> variant( |
1115 |
+ g_dbus_proxy_call_finish(proxy, result, error.receive())); |
1116 |
if (!variant) { |
1117 |
- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1118 |
+ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1119 |
return; |
1120 |
RTC_LOG(LS_ERROR) << "Failed to request the sources: " << error->message; |
1121 |
- g_error_free(error); |
1122 |
that->portal_init_failed_ = true; |
1123 |
return; |
1124 |
} |
1125 |
|
1126 |
RTC_LOG(LS_INFO) << "Sources requested from the screen cast session."; |
1127 |
|
1128 |
- gchar* handle = nullptr; |
1129 |
- g_variant_get_child(variant, 0, "o", &handle); |
1130 |
- g_variant_unref(variant); |
1131 |
+ Scoped<gchar> handle; |
1132 |
+ g_variant_get_child(variant.get(), 0, "o", handle.receive()); |
1133 |
if (!handle) { |
1134 |
RTC_LOG(LS_ERROR) << "Failed to initialize the screen cast session."; |
1135 |
if (that->sources_request_signal_id_) { |
1136 |
@@ -635,8 +1085,6 @@ void BaseCapturerPipeWire::OnSourcesRequested(GDBusProxy *proxy, |
1137 |
return; |
1138 |
} |
1139 |
|
1140 |
- g_free(handle); |
1141 |
- |
1142 |
RTC_LOG(LS_INFO) << "Subscribed to sources signal."; |
1143 |
} |
1144 |
|
1145 |
@@ -668,17 +1116,16 @@ void BaseCapturerPipeWire::OnSourcesRequestResponseSignal( |
1146 |
|
1147 |
void BaseCapturerPipeWire::StartRequest() { |
1148 |
GVariantBuilder builder; |
1149 |
- gchar* variant_string; |
1150 |
+ Scoped<gchar> variant_string; |
1151 |
|
1152 |
g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); |
1153 |
variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, G_MAXINT)); |
1154 |
g_variant_builder_add(&builder, "{sv}", "handle_token", |
1155 |
- g_variant_new_string(variant_string)); |
1156 |
+ g_variant_new_string(variant_string.get())); |
1157 |
|
1158 |
- start_handle_ = PrepareSignalHandle(connection_, variant_string); |
1159 |
+ start_handle_ = PrepareSignalHandle(connection_, variant_string.get()); |
1160 |
start_request_signal_id_ = |
1161 |
SetupRequestResponseSignal(start_handle_, OnStartRequestResponseSignal); |
1162 |
- g_free(variant_string); |
1163 |
|
1164 |
// "Identifier for the application window", this is Wayland, so not "x11:...". |
1165 |
const gchar parent_window[] = ""; |
1166 |
@@ -698,23 +1145,22 @@ void BaseCapturerPipeWire::OnStartRequested(GDBusProxy *proxy, |
1167 |
BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(user_data); |
1168 |
RTC_DCHECK(that); |
1169 |
|
1170 |
- GError* error = nullptr; |
1171 |
- GVariant* variant = g_dbus_proxy_call_finish(proxy, result, &error); |
1172 |
+ Scoped<GError> error; |
1173 |
+ Scoped<GVariant> variant( |
1174 |
+ g_dbus_proxy_call_finish(proxy, result, error.receive())); |
1175 |
if (!variant) { |
1176 |
- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1177 |
+ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1178 |
return; |
1179 |
RTC_LOG(LS_ERROR) << "Failed to start the screen cast session: " |
1180 |
<< error->message; |
1181 |
- g_error_free(error); |
1182 |
that->portal_init_failed_ = true; |
1183 |
return; |
1184 |
} |
1185 |
|
1186 |
RTC_LOG(LS_INFO) << "Initializing the start of the screen cast session."; |
1187 |
|
1188 |
- gchar* handle = nullptr; |
1189 |
- g_variant_get_child(variant, 0, "o", &handle); |
1190 |
- g_variant_unref(variant); |
1191 |
+ Scoped<gchar> handle; |
1192 |
+ g_variant_get_child(variant.get(), 0, "o", handle.receive()); |
1193 |
if (!handle) { |
1194 |
RTC_LOG(LS_ERROR) |
1195 |
<< "Failed to initialize the start of the screen cast session."; |
1196 |
@@ -727,8 +1173,6 @@ void BaseCapturerPipeWire::OnStartRequested(GDBusProxy *proxy, |
1197 |
return; |
1198 |
} |
1199 |
|
1200 |
- g_free(handle); |
1201 |
- |
1202 |
RTC_LOG(LS_INFO) << "Subscribed to the start signal."; |
1203 |
} |
1204 |
|
1205 |
@@ -746,9 +1190,10 @@ void BaseCapturerPipeWire::OnStartRequestResponseSignal( |
1206 |
|
1207 |
RTC_LOG(LS_INFO) << "Start signal received."; |
1208 |
guint32 portal_response; |
1209 |
- GVariant* response_data; |
1210 |
- GVariantIter* iter = nullptr; |
1211 |
- g_variant_get(parameters, "(u@a{sv})", &portal_response, &response_data); |
1212 |
+ Scoped<GVariant> response_data; |
1213 |
+ Scoped<GVariantIter> iter; |
1214 |
+ g_variant_get(parameters, "(u@a{sv})", &portal_response, |
1215 |
+ response_data.receive()); |
1216 |
if (portal_response || !response_data) { |
1217 |
RTC_LOG(LS_ERROR) << "Failed to start the screen cast session."; |
1218 |
that->portal_init_failed_ = true; |
1219 |
@@ -758,28 +1203,28 @@ void BaseCapturerPipeWire::OnStartRequestResponseSignal( |
1220 |
// Array of PipeWire streams. See |
1221 |
// https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml |
1222 |
// documentation for <method name="Start">. |
1223 |
- if (g_variant_lookup(response_data, "streams", "a(ua{sv})", &iter)) { |
1224 |
- GVariant* variant; |
1225 |
+ if (g_variant_lookup(response_data.get(), "streams", "a(ua{sv})", |
1226 |
+ iter.receive())) { |
1227 |
+ Scoped<GVariant> variant; |
1228 |
|
1229 |
- while (g_variant_iter_next(iter, "@(ua{sv})", &variant)) { |
1230 |
+ while (g_variant_iter_next(iter.get(), "@(ua{sv})", variant.receive())) { |
1231 |
guint32 stream_id; |
1232 |
- gint32 width; |
1233 |
- gint32 height; |
1234 |
- GVariant* options; |
1235 |
+ guint32 type; |
1236 |
+ Scoped<GVariant> options; |
1237 |
|
1238 |
- g_variant_get(variant, "(u@a{sv})", &stream_id, &options); |
1239 |
- RTC_DCHECK(options != nullptr); |
1240 |
+ g_variant_get(variant.get(), "(u@a{sv})", &stream_id, options.receive()); |
1241 |
+ RTC_DCHECK(options.get()); |
1242 |
|
1243 |
- g_variant_lookup(options, "size", "(ii)", &width, &height); |
1244 |
+ if (g_variant_lookup(options.get(), "source_type", "u", &type)) { |
1245 |
+ that->capture_source_type_ = |
1246 |
+ static_cast<BaseCapturerPipeWire::CaptureSourceType>(type); |
1247 |
+ } |
1248 |
|
1249 |
- that->desktop_size_.set(width, height); |
1250 |
+ that->pw_stream_node_id_ = stream_id; |
1251 |
|
1252 |
- g_variant_unref(options); |
1253 |
- g_variant_unref(variant); |
1254 |
+ break; |
1255 |
} |
1256 |
} |
1257 |
- g_variant_iter_free(iter); |
1258 |
- g_variant_unref(response_data); |
1259 |
|
1260 |
that->OpenPipeWireRemote(); |
1261 |
} |
1262 |
@@ -807,35 +1252,30 @@ void BaseCapturerPipeWire::OnOpenPipeWireRemoteRequested( |
1263 |
BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(user_data); |
1264 |
RTC_DCHECK(that); |
1265 |
|
1266 |
- GError* error = nullptr; |
1267 |
- GUnixFDList* outlist = nullptr; |
1268 |
- GVariant* variant = g_dbus_proxy_call_with_unix_fd_list_finish( |
1269 |
- proxy, &outlist, result, &error); |
1270 |
+ Scoped<GError> error; |
1271 |
+ Scoped<GUnixFDList> outlist; |
1272 |
+ Scoped<GVariant> variant(g_dbus_proxy_call_with_unix_fd_list_finish( |
1273 |
+ proxy, outlist.receive(), result, error.receive())); |
1274 |
if (!variant) { |
1275 |
- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1276 |
+ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) |
1277 |
return; |
1278 |
RTC_LOG(LS_ERROR) << "Failed to open the PipeWire remote: " |
1279 |
<< error->message; |
1280 |
- g_error_free(error); |
1281 |
that->portal_init_failed_ = true; |
1282 |
return; |
1283 |
} |
1284 |
|
1285 |
gint32 index; |
1286 |
- g_variant_get(variant, "(h)", &index); |
1287 |
+ g_variant_get(variant.get(), "(h)", &index); |
1288 |
|
1289 |
- if ((that->pw_fd_ = g_unix_fd_list_get(outlist, index, &error)) == -1) { |
1290 |
+ if ((that->pw_fd_ = |
1291 |
+ g_unix_fd_list_get(outlist.get(), index, error.receive())) == -1) { |
1292 |
RTC_LOG(LS_ERROR) << "Failed to get file descriptor from the list: " |
1293 |
<< error->message; |
1294 |
- g_error_free(error); |
1295 |
- g_variant_unref(variant); |
1296 |
that->portal_init_failed_ = true; |
1297 |
return; |
1298 |
} |
1299 |
|
1300 |
- g_variant_unref(variant); |
1301 |
- g_object_unref(outlist); |
1302 |
- |
1303 |
that->InitPipeWire(); |
1304 |
} |
1305 |
|
1306 |
@@ -854,15 +1294,18 @@ void BaseCapturerPipeWire::CaptureFrame() { |
1307 |
return; |
1308 |
} |
1309 |
|
1310 |
+ webrtc::MutexLock lock(¤t_frame_lock_); |
1311 |
if (!current_frame_) { |
1312 |
callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); |
1313 |
return; |
1314 |
} |
1315 |
|
1316 |
- std::unique_ptr<DesktopFrame> result(new BasicDesktopFrame(desktop_size_)); |
1317 |
+ DesktopSize frame_size = video_size_; |
1318 |
+ |
1319 |
+ std::unique_ptr<DesktopFrame> result(new BasicDesktopFrame(frame_size)); |
1320 |
result->CopyPixelsFrom( |
1321 |
- current_frame_, (desktop_size_.width() * kBytesPerPixel), |
1322 |
- DesktopRect::MakeWH(desktop_size_.width(), desktop_size_.height())); |
1323 |
+ current_frame_.get(), (frame_size.width() * kBytesPerPixel), |
1324 |
+ DesktopRect::MakeWH(frame_size.width(), frame_size.height())); |
1325 |
if (!result) { |
1326 |
callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); |
1327 |
return; |
1328 |
@@ -887,4 +1330,11 @@ bool BaseCapturerPipeWire::SelectSource(SourceId id) { |
1329 |
return true; |
1330 |
} |
1331 |
|
1332 |
+// static |
1333 |
+std::unique_ptr<DesktopCapturer> BaseCapturerPipeWire::CreateRawCapturer( |
1334 |
+ const DesktopCaptureOptions& options) { |
1335 |
+ return std::make_unique<BaseCapturerPipeWire>( |
1336 |
+ BaseCapturerPipeWire::CaptureSourceType::kAny); |
1337 |
+} |
1338 |
+ |
1339 |
} // namespace webrtc |
1340 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h |
1341 |
index f28d7a5..75d20db 100644 |
1342 |
--- a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h |
1343 |
+++ b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h |
1344 |
@@ -10,18 +10,23 @@ |
1345 |
|
1346 |
#ifndef MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ |
1347 |
#define MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ |
1348 |
- |
1349 |
#include <gio/gio.h> |
1350 |
#define typeof __typeof__ |
1351 |
#include <pipewire/pipewire.h> |
1352 |
#include <spa/param/video/format-utils.h> |
1353 |
+#if PW_CHECK_VERSION(0, 3, 0) |
1354 |
+#include <spa/utils/result.h> |
1355 |
+#endif |
1356 |
|
1357 |
+#include "absl/types/optional.h" |
1358 |
#include "modules/desktop_capture/desktop_capture_options.h" |
1359 |
#include "modules/desktop_capture/desktop_capturer.h" |
1360 |
#include "rtc_base/constructor_magic.h" |
1361 |
+#include "rtc_base/synchronization/mutex.h" |
1362 |
|
1363 |
namespace webrtc { |
1364 |
|
1365 |
+#if !PW_CHECK_VERSION(0, 3, 0) |
1366 |
class PipeWireType { |
1367 |
public: |
1368 |
spa_type_media_type media_type; |
1369 |
@@ -29,14 +34,25 @@ class PipeWireType { |
1370 |
spa_type_format_video format_video; |
1371 |
spa_type_video_format video_format; |
1372 |
}; |
1373 |
+#endif |
1374 |
|
1375 |
class BaseCapturerPipeWire : public DesktopCapturer { |
1376 |
public: |
1377 |
- enum CaptureSourceType { Screen = 1, Window }; |
1378 |
+ // Values are set based on source type property in |
1379 |
+ // xdg-desktop-portal/screencast |
1380 |
+ // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml |
1381 |
+ enum class CaptureSourceType : uint32_t { |
1382 |
+ kScreen = 0b01, |
1383 |
+ kWindow = 0b10, |
1384 |
+ kAny = 0b11 |
1385 |
+ }; |
1386 |
|
1387 |
explicit BaseCapturerPipeWire(CaptureSourceType source_type); |
1388 |
~BaseCapturerPipeWire() override; |
1389 |
|
1390 |
+ static std::unique_ptr<DesktopCapturer> CreateRawCapturer( |
1391 |
+ const DesktopCaptureOptions& options); |
1392 |
+ |
1393 |
// DesktopCapturer interface. |
1394 |
void Start(Callback* delegate) override; |
1395 |
void CaptureFrame() override; |
1396 |
@@ -45,6 +61,21 @@ class BaseCapturerPipeWire : public DesktopCapturer { |
1397 |
|
1398 |
private: |
1399 |
// PipeWire types --> |
1400 |
+#if PW_CHECK_VERSION(0, 3, 0) |
1401 |
+ struct pw_context* pw_context_ = nullptr; |
1402 |
+ struct pw_core* pw_core_ = nullptr; |
1403 |
+ struct pw_stream* pw_stream_ = nullptr; |
1404 |
+ struct pw_thread_loop* pw_main_loop_ = nullptr; |
1405 |
+ |
1406 |
+ spa_hook spa_core_listener_; |
1407 |
+ spa_hook spa_stream_listener_; |
1408 |
+ |
1409 |
+ // event handlers |
1410 |
+ pw_core_events pw_core_events_ = {}; |
1411 |
+ pw_stream_events pw_stream_events_ = {}; |
1412 |
+ |
1413 |
+ struct spa_video_info_raw spa_video_format_; |
1414 |
+#else |
1415 |
pw_core* pw_core_ = nullptr; |
1416 |
pw_type* pw_core_type_ = nullptr; |
1417 |
pw_stream* pw_stream_ = nullptr; |
1418 |
@@ -60,11 +91,13 @@ class BaseCapturerPipeWire : public DesktopCapturer { |
1419 |
pw_remote_events pw_remote_events_ = {}; |
1420 |
|
1421 |
spa_video_info_raw* spa_video_format_ = nullptr; |
1422 |
+#endif |
1423 |
|
1424 |
+ guint32 pw_stream_node_id_ = 0; |
1425 |
gint32 pw_fd_ = -1; |
1426 |
|
1427 |
CaptureSourceType capture_source_type_ = |
1428 |
- BaseCapturerPipeWire::CaptureSourceType::Screen; |
1429 |
+ BaseCapturerPipeWire::CaptureSourceType::kScreen; |
1430 |
|
1431 |
// <-- end of PipeWire types |
1432 |
|
1433 |
@@ -79,10 +112,12 @@ class BaseCapturerPipeWire : public DesktopCapturer { |
1434 |
guint sources_request_signal_id_ = 0; |
1435 |
guint start_request_signal_id_ = 0; |
1436 |
|
1437 |
+ DesktopSize video_size_; |
1438 |
DesktopSize desktop_size_ = {}; |
1439 |
DesktopCaptureOptions options_ = {}; |
1440 |
|
1441 |
- uint8_t* current_frame_ = nullptr; |
1442 |
+ webrtc::Mutex current_frame_lock_; |
1443 |
+ std::unique_ptr<uint8_t[]> current_frame_; |
1444 |
Callback* callback_ = nullptr; |
1445 |
|
1446 |
bool portal_init_failed_ = false; |
1447 |
@@ -91,21 +126,32 @@ class BaseCapturerPipeWire : public DesktopCapturer { |
1448 |
void InitPipeWire(); |
1449 |
void InitPipeWireTypes(); |
1450 |
|
1451 |
- void CreateReceivingStream(); |
1452 |
+ pw_stream* CreateReceivingStream(); |
1453 |
void HandleBuffer(pw_buffer* buffer); |
1454 |
|
1455 |
void ConvertRGBxToBGRx(uint8_t* frame, uint32_t size); |
1456 |
|
1457 |
+#if PW_CHECK_VERSION(0, 3, 0) |
1458 |
+ static void OnCoreError(void* data, |
1459 |
+ uint32_t id, |
1460 |
+ int seq, |
1461 |
+ int res, |
1462 |
+ const char* message); |
1463 |
+ static void OnStreamParamChanged(void* data, |
1464 |
+ uint32_t id, |
1465 |
+ const struct spa_pod* format); |
1466 |
+#else |
1467 |
static void OnStateChanged(void* data, |
1468 |
pw_remote_state old_state, |
1469 |
pw_remote_state state, |
1470 |
const char* error); |
1471 |
+ static void OnStreamFormatChanged(void* data, const struct spa_pod* format); |
1472 |
+#endif |
1473 |
static void OnStreamStateChanged(void* data, |
1474 |
pw_stream_state old_state, |
1475 |
pw_stream_state state, |
1476 |
const char* error_message); |
1477 |
|
1478 |
- static void OnStreamFormatChanged(void* data, const struct spa_pod* format); |
1479 |
static void OnStreamProcess(void* data); |
1480 |
static void OnNewBuffer(void* data, uint32_t id); |
1481 |
|
1482 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire.sigs b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire02.sigs |
1483 |
similarity index 91% |
1484 |
rename from src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire.sigs |
1485 |
rename to src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire02.sigs |
1486 |
index 3e21e9d..5ac3d1d 100644 |
1487 |
--- a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire.sigs |
1488 |
+++ b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire02.sigs |
1489 |
@@ -26,6 +26,7 @@ void pw_remote_add_listener(pw_remote *remote, spa_hook *listener, const pw_remo |
1490 |
int pw_remote_connect_fd(pw_remote *remote, int fd); |
1491 |
void pw_remote_destroy(pw_remote *remote); |
1492 |
pw_remote * pw_remote_new(pw_core *core, pw_properties *properties, size_t user_data_size); |
1493 |
+enum pw_remote_state pw_remote_get_state(pw_remote *remote, const char **error); |
1494 |
|
1495 |
// stream.h |
1496 |
void pw_stream_add_listener(pw_stream *stream, spa_hook *listener, const pw_stream_events *events, void *data); |
1497 |
@@ -42,3 +43,5 @@ void pw_thread_loop_destroy(pw_thread_loop *loop); |
1498 |
pw_thread_loop * pw_thread_loop_new(pw_loop *loop, const char *name); |
1499 |
int pw_thread_loop_start(pw_thread_loop *loop); |
1500 |
void pw_thread_loop_stop(pw_thread_loop *loop); |
1501 |
+void pw_thread_loop_lock(struct pw_thread_loop *loop); |
1502 |
+void pw_thread_loop_unlock(struct pw_thread_loop *loop); |
1503 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire03.sigs b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire03.sigs |
1504 |
new file mode 100644 |
1505 |
index 0000000..78d241f |
1506 |
--- /dev/null |
1507 |
+++ b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire03.sigs |
1508 |
@@ -0,0 +1,46 @@ |
1509 |
+// Copyright 2018 The WebRTC project authors. All rights reserved. |
1510 |
+// Use of this source code is governed by a BSD-style license that can be |
1511 |
+// found in the LICENSE file. |
1512 |
+ |
1513 |
+//------------------------------------------------ |
1514 |
+// Functions from PipeWire used in capturer code. |
1515 |
+//------------------------------------------------ |
1516 |
+ |
1517 |
+// core.h |
1518 |
+int pw_core_disconnect(pw_core *core); |
1519 |
+ |
1520 |
+// loop.h |
1521 |
+void pw_loop_destroy(pw_loop *loop); |
1522 |
+pw_loop * pw_loop_new(const spa_dict *props); |
1523 |
+ |
1524 |
+ |
1525 |
+// pipewire.h |
1526 |
+void pw_init(int *argc, char **argv[]); |
1527 |
+ |
1528 |
+// properties.h |
1529 |
+pw_properties * pw_properties_new_string(const char *args); |
1530 |
+ |
1531 |
+// stream.h |
1532 |
+void pw_stream_add_listener(pw_stream *stream, spa_hook *listener, const pw_stream_events *events, void *data); |
1533 |
+int pw_stream_connect(pw_stream *stream, enum pw_direction direction, uint32_t target_id, enum pw_stream_flags flags, const spa_pod **params, uint32_t n_params); |
1534 |
+pw_buffer *pw_stream_dequeue_buffer(pw_stream *stream); |
1535 |
+void pw_stream_destroy(pw_stream *stream); |
1536 |
+pw_stream * pw_stream_new(pw_core *core, const char *name, pw_properties *props); |
1537 |
+int pw_stream_queue_buffer(pw_stream *stream, pw_buffer *buffer); |
1538 |
+int pw_stream_set_active(pw_stream *stream, bool active); |
1539 |
+int pw_stream_update_params(pw_stream *stream, const spa_pod **params, uint32_t n_params); |
1540 |
+ |
1541 |
+// thread-loop.h |
1542 |
+void pw_thread_loop_destroy(pw_thread_loop *loop); |
1543 |
+pw_thread_loop * pw_thread_loop_new(const char *name, const spa_dict *props); |
1544 |
+int pw_thread_loop_start(pw_thread_loop *loop); |
1545 |
+void pw_thread_loop_stop(pw_thread_loop *loop); |
1546 |
+void pw_thread_loop_lock(pw_thread_loop *loop); |
1547 |
+void pw_thread_loop_unlock(pw_thread_loop *loop); |
1548 |
+pw_loop * pw_thread_loop_get_loop(pw_thread_loop *loop); |
1549 |
+ |
1550 |
+ |
1551 |
+// context.h |
1552 |
+void pw_context_destroy(pw_context *context); |
1553 |
+pw_context *pw_context_new(pw_loop *main_loop, pw_properties *props, size_t user_data_size); |
1554 |
+pw_core * pw_context_connect(pw_context *context, pw_properties *properties, size_t user_data_size); |
1555 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc |
1556 |
deleted file mode 100644 |
1557 |
index fe67214..0000000 |
1558 |
--- a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc |
1559 |
+++ /dev/null |
1560 |
@@ -1,29 +0,0 @@ |
1561 |
-/* |
1562 |
- * Copyright 2018 The WebRTC project authors. All Rights Reserved. |
1563 |
- * |
1564 |
- * Use of this source code is governed by a BSD-style license |
1565 |
- * that can be found in the LICENSE file in the root of the source |
1566 |
- * tree. An additional intellectual property rights grant can be found |
1567 |
- * in the file PATENTS. All contributing project authors may |
1568 |
- * be found in the AUTHORS file in the root of the source tree. |
1569 |
- */ |
1570 |
- |
1571 |
-#include "modules/desktop_capture/linux/screen_capturer_pipewire.h" |
1572 |
- |
1573 |
-#include <memory> |
1574 |
- |
1575 |
- |
1576 |
-namespace webrtc { |
1577 |
- |
1578 |
-ScreenCapturerPipeWire::ScreenCapturerPipeWire() |
1579 |
- : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Screen) {} |
1580 |
-ScreenCapturerPipeWire::~ScreenCapturerPipeWire() {} |
1581 |
- |
1582 |
-// static |
1583 |
-std::unique_ptr<DesktopCapturer> |
1584 |
-ScreenCapturerPipeWire::CreateRawScreenCapturer( |
1585 |
- const DesktopCaptureOptions& options) { |
1586 |
- return std::make_unique<ScreenCapturerPipeWire>(); |
1587 |
-} |
1588 |
- |
1589 |
-} // namespace webrtc |
1590 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.h b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.h |
1591 |
deleted file mode 100644 |
1592 |
index 66dcd68..0000000 |
1593 |
--- a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.h |
1594 |
+++ /dev/null |
1595 |
@@ -1,33 +0,0 @@ |
1596 |
-/* |
1597 |
- * Copyright 2018 The WebRTC project authors. All Rights Reserved. |
1598 |
- * |
1599 |
- * Use of this source code is governed by a BSD-style license |
1600 |
- * that can be found in the LICENSE file in the root of the source |
1601 |
- * tree. An additional intellectual property rights grant can be found |
1602 |
- * in the file PATENTS. All contributing project authors may |
1603 |
- * be found in the AUTHORS file in the root of the source tree. |
1604 |
- */ |
1605 |
- |
1606 |
-#ifndef MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_PIPEWIRE_H_ |
1607 |
-#define MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_PIPEWIRE_H_ |
1608 |
- |
1609 |
-#include <memory> |
1610 |
- |
1611 |
-#include "modules/desktop_capture/linux/base_capturer_pipewire.h" |
1612 |
- |
1613 |
-namespace webrtc { |
1614 |
- |
1615 |
-class ScreenCapturerPipeWire : public BaseCapturerPipeWire { |
1616 |
- public: |
1617 |
- ScreenCapturerPipeWire(); |
1618 |
- ~ScreenCapturerPipeWire() override; |
1619 |
- |
1620 |
- static std::unique_ptr<DesktopCapturer> CreateRawScreenCapturer( |
1621 |
- const DesktopCaptureOptions& options); |
1622 |
- |
1623 |
- RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerPipeWire); |
1624 |
-}; |
1625 |
- |
1626 |
-} // namespace webrtc |
1627 |
- |
1628 |
-#endif // MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_PIPEWIRE_H_ |
1629 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc |
1630 |
deleted file mode 100644 |
1631 |
index b455915..0000000 |
1632 |
--- a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc |
1633 |
+++ /dev/null |
1634 |
@@ -1,29 +0,0 @@ |
1635 |
-/* |
1636 |
- * Copyright 2018 The WebRTC project authors. All Rights Reserved. |
1637 |
- * |
1638 |
- * Use of this source code is governed by a BSD-style license |
1639 |
- * that can be found in the LICENSE file in the root of the source |
1640 |
- * tree. An additional intellectual property rights grant can be found |
1641 |
- * in the file PATENTS. All contributing project authors may |
1642 |
- * be found in the AUTHORS file in the root of the source tree. |
1643 |
- */ |
1644 |
- |
1645 |
-#include "modules/desktop_capture/linux/window_capturer_pipewire.h" |
1646 |
- |
1647 |
-#include <memory> |
1648 |
- |
1649 |
- |
1650 |
-namespace webrtc { |
1651 |
- |
1652 |
-WindowCapturerPipeWire::WindowCapturerPipeWire() |
1653 |
- : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Window) {} |
1654 |
-WindowCapturerPipeWire::~WindowCapturerPipeWire() {} |
1655 |
- |
1656 |
-// static |
1657 |
-std::unique_ptr<DesktopCapturer> |
1658 |
-WindowCapturerPipeWire::CreateRawWindowCapturer( |
1659 |
- const DesktopCaptureOptions& options) { |
1660 |
- return std::make_unique<WindowCapturerPipeWire>(); |
1661 |
-} |
1662 |
- |
1663 |
-} // namespace webrtc |
1664 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.h b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.h |
1665 |
deleted file mode 100644 |
1666 |
index 7f184ef..0000000 |
1667 |
--- a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.h |
1668 |
+++ /dev/null |
1669 |
@@ -1,33 +0,0 @@ |
1670 |
-/* |
1671 |
- * Copyright 2018 The WebRTC project authors. All Rights Reserved. |
1672 |
- * |
1673 |
- * Use of this source code is governed by a BSD-style license |
1674 |
- * that can be found in the LICENSE file in the root of the source |
1675 |
- * tree. An additional intellectual property rights grant can be found |
1676 |
- * in the file PATENTS. All contributing project authors may |
1677 |
- * be found in the AUTHORS file in the root of the source tree. |
1678 |
- */ |
1679 |
- |
1680 |
-#ifndef MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_PIPEWIRE_H_ |
1681 |
-#define MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_PIPEWIRE_H_ |
1682 |
- |
1683 |
-#include <memory> |
1684 |
- |
1685 |
-#include "modules/desktop_capture/linux/base_capturer_pipewire.h" |
1686 |
- |
1687 |
-namespace webrtc { |
1688 |
- |
1689 |
-class WindowCapturerPipeWire : public BaseCapturerPipeWire { |
1690 |
- public: |
1691 |
- WindowCapturerPipeWire(); |
1692 |
- ~WindowCapturerPipeWire() override; |
1693 |
- |
1694 |
- static std::unique_ptr<DesktopCapturer> CreateRawWindowCapturer( |
1695 |
- const DesktopCaptureOptions& options); |
1696 |
- |
1697 |
- RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerPipeWire); |
1698 |
-}; |
1699 |
- |
1700 |
-} // namespace webrtc |
1701 |
- |
1702 |
-#endif // MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_PIPEWIRE_H_ |
1703 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/screen_capturer_linux.cc b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/screen_capturer_linux.cc |
1704 |
index 82dbae4..ed48b7d 100644 |
1705 |
--- a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/screen_capturer_linux.cc |
1706 |
+++ b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/screen_capturer_linux.cc |
1707 |
@@ -14,7 +14,7 @@ |
1708 |
#include "modules/desktop_capture/desktop_capturer.h" |
1709 |
|
1710 |
#if defined(WEBRTC_USE_PIPEWIRE) |
1711 |
-#include "modules/desktop_capture/linux/screen_capturer_pipewire.h" |
1712 |
+#include "modules/desktop_capture/linux/base_capturer_pipewire.h" |
1713 |
#endif // defined(WEBRTC_USE_PIPEWIRE) |
1714 |
|
1715 |
#if defined(WEBRTC_USE_X11) |
1716 |
@@ -28,7 +28,7 @@ std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawScreenCapturer( |
1717 |
const DesktopCaptureOptions& options) { |
1718 |
#if defined(WEBRTC_USE_PIPEWIRE) |
1719 |
if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { |
1720 |
- return ScreenCapturerPipeWire::CreateRawScreenCapturer(options); |
1721 |
+ return BaseCapturerPipeWire::CreateRawCapturer(options); |
1722 |
} |
1723 |
#endif // defined(WEBRTC_USE_PIPEWIRE) |
1724 |
|
1725 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/window_capturer_linux.cc b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/window_capturer_linux.cc |
1726 |
index 41dbf83..2b142ae 100644 |
1727 |
--- a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/window_capturer_linux.cc |
1728 |
+++ b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/window_capturer_linux.cc |
1729 |
@@ -14,7 +14,7 @@ |
1730 |
#include "modules/desktop_capture/desktop_capturer.h" |
1731 |
|
1732 |
#if defined(WEBRTC_USE_PIPEWIRE) |
1733 |
-#include "modules/desktop_capture/linux/window_capturer_pipewire.h" |
1734 |
+#include "modules/desktop_capture/linux/base_capturer_pipewire.h" |
1735 |
#endif // defined(WEBRTC_USE_PIPEWIRE) |
1736 |
|
1737 |
#if defined(WEBRTC_USE_X11) |
1738 |
@@ -28,7 +28,7 @@ std::unique_ptr<DesktopCapturer> DesktopCapturer::CreateRawWindowCapturer( |
1739 |
const DesktopCaptureOptions& options) { |
1740 |
#if defined(WEBRTC_USE_PIPEWIRE) |
1741 |
if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { |
1742 |
- return WindowCapturerPipeWire::CreateRawWindowCapturer(options); |
1743 |
+ return BaseCapturerPipeWire::CreateRawCapturer(options); |
1744 |
} |
1745 |
#endif // defined(WEBRTC_USE_PIPEWIRE) |
1746 |
|
1747 |
diff --git a/src/3rdparty/chromium/third_party/webrtc/webrtc.gni b/src/3rdparty/chromium/third_party/webrtc/webrtc.gni |
1748 |
index ca8acdb..505c975 100644 |
1749 |
--- a/src/3rdparty/chromium/third_party/webrtc/webrtc.gni |
1750 |
+++ b/src/3rdparty/chromium/third_party/webrtc/webrtc.gni |
1751 |
@@ -117,6 +117,10 @@ declare_args() { |
1752 |
# Set this to link PipeWire directly instead of using the dlopen. |
1753 |
rtc_link_pipewire = false |
1754 |
|
1755 |
+ # Set this to use certain PipeWire version |
1756 |
+ # Currently we support PipeWire 0.2 (default) and PipeWire 0.3 |
1757 |
+ rtc_pipewire_version = "0.3" |
1758 |
+ |
1759 |
# Enable to use the Mozilla internal settings. |
1760 |
build_with_mozilla = false |
1761 |
|
1762 |
-- |
1763 |
2.37.3 |
1764 |
|