Control: tags -1 moreinfo On 2023-03-11 21:04:14 +0300, Dmitry Shachnev wrote: > Package: release.debian.org > Severity: wishlist > > Dear Release Team, > > Qt WebEngine 5.15 LTS branch has a new patch release, 5.15.13. > > It mostly contains backports for security fixes from upstream Chromium, > and some other minor fixes. > > This particular release does not have any ABI changes, but per our > team practice we bump the name of provided virtual ABI package from > qtwebengine-abi-5-15-12 to qtwebengine-abi-5-15-13. This will require a > no-change rebuild of two reverse dependencies (qtwebview-opensource-src > and angelfish). Is that acceptable for bookworm?
Do both reverse dependencies build fine with the new version of qtwebengine-opensource-src? > I am attaching a git diff of my packaging and an upstream git diff. > Upstream diff is large, but it's mostly security/CVE fixes, as can be > seen in the commit messages (the relevant commits are starting from > 2022-12-22): > > https://code.qt.io/cgit/qt/qtwebengine-chromium.git/log/?h=87-based > > I have also included a patch from bug #1005824 to build with pipewire > support. If a new release is acceptable but that patch is not, I can > remove it. We are past the point of adding new features. Please postpone this change to trixie. Cheers > > -- > Dmitry Shachnev > diff --git a/debian/changelog b/debian/changelog > index 9f4762d..afa565a 100644 > --- a/debian/changelog > +++ b/debian/changelog > @@ -1,3 +1,19 @@ > +qtwebengine-opensource-src (5.15.13+dfsg-1) UNRELEASED; urgency=medium > + > + [ Dmitry Shachnev ] > + * New upstream release. > + * Update SUBMODULE_COMMIT for the new release. > + * Remove copyright section for debian/missing-sources/jszip-2.4.0. > + * Build with pipewire support (closes: #1005824). > + - Backport upstream patch to improve screen sharing with PipeWire > + on Wayland and to add support for PipeWire 0.3. > + - Thanks Pirate Praveen and C�dric Hannotier! > + * Bump ABI version to qtwebengine-abi-5-15-13. > + * Drop gcc-12.patch, included in the new release. > + * Refresh debian/patches/python3.patch. > + > + -- Debian Qt/KDE Maintainers <debian-qt-...@lists.debian.org> Sat, 11 Feb > 2023 13:19:26 +0400 > + > qtwebengine-opensource-src (5.15.12+dfsg-3) unstable; urgency=medium > > * Add debian/90qtwebengine-dictionaries-path.conf. > diff --git a/debian/control b/debian/control > index 827e12c..72d1c65 100644 > --- a/debian/control > +++ b/debian/control > @@ -39,6 +39,7 @@ Build-Depends: binutils (>= 2.32-8~), > libopenjp2-7-dev, > libopus-dev (>= 1.3.1), > libpci-dev, > + libpipewire-0.3-dev, > libpng-dev, > libprotobuf-dev, > libpulse-dev, > @@ -158,7 +159,7 @@ Description: Web content engine library for Qt > Package: libqt5webenginecore5 > Architecture: amd64 arm64 armhf i386 mips64el mipsel > Multi-Arch: same > -Provides: qtwebengine-abi-5-15-12 > +Provides: qtwebengine-abi-5-15-13 > Depends: libqt5webengine-data (= ${source:Version}), > sse2-support [i386], > ${misc:Depends}, > diff --git a/debian/copyright b/debian/copyright > index 01fc92e..f8e99e9 100644 > --- a/debian/copyright > +++ b/debian/copyright > @@ -120,10 +120,6 @@ Files: src/3rdparty/ninja/* > Copyright: 2011-2018 Google Inc. > License: Apache-2.0 > > -Files: debian/missing-sources/jszip-2.4.0/* > -Copyright: 2009-2014 Stuart Knightley, David Duponchel, Franz Buchinger, > Ant�nio Afonso > -License: MIT or GPL-3 > - > ## BEGIN AUTO GENERATED BLOCK > > Files: examples/webengine/quicknanobrowser/icons/3rdparty/* > diff --git a/debian/libqt5webengine5.symbols b/debian/libqt5webengine5.symbols > index 2dcf53f..a555804 100644 > --- a/debian/libqt5webengine5.symbols > +++ b/debian/libqt5webengine5.symbols > @@ -1,6 +1,6 @@ > # SymbolsHelper-Confirmed: 5.15.5 amd64 > libQt5WebEngine.so.5 libqt5webengine5 #MINVER# > -| libqt5webengine5 #MINVER#, qtwebengine-abi-5-15-12 > +| libqt5webengine5 #MINVER#, qtwebengine-abi-5-15-13 > * Build-Depends-Package: qtwebengine5-dev > Qt_5.0@Qt_5.0 5.7.1 > Qt_5.10@Qt_5.10 5.10.1 > diff --git a/debian/libqt5webenginecore5.symbols > b/debian/libqt5webenginecore5.symbols > index 286c991..58e1462 100644 > --- a/debian/libqt5webenginecore5.symbols > +++ b/debian/libqt5webenginecore5.symbols > @@ -1,6 +1,6 @@ > # SymbolsHelper-Confirmed: 5.15.10 amd64 arm64 armhf i386 mips64el mipsel > libQt5WebEngineCore.so.5 libqt5webenginecore5 #MINVER# > -| libqt5webenginecore5 #MINVER#, qtwebengine-abi-5-15-12 > +| libqt5webenginecore5 #MINVER#, qtwebengine-abi-5-15-13 > * Build-Depends-Package: qtwebengine5-dev > (optional=gold)Qt_5.0@Qt_5.0 5.7.1 > (optional=gold)Qt_5.10@Qt_5.10 5.10.1 > diff --git a/debian/libqt5webenginewidgets5.symbols > b/debian/libqt5webenginewidgets5.symbols > index ec9760b..4773255 100644 > --- a/debian/libqt5webenginewidgets5.symbols > +++ b/debian/libqt5webenginewidgets5.symbols > @@ -1,6 +1,6 @@ > # SymbolsHelper-Confirmed: 5.15.3 amd64 mips64el > libQt5WebEngineWidgets.so.5 libqt5webenginewidgets5 #MINVER# > -| libqt5webenginewidgets5 #MINVER#, qtwebengine-abi-5-15-12 > +| libqt5webenginewidgets5 #MINVER#, qtwebengine-abi-5-15-13 > * Build-Depends-Package: qtwebengine5-dev > Qt_5.0@Qt_5.0 5.7.1 > Qt_5.10@Qt_5.10 5.10.1 > diff --git a/debian/patches/gcc-12.patch b/debian/patches/gcc-12.patch > deleted file mode 100644 > index c7f43fe..0000000 > --- a/debian/patches/gcc-12.patch > +++ /dev/null > @@ -1,15 +0,0 @@ > -Description: fix build with GCC 12 > -Origin: upstream skia, > https://chromium.googlesource.com/skia/+/cd397f3c4738beb6 > -Last-Update: 2022-06-26 > - > ---- a/src/3rdparty/chromium/third_party/skia/src/utils/SkParseColor.cpp > -+++ b/src/3rdparty/chromium/third_party/skia/src/utils/SkParseColor.cpp > -@@ -8,6 +8,8 @@ > - > - #include "include/utils/SkParse.h" > - > -+#include <iterator> > -+ > - static constexpr const char* gColorNames[] = { > - "aliceblue", > - "antiquewhite", > diff --git a/debian/patches/pipewire-0.3.patch > b/debian/patches/pipewire-0.3.patch > new file mode 100644 > index 0000000..7854392 > --- /dev/null > +++ b/debian/patches/pipewire-0.3.patch > @@ -0,0 +1,1792 @@ > +Description: add support for PipeWire 0.3 > +Origin: upstream webrtc, commits: > + - https://webrtc.googlesource.com/src/+/40c3ea5c7146cb7e > + - https://webrtc.googlesource.com/src/+/c3c81297365b6a29 > +Bug: https://bugs.debian.org/1005824 > +Last-Update: 2023-02-11 > + > +--- > a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/BUILD.gn > ++++ > b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/BUILD.gn > +@@ -11,6 +11,11 @@ import("//build/config/ui.gni") > + import("//tools/generate_stubs/rules.gni") > + import("../../webrtc.gni") > + > ++if (rtc_use_pipewire) { > ++ assert(rtc_pipewire_version == "0.2" || rtc_pipewire_version == "0.3", > ++ "Unsupported PipeWire version") > ++} > ++ > + use_desktop_capture_differ_sse2 = current_cpu == "x86" || current_cpu == > "x64" > + > + config("x11_config") { > +@@ -200,22 +205,41 @@ if (is_linux || is_chromeos) { > + ] > + } > + > +- if (rtc_link_pipewire) { > ++ if (rtc_pipewire_version == "0.3") { > + pkg_config("pipewire") { > +- packages = [ "libpipewire-0.2" ] > ++ packages = [ "libpipewire-0.3" ] > ++ if (!rtc_link_pipewire) { > ++ ignore_libs = true > ++ } > + } > + } else { > ++ pkg_config("pipewire") { > ++ packages = [ "libpipewire-0.2" ] > ++ if (!rtc_link_pipewire) { > ++ ignore_libs = true > ++ } > ++ } > ++ } > ++ > ++ if (!rtc_link_pipewire) { > + # When libpipewire is not directly linked, use stubs to allow for > dlopening of > + # the binary. > + generate_stubs("pipewire_stubs") { > +- configs = [ "../../:common_config" ] > ++ configs = [ > ++ "../../:common_config", > ++ ":pipewire", > ++ ] > + deps = [ "../../rtc_base" ] > + extra_header = "linux/pipewire_stub_header.fragment" > + logging_function = "RTC_LOG(LS_VERBOSE)" > + logging_include = "rtc_base/logging.h" > + output_name = "linux/pipewire_stubs" > + path_from_source = "modules/desktop_capture/linux" > +- sigs = [ "linux/pipewire.sigs" ] > ++ if (rtc_pipewire_version == "0.3") { > ++ sigs = [ "linux/pipewire03.sigs" ] > ++ } else { > ++ sigs = [ "linux/pipewire02.sigs" ] > ++ } > + } > + } > + > +@@ -506,6 +530,7 @@ rtc_library("desktop_capture_generic") { > + absl_deps = [ > + "//third_party/abseil-cpp/absl/memory", > + "//third_party/abseil-cpp/absl/strings", > ++ "//third_party/abseil-cpp/absl/types:optional", > + ] > + > + if (rtc_use_x11_extensions) { > +@@ -526,20 +551,15 @@ rtc_library("desktop_capture_generic") { > + sources += [ > + "linux/base_capturer_pipewire.cc", > + "linux/base_capturer_pipewire.h", > +- "linux/screen_capturer_pipewire.cc", > +- "linux/screen_capturer_pipewire.h", > +- "linux/window_capturer_pipewire.cc", > +- "linux/window_capturer_pipewire.h", > + ] > + > + configs += [ > + ":pipewire_config", > + ":gio", > ++ ":pipewire", > + ] > + > +- if (rtc_link_pipewire) { > +- configs += [ ":pipewire" ] > +- } else { > ++ if (!rtc_link_pipewire) { > + deps += [ ":pipewire_stubs" ] > + } > + } > +--- > 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 > +@@ -14,8 +14,14 @@ > + #include <glib-object.h> > + #include <spa/param/format-utils.h> > + #include <spa/param/props.h> > ++#if !PW_CHECK_VERSION(0, 3, 0) > + #include <spa/param/video/raw-utils.h> > + #include <spa/support/type-map.h> > ++#endif > ++ > ++#include <sys/ioctl.h> > ++#include <sys/mman.h> > ++#include <sys/syscall.h> > + > + #include <memory> > + #include <utility> > +@@ -30,7 +36,11 @@ > + #include "modules/desktop_capture/linux/pipewire_stubs.h" > + > + using modules_desktop_capture_linux::InitializeStubs; > +-using modules_desktop_capture_linux::kModulePipewire; > ++#if PW_CHECK_VERSION(0, 3, 0) > ++using modules_desktop_capture_linux::kModulePipewire03; > ++#else > ++using modules_desktop_capture_linux::kModulePipewire02; > ++#endif > + using modules_desktop_capture_linux::StubPathMap; > + #endif // defined(WEBRTC_DLOPEN_PIPEWIRE) > + > +@@ -47,10 +57,157 @@ const char kScreenCastInterfaceName[] = > + const int kBytesPerPixel = 4; > + > + #if defined(WEBRTC_DLOPEN_PIPEWIRE) > ++#if PW_CHECK_VERSION(0, 3, 0) > ++const char kPipeWireLib[] = "libpipewire-0.3.so.0"; > ++#else > + const char kPipeWireLib[] = "libpipewire-0.2.so.1"; > + #endif > ++#endif > + > + // static > ++struct dma_buf_sync { > ++ uint64_t flags; > ++}; > ++#define DMA_BUF_SYNC_READ (1 << 0) > ++#define DMA_BUF_SYNC_START (0 << 2) > ++#define DMA_BUF_SYNC_END (1 << 2) > ++#define DMA_BUF_BASE 'b' > ++#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) > ++ > ++static void SyncDmaBuf(int fd, uint64_t start_or_end) { > ++ struct dma_buf_sync sync = {0}; > ++ > ++ sync.flags = start_or_end | DMA_BUF_SYNC_READ; > ++ > ++ while (true) { > ++ int ret; > ++ ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync); > ++ if (ret == -1 && errno == EINTR) { > ++ continue; > ++ } else if (ret == -1) { > ++ RTC_LOG(LS_ERROR) << "Failed to synchronize DMA buffer: " > ++ << g_strerror(errno); > ++ break; > ++ } else { > ++ break; > ++ } > ++ } > ++} > ++ > ++class ScopedBuf { > ++ public: > ++ ScopedBuf() {} > ++ ScopedBuf(unsigned char* map, int map_size, bool is_dma_buf, int fd) > ++ : map_(map), map_size_(map_size), is_dma_buf_(is_dma_buf), fd_(fd) {} > ++ ~ScopedBuf() { > ++ if (map_ != MAP_FAILED) { > ++ if (is_dma_buf_) { > ++ SyncDmaBuf(fd_, DMA_BUF_SYNC_END); > ++ } > ++ munmap(map_, map_size_); > ++ } > ++ } > ++ > ++ operator bool() { return map_ != MAP_FAILED; } > ++ > ++ void initialize(unsigned char* map, int map_size, bool is_dma_buf, int > fd) { > ++ map_ = map; > ++ map_size_ = map_size; > ++ is_dma_buf_ = is_dma_buf; > ++ fd_ = fd; > ++ } > ++ > ++ unsigned char* get() { return map_; } > ++ > ++ protected: > ++ unsigned char* map_ = nullptr; > ++ int map_size_; > ++ bool is_dma_buf_; > ++ int fd_; > ++}; > ++ > ++template <class T> > ++class Scoped { > ++ public: > ++ Scoped() {} > ++ explicit Scoped(T* val) { ptr_ = val; } > ++ ~Scoped() { RTC_NOTREACHED(); } > ++ > ++ T* operator->() { return ptr_; } > ++ > ++ bool operator!() { return ptr_ == nullptr; } > ++ > ++ T* get() { return ptr_; } > ++ > ++ T** receive() { > ++ RTC_CHECK(!ptr_); > ++ return &ptr_; > ++ } > ++ > ++ Scoped& operator=(T* val) { > ++ ptr_ = val; > ++ return *this; > ++ } > ++ > ++ protected: > ++ T* ptr_ = nullptr; > ++}; > ++ > ++template <> > ++Scoped<GError>::~Scoped() { > ++ if (ptr_) { > ++ g_error_free(ptr_); > ++ } > ++} > ++ > ++template <> > ++Scoped<gchar>::~Scoped() { > ++ if (ptr_) { > ++ g_free(ptr_); > ++ } > ++} > ++ > ++template <> > ++Scoped<GVariant>::~Scoped() { > ++ if (ptr_) { > ++ g_variant_unref(ptr_); > ++ } > ++} > ++ > ++template <> > ++Scoped<GVariantIter>::~Scoped() { > ++ if (ptr_) { > ++ g_variant_iter_free(ptr_); > ++ } > ++} > ++ > ++template <> > ++Scoped<GDBusMessage>::~Scoped() { > ++ if (ptr_) { > ++ g_object_unref(ptr_); > ++ } > ++} > ++ > ++template <> > ++Scoped<GUnixFDList>::~Scoped() { > ++ if (ptr_) { > ++ g_object_unref(ptr_); > ++ } > ++} > ++ > ++#if PW_CHECK_VERSION(0, 3, 0) > ++void BaseCapturerPipeWire::OnCoreError(void* data, > ++ uint32_t id, > ++ int seq, > ++ int res, > ++ const char* message) { > ++ BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); > ++ RTC_DCHECK(that); > ++ > ++ RTC_LOG(LS_ERROR) << "PipeWire remote error: " << message; > ++} > ++#else > ++// static > + void BaseCapturerPipeWire::OnStateChanged(void* data, > + pw_remote_state old_state, > + pw_remote_state state, > +@@ -64,7 +221,7 @@ void BaseCapturerPipeWire::OnStateChange > + break; > + case PW_REMOTE_STATE_CONNECTED: > + RTC_LOG(LS_INFO) << "PipeWire remote state: connected."; > +- that->CreateReceivingStream(); > ++ that->pw_stream_ = that->CreateReceivingStream(); > + break; > + case PW_REMOTE_STATE_CONNECTING: > + RTC_LOG(LS_INFO) << "PipeWire remote state: connecting."; > +@@ -74,6 +231,7 @@ void BaseCapturerPipeWire::OnStateChange > + break; > + } > + } > ++#endif > + > + // static > + void BaseCapturerPipeWire::OnStreamStateChanged(void* data, > +@@ -83,6 +241,18 @@ void BaseCapturerPipeWire::OnStreamState > + BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); > + RTC_DCHECK(that); > + > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ switch (state) { > ++ case PW_STREAM_STATE_ERROR: > ++ RTC_LOG(LS_ERROR) << "PipeWire stream state error: " << error_message; > ++ break; > ++ case PW_STREAM_STATE_PAUSED: > ++ case PW_STREAM_STATE_STREAMING: > ++ case PW_STREAM_STATE_UNCONNECTED: > ++ case PW_STREAM_STATE_CONNECTING: > ++ break; > ++ } > ++#else > + switch (state) { > + case PW_STREAM_STATE_ERROR: > + RTC_LOG(LS_ERROR) << "PipeWire stream state error: " << error_message; > +@@ -97,36 +267,74 @@ void BaseCapturerPipeWire::OnStreamState > + case PW_STREAM_STATE_STREAMING: > + break; > + } > ++#endif > + } > + > + // static > ++#if PW_CHECK_VERSION(0, 3, 0) > ++void BaseCapturerPipeWire::OnStreamParamChanged(void* data, > ++ uint32_t id, > ++ const struct spa_pod* > format) { > ++#else > + void BaseCapturerPipeWire::OnStreamFormatChanged(void* data, > + const struct spa_pod* > format) { > ++#endif > + BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); > + RTC_DCHECK(that); > + > + RTC_LOG(LS_INFO) << "PipeWire stream format changed."; > + > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ if (!format || id != SPA_PARAM_Format) { > ++#else > + if (!format) { > + pw_stream_finish_format(that->pw_stream_, /*res=*/0, /*params=*/nullptr, > + /*n_params=*/0); > ++#endif > + return; > + } > + > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ spa_format_video_raw_parse(format, &that->spa_video_format_); > ++#else > + that->spa_video_format_ = new spa_video_info_raw(); > + spa_format_video_raw_parse(format, that->spa_video_format_, > + &that->pw_type_->format_video); > ++#endif > + > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ auto width = that->spa_video_format_.size.width; > ++ auto height = that->spa_video_format_.size.height; > ++#else > + auto width = that->spa_video_format_->size.width; > + auto height = that->spa_video_format_->size.height; > ++#endif > + auto stride = SPA_ROUND_UP_N(width * kBytesPerPixel, 4); > + auto size = height * stride; > + > ++ that->desktop_size_ = DesktopSize(width, height); > ++ > + uint8_t buffer[1024] = {}; > + auto builder = spa_pod_builder{buffer, sizeof(buffer)}; > + > + // Setup buffers and meta header for new format. > +- const struct spa_pod* params[2]; > ++ const struct spa_pod* params[3]; > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_add_object( > ++ &builder, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, > ++ SPA_PARAM_BUFFERS_size, SPA_POD_Int(size), SPA_PARAM_BUFFERS_stride, > ++ SPA_POD_Int(stride), SPA_PARAM_BUFFERS_buffers, > ++ SPA_POD_CHOICE_RANGE_Int(8, 1, 32))); > ++ params[1] = reinterpret_cast<spa_pod*>(spa_pod_builder_add_object( > ++ &builder, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, > SPA_PARAM_META_type, > ++ SPA_POD_Id(SPA_META_Header), SPA_PARAM_META_size, > ++ SPA_POD_Int(sizeof(struct spa_meta_header)))); > ++ params[2] = reinterpret_cast<spa_pod*>(spa_pod_builder_add_object( > ++ &builder, SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, > SPA_PARAM_META_type, > ++ SPA_POD_Id(SPA_META_VideoCrop), SPA_PARAM_META_size, > ++ SPA_POD_Int(sizeof(struct spa_meta_region)))); > ++ pw_stream_update_params(that->pw_stream_, params, 3); > ++#else > + params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_object( > + &builder, > + // id to enumerate buffer requirements > +@@ -155,8 +363,18 @@ void BaseCapturerPipeWire::OnStreamForma > + // Size: size of the metadata, specified as integer (i) > + ":", that->pw_core_type_->param_meta.size, "i", > + sizeof(struct spa_meta_header))); > +- > +- pw_stream_finish_format(that->pw_stream_, /*res=*/0, params, > /*n_params=*/2); > ++ params[2] = reinterpret_cast<spa_pod*>(spa_pod_builder_object( > ++ &builder, > ++ // id to enumerate supported metadata > ++ that->pw_core_type_->param.idMeta, > that->pw_core_type_->param_meta.Meta, > ++ // Type: specified as id or enum (I) > ++ ":", that->pw_core_type_->param_meta.type, "I", > ++ that->pw_core_type_->meta.VideoCrop, > ++ // Size: size of the metadata, specified as integer (i) > ++ ":", that->pw_core_type_->param_meta.size, "i", > ++ sizeof(struct spa_meta_video_crop))); > ++ pw_stream_finish_format(that->pw_stream_, /*res=*/0, params, > /*n_params=*/3); > ++#endif > + } > + > + // static > +@@ -164,15 +382,26 @@ void BaseCapturerPipeWire::OnStreamProce > + BaseCapturerPipeWire* that = static_cast<BaseCapturerPipeWire*>(data); > + RTC_DCHECK(that); > + > +- pw_buffer* buf = nullptr; > ++ struct pw_buffer* next_buffer; > ++ struct pw_buffer* buffer = nullptr; > + > +- if (!(buf = pw_stream_dequeue_buffer(that->pw_stream_))) { > ++ next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); > ++ while (next_buffer) { > ++ buffer = next_buffer; > ++ next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); > ++ > ++ if (next_buffer) { > ++ pw_stream_queue_buffer(that->pw_stream_, buffer); > ++ } > ++ } > ++ > ++ if (!buffer) { > + return; > + } > + > +- that->HandleBuffer(buf); > ++ that->HandleBuffer(buffer); > + > +- pw_stream_queue_buffer(that->pw_stream_, buf); > ++ pw_stream_queue_buffer(that->pw_stream_, buffer); > + } > + > + BaseCapturerPipeWire::BaseCapturerPipeWire(CaptureSourceType source_type) > +@@ -183,6 +412,7 @@ BaseCapturerPipeWire::~BaseCapturerPipeW > + pw_thread_loop_stop(pw_main_loop_); > + } > + > ++#if !PW_CHECK_VERSION(0, 3, 0) > + if (pw_type_) { > + delete pw_type_; > + } > +@@ -190,30 +420,41 @@ BaseCapturerPipeWire::~BaseCapturerPipeW > + if (spa_video_format_) { > + delete spa_video_format_; > + } > ++#endif > + > + if (pw_stream_) { > + pw_stream_destroy(pw_stream_); > + } > + > ++#if !PW_CHECK_VERSION(0, 3, 0) > + if (pw_remote_) { > + pw_remote_destroy(pw_remote_); > + } > ++#endif > + > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ if (pw_core_) { > ++ pw_core_disconnect(pw_core_); > ++ } > ++ > ++ if (pw_context_) { > ++ pw_context_destroy(pw_context_); > ++ } > ++#else > + if (pw_core_) { > + pw_core_destroy(pw_core_); > + } > ++#endif > + > + if (pw_main_loop_) { > + pw_thread_loop_destroy(pw_main_loop_); > + } > + > ++#if !PW_CHECK_VERSION(0, 3, 0) > + if (pw_loop_) { > + pw_loop_destroy(pw_loop_); > + } > +- > +- if (current_frame_) { > +- free(current_frame_); > +- } > ++#endif > + > + if (start_request_signal_id_) { > + g_dbus_connection_signal_unsubscribe(connection_, > start_request_signal_id_); > +@@ -228,18 +469,16 @@ BaseCapturerPipeWire::~BaseCapturerPipeW > + } > + > + if (session_handle_) { > +- GDBusMessage* message = g_dbus_message_new_method_call( > +- kDesktopBusName, session_handle_, kSessionInterfaceName, "Close"); > +- if (message) { > +- GError* error = nullptr; > +- g_dbus_connection_send_message(connection_, message, > ++ Scoped<GDBusMessage> message(g_dbus_message_new_method_call( > ++ kDesktopBusName, session_handle_, kSessionInterfaceName, "Close")); > ++ if (message.get()) { > ++ Scoped<GError> error; > ++ g_dbus_connection_send_message(connection_, message.get(), > + G_DBUS_SEND_MESSAGE_FLAGS_NONE, > +- /*out_serial=*/nullptr, &error); > +- if (error) { > ++ /*out_serial=*/nullptr, > error.receive()); > ++ if (error.get()) { > + RTC_LOG(LS_ERROR) << "Failed to close the session: " << > error->message; > +- g_error_free(error); > + } > +- g_object_unref(message); > + } > + } > + > +@@ -274,7 +513,11 @@ void BaseCapturerPipeWire::InitPipeWire( > + StubPathMap paths; > + > + // Check if the PipeWire library is available. > +- paths[kModulePipewire].push_back(kPipeWireLib); > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ paths[kModulePipewire03].push_back(kPipeWireLib); > ++#else > ++ paths[kModulePipewire02].push_back(kPipeWireLib); > ++#endif > + if (!InitializeStubs(paths)) { > + RTC_LOG(LS_ERROR) << "Failed to load the PipeWire library and symbols."; > + portal_init_failed_ = true; > +@@ -284,16 +527,46 @@ void BaseCapturerPipeWire::InitPipeWire( > + > + pw_init(/*argc=*/nullptr, /*argc=*/nullptr); > + > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ pw_main_loop_ = pw_thread_loop_new("pipewire-main-loop", nullptr); > ++ > ++ pw_thread_loop_lock(pw_main_loop_); > ++ > ++ pw_context_ = > ++ pw_context_new(pw_thread_loop_get_loop(pw_main_loop_), nullptr, 0); > ++ if (!pw_context_) { > ++ RTC_LOG(LS_ERROR) << "Failed to create PipeWire context"; > ++ return; > ++ } > ++ > ++ pw_core_ = pw_context_connect(pw_context_, nullptr, 0); > ++ if (!pw_core_) { > ++ RTC_LOG(LS_ERROR) << "Failed to connect PipeWire context"; > ++ return; > ++ } > ++#else > + pw_loop_ = pw_loop_new(/*properties=*/nullptr); > + pw_main_loop_ = pw_thread_loop_new(pw_loop_, "pipewire-main-loop"); > + > ++ pw_thread_loop_lock(pw_main_loop_); > ++ > + pw_core_ = pw_core_new(pw_loop_, /*properties=*/nullptr); > + pw_core_type_ = pw_core_get_type(pw_core_); > + pw_remote_ = pw_remote_new(pw_core_, nullptr, /*user_data_size=*/0); > + > + InitPipeWireTypes(); > ++#endif > + > + // Initialize event handlers, remote end and stream-related. > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ pw_core_events_.version = PW_VERSION_CORE_EVENTS; > ++ pw_core_events_.error = &OnCoreError; > ++ > ++ pw_stream_events_.version = PW_VERSION_STREAM_EVENTS; > ++ pw_stream_events_.state_changed = &OnStreamStateChanged; > ++ pw_stream_events_.param_changed = &OnStreamParamChanged; > ++ pw_stream_events_.process = &OnStreamProcess; > ++#else > + pw_remote_events_.version = PW_VERSION_REMOTE_EVENTS; > + pw_remote_events_.state_changed = &OnStateChanged; > + > +@@ -301,19 +574,33 @@ void BaseCapturerPipeWire::InitPipeWire( > + pw_stream_events_.state_changed = &OnStreamStateChanged; > + pw_stream_events_.format_changed = &OnStreamFormatChanged; > + pw_stream_events_.process = &OnStreamProcess; > ++#endif > ++ > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ pw_core_add_listener(pw_core_, &spa_core_listener_, &pw_core_events_, > this); > + > ++ pw_stream_ = CreateReceivingStream(); > ++ if (!pw_stream_) { > ++ RTC_LOG(LS_ERROR) << "Failed to create PipeWire stream"; > ++ return; > ++ } > ++#else > + pw_remote_add_listener(pw_remote_, &spa_remote_listener_, > &pw_remote_events_, > + this); > + pw_remote_connect_fd(pw_remote_, pw_fd_); > ++#endif > + > + if (pw_thread_loop_start(pw_main_loop_) < 0) { > + RTC_LOG(LS_ERROR) << "Failed to start main PipeWire loop"; > + portal_init_failed_ = true; > + } > + > ++ pw_thread_loop_unlock(pw_main_loop_); > ++ > + RTC_LOG(LS_INFO) << "PipeWire remote opened."; > + } > + > ++#if !PW_CHECK_VERSION(0, 3, 0) > + void BaseCapturerPipeWire::InitPipeWireTypes() { > + spa_type_map* map = pw_core_type_->map; > + pw_type_ = new PipeWireType(); > +@@ -323,23 +610,44 @@ void BaseCapturerPipeWire::InitPipeWireT > + spa_type_format_video_map(map, &pw_type_->format_video); > + spa_type_video_format_map(map, &pw_type_->video_format); > + } > ++#endif > + > +-void BaseCapturerPipeWire::CreateReceivingStream() { > ++pw_stream* BaseCapturerPipeWire::CreateReceivingStream() { > ++#if !PW_CHECK_VERSION(0, 3, 0) > ++ if (pw_remote_get_state(pw_remote_, nullptr) != > PW_REMOTE_STATE_CONNECTED) { > ++ RTC_LOG(LS_ERROR) << "Cannot create pipewire stream"; > ++ return nullptr; > ++ } > ++#endif > + spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; > +- spa_rectangle pwScreenBounds = > +- spa_rectangle{static_cast<uint32_t>(desktop_size_.width()), > +- static_cast<uint32_t>(desktop_size_.height())}; > +- > +- spa_fraction pwFrameRateMin = spa_fraction{0, 1}; > +- spa_fraction pwFrameRateMax = spa_fraction{60, 1}; > ++ spa_rectangle pwMaxScreenBounds = spa_rectangle{UINT32_MAX, UINT32_MAX}; > + > + pw_properties* reuseProps = > + pw_properties_new_string("pipewire.client.reuse=1"); > +- pw_stream_ = pw_stream_new(pw_remote_, "webrtc-consume-stream", > reuseProps); > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ auto stream = pw_stream_new(pw_core_, "webrtc-consume-stream", > reuseProps); > ++#else > ++ auto stream = pw_stream_new(pw_remote_, "webrtc-consume-stream", > reuseProps); > ++#endif > + > + uint8_t buffer[1024] = {}; > + const spa_pod* params[1]; > + spa_pod_builder builder = spa_pod_builder{buffer, sizeof(buffer)}; > ++ > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_add_object( > ++ &builder, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, > ++ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), > ++ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), > ++ SPA_FORMAT_VIDEO_format, > ++ SPA_POD_CHOICE_ENUM_Id(5, SPA_VIDEO_FORMAT_BGRx, > SPA_VIDEO_FORMAT_RGBx, > ++ SPA_VIDEO_FORMAT_RGBA, SPA_VIDEO_FORMAT_BGRx, > ++ SPA_VIDEO_FORMAT_BGRA), > ++ SPA_FORMAT_VIDEO_size, > ++ SPA_POD_CHOICE_RANGE_Rectangle(&pwMinScreenBounds, &pwMinScreenBounds, > ++ &pwMaxScreenBounds), > ++ 0)); > ++#else > + params[0] = reinterpret_cast<spa_pod*>(spa_pod_builder_object( > + &builder, > + // id to enumerate formats > +@@ -349,69 +657,218 @@ void BaseCapturerPipeWire::CreateReceivi > + // then allowed formats are enumerated (e) and the format is > undecided (u) > + // to allow negotiation > + ":", pw_type_->format_video.format, "Ieu", > pw_type_->video_format.BGRx, > +- SPA_POD_PROP_ENUM(2, pw_type_->video_format.RGBx, > +- pw_type_->video_format.BGRx), > ++ SPA_POD_PROP_ENUM( > ++ 4, pw_type_->video_format.RGBx, pw_type_->video_format.BGRx, > ++ pw_type_->video_format.RGBA, pw_type_->video_format.BGRA), > + // Video size: specified as rectangle (R), preferred size is > specified as > + // first parameter, then allowed size is defined as range (r) from > min and > + // max values and the format is undecided (u) to allow negotiation > +- ":", pw_type_->format_video.size, "Rru", &pwScreenBounds, 2, > +- &pwMinScreenBounds, &pwScreenBounds, > +- // Frame rate: specified as fraction (F) and set to minimum frame rate > +- // value > +- ":", pw_type_->format_video.framerate, "F", &pwFrameRateMin, > +- // Max frame rate: specified as fraction (F), preferred frame rate is > set > +- // to maximum value, then allowed frame rate is defined as range (r) > from > +- // min and max values and it is undecided (u) to allow negotiation > +- ":", pw_type_->format_video.max_framerate, "Fru", &pwFrameRateMax, 2, > +- &pwFrameRateMin, &pwFrameRateMax)); > ++ ":", pw_type_->format_video.size, "Rru", &pwMinScreenBounds, > ++ SPA_POD_PROP_MIN_MAX(&pwMinScreenBounds, &pwMaxScreenBounds))); > ++#endif > + > +- pw_stream_add_listener(pw_stream_, &spa_stream_listener_, > &pw_stream_events_, > ++ pw_stream_add_listener(stream, &spa_stream_listener_, &pw_stream_events_, > + this); > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ if (pw_stream_connect(stream, PW_DIRECTION_INPUT, pw_stream_node_id_, > ++ PW_STREAM_FLAG_AUTOCONNECT, params, 1) != 0) { > ++#else > + pw_stream_flags flags = static_cast<pw_stream_flags>( > +- PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE | > +- PW_STREAM_FLAG_MAP_BUFFERS); > +- if (pw_stream_connect(pw_stream_, PW_DIRECTION_INPUT, > /*port_path=*/nullptr, > ++ PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE); > ++ if (pw_stream_connect(stream, PW_DIRECTION_INPUT, /*port_path=*/nullptr, > + flags, params, > + /*n_params=*/1) != 0) { > ++#endif > + RTC_LOG(LS_ERROR) << "Could not connect receiving stream."; > + portal_init_failed_ = true; > +- return; > ++ return nullptr; > + } > ++ > ++ return stream; > + } > + > + void BaseCapturerPipeWire::HandleBuffer(pw_buffer* buffer) { > + spa_buffer* spaBuffer = buffer->buffer; > +- void* src = nullptr; > ++ ScopedBuf map; > ++ uint8_t* src = nullptr; > ++ > ++ if (spaBuffer->datas[0].chunk->size == 0) { > ++ RTC_LOG(LS_ERROR) << "Failed to get video stream: Zero size."; > ++ return; > ++ } > ++ > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ if (spaBuffer->datas[0].type == SPA_DATA_MemFd || > ++ spaBuffer->datas[0].type == SPA_DATA_DmaBuf) { > ++#else > ++ if (spaBuffer->datas[0].type == pw_core_type_->data.MemFd || > ++ spaBuffer->datas[0].type == pw_core_type_->data.DmaBuf) { > ++#endif > ++ map.initialize( > ++ static_cast<uint8_t*>( > ++ mmap(nullptr, > ++ spaBuffer->datas[0].maxsize + > spaBuffer->datas[0].mapoffset, > ++ PROT_READ, MAP_PRIVATE, spaBuffer->datas[0].fd, 0)), > ++ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ spaBuffer->datas[0].type == SPA_DATA_DmaBuf, > ++#else > ++ spaBuffer->datas[0].type == pw_core_type_->data.DmaBuf, > ++#endif > ++ spaBuffer->datas[0].fd); > ++ > ++ if (!map) { > ++ RTC_LOG(LS_ERROR) << "Failed to mmap the memory: " > ++ << std::strerror(errno); > ++ return; > ++ } > ++ > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf) { > ++#else > ++ if (spaBuffer->datas[0].type == pw_core_type_->data.DmaBuf) { > ++#endif > ++ SyncDmaBuf(spaBuffer->datas[0].fd, DMA_BUF_SYNC_START); > ++ } > ++ > ++ src = SPA_MEMBER(map.get(), spaBuffer->datas[0].mapoffset, uint8_t); > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ } else if (spaBuffer->datas[0].type == SPA_DATA_MemPtr) { > ++#else > ++ } else if (spaBuffer->datas[0].type == pw_core_type_->data.MemPtr) { > ++#endif > ++ src = static_cast<uint8_t*>(spaBuffer->datas[0].data); > ++ } > ++ > ++ if (!src) { > ++ return; > ++ } > ++ > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ struct spa_meta_region* video_metadata = > ++ static_cast<struct spa_meta_region*>(spa_buffer_find_meta_data( > ++ spaBuffer, SPA_META_VideoCrop, sizeof(*video_metadata))); > ++#else > ++ struct spa_meta_video_crop* video_metadata = > ++ static_cast<struct spa_meta_video_crop*>( > ++ spa_buffer_find_meta(spaBuffer, pw_core_type_->meta.VideoCrop)); > ++#endif > + > +- if (!(src = spaBuffer->datas[0].data)) { > ++ // Video size from metadata is bigger than an actual video stream size. > ++ // The metadata are wrong or we should up-scale the video...in both cases > ++ // just quit now. > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ if (video_metadata && (video_metadata->region.size.width > > ++ static_cast<uint32_t>(desktop_size_.width()) || > ++ video_metadata->region.size.height > > ++ > static_cast<uint32_t>(desktop_size_.height()))) { > ++#else > ++ if (video_metadata && (video_metadata->width > desktop_size_.width() || > ++ video_metadata->height > desktop_size_.height())) { > ++#endif > ++ RTC_LOG(LS_ERROR) << "Stream metadata sizes are wrong!"; > + return; > + } > + > +- uint32_t maxSize = spaBuffer->datas[0].maxsize; > +- int32_t srcStride = spaBuffer->datas[0].chunk->stride; > +- if (srcStride != (desktop_size_.width() * kBytesPerPixel)) { > ++ // Use video metadata when video size from metadata is set and smaller > than > ++ // video stream size, so we need to adjust it. > ++ bool video_is_full_width = true; > ++ bool video_is_full_height = true; > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ if (video_metadata && video_metadata->region.size.width != 0 && > ++ video_metadata->region.size.height != 0) { > ++ if (video_metadata->region.size.width < > ++ static_cast<uint32_t>(desktop_size_.width())) { > ++ video_is_full_width = false; > ++ } else if (video_metadata->region.size.height < > ++ static_cast<uint32_t>(desktop_size_.height())) { > ++ video_is_full_height = false; > ++ } > ++ } > ++#else > ++ if (video_metadata && video_metadata->width != 0 && > ++ video_metadata->height != 0) { > ++ if (video_metadata->width < desktop_size_.width()) { > ++ } else if (video_metadata->height < desktop_size_.height()) { > ++ video_is_full_height = false; > ++ } > ++ } > ++#endif > ++ > ++ DesktopSize video_size_prev = video_size_; > ++ if (!video_is_full_height || !video_is_full_width) { > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ video_size_ = DesktopSize(video_metadata->region.size.width, > ++ video_metadata->region.size.height); > ++#else > ++ video_size_ = DesktopSize(video_metadata->width, > video_metadata->height); > ++#endif > ++ } else { > ++ video_size_ = desktop_size_; > ++ } > ++ > ++ webrtc::MutexLock lock(¤t_frame_lock_); > ++ if (!current_frame_ || !video_size_.equals(video_size_prev)) { > ++ current_frame_ = std::make_unique<uint8_t[]>( > ++ video_size_.width() * video_size_.height() * kBytesPerPixel); > ++ } > ++ > ++ const int32_t dst_stride = video_size_.width() * kBytesPerPixel; > ++ const int32_t src_stride = spaBuffer->datas[0].chunk->stride; > ++ > ++ if (src_stride != (desktop_size_.width() * kBytesPerPixel)) { > + RTC_LOG(LS_ERROR) << "Got buffer with stride different from screen > stride: " > +- << srcStride > ++ << src_stride > + << " != " << (desktop_size_.width() * kBytesPerPixel); > + portal_init_failed_ = true; > ++ > + return; > + } > + > +- if (!current_frame_) { > +- current_frame_ = static_cast<uint8_t*>(malloc(maxSize)); > +- } > +- RTC_DCHECK(current_frame_ != nullptr); > ++ // Adjust source content based on metadata video position > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ if (!video_is_full_height && > ++ (video_metadata->region.position.y + video_size_.height() <= > ++ desktop_size_.height())) { > ++ src += src_stride * video_metadata->region.position.y; > ++ } > ++ const int x_offset = > ++ !video_is_full_width && > ++ (video_metadata->region.position.x + video_size_.width() <= > ++ desktop_size_.width()) > ++ ? video_metadata->region.position.x * kBytesPerPixel > ++ : 0; > ++#else > ++ if (!video_is_full_height && > ++ (video_metadata->y + video_size_.height() <= desktop_size_.height())) > { > ++ src += src_stride * video_metadata->y; > ++ } > ++ > ++ const int x_offset = > ++ !video_is_full_width && > ++ (video_metadata->x + video_size_.width() <= > desktop_size_.width()) > ++ ? video_metadata->x * kBytesPerPixel > ++ : 0; > ++#endif > + > +- // If both sides decided to go with the RGBx format we need to convert it > to > +- // BGRx to match color format expected by WebRTC. > +- if (spa_video_format_->format == pw_type_->video_format.RGBx) { > +- uint8_t* tempFrame = static_cast<uint8_t*>(malloc(maxSize)); > +- std::memcpy(tempFrame, src, maxSize); > +- ConvertRGBxToBGRx(tempFrame, maxSize); > +- std::memcpy(current_frame_, tempFrame, maxSize); > +- free(tempFrame); > +- } else { > +- std::memcpy(current_frame_, src, maxSize); > ++ uint8_t* dst = current_frame_.get(); > ++ for (int i = 0; i < video_size_.height(); ++i) { > ++ // Adjust source content based on crop video position if needed > ++ src += x_offset; > ++ std::memcpy(dst, src, dst_stride); > ++ // If both sides decided to go with the RGBx format we need to convert > it to > ++ // BGRx to match color format expected by WebRTC. > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ if (spa_video_format_.format == SPA_VIDEO_FORMAT_RGBx || > ++ spa_video_format_.format == SPA_VIDEO_FORMAT_RGBA) { > ++#else > ++ if (spa_video_format_->format == pw_type_->video_format.RGBx || > ++ spa_video_format_->format == pw_type_->video_format.RGBA) { > ++#endif > ++ ConvertRGBxToBGRx(dst, dst_stride); > ++ } > ++ src += src_stride - x_offset; > ++ dst += dst_stride; > + } > + } > + > +@@ -441,14 +898,13 @@ void BaseCapturerPipeWire::OnProxyReques > + BaseCapturerPipeWire* that = > static_cast<BaseCapturerPipeWire*>(user_data); > + RTC_DCHECK(that); > + > +- GError* error = nullptr; > +- GDBusProxy *proxy = g_dbus_proxy_new_finish(result, &error); > ++ Scoped<GError> error; > ++ GDBusProxy* proxy = g_dbus_proxy_new_finish(result, error.receive()); > + if (!proxy) { > +- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) > ++ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) > + return; > + RTC_LOG(LS_ERROR) << "Failed to create a proxy for the screen cast > portal: " > + << error->message; > +- g_error_free(error); > + that->portal_init_failed_ = true; > + return; > + } > +@@ -462,38 +918,36 @@ void BaseCapturerPipeWire::OnProxyReques > + // static > + gchar* BaseCapturerPipeWire::PrepareSignalHandle(GDBusConnection* > connection, > + const gchar* token) { > +- gchar* sender = g_strdup(g_dbus_connection_get_unique_name(connection) + > 1); > +- for (int i = 0; sender[i]; i++) { > +- if (sender[i] == '.') { > +- sender[i] = '_'; > ++ Scoped<gchar> sender( > ++ g_strdup(g_dbus_connection_get_unique_name(connection) + 1)); > ++ for (int i = 0; sender.get()[i]; i++) { > ++ if (sender.get()[i] == '.') { > ++ sender.get()[i] = '_'; > + } > + } > + > +- gchar* handle = g_strconcat(kDesktopRequestObjectPath, "/", sender, "/", > ++ gchar* handle = g_strconcat(kDesktopRequestObjectPath, "/", sender.get(), > "/", > + token, /*end of varargs*/ nullptr); > +- g_free(sender); > + > + return handle; > + } > + > + void BaseCapturerPipeWire::SessionRequest() { > + GVariantBuilder builder; > +- gchar* variant_string; > ++ Scoped<gchar> variant_string; > + > + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); > + variant_string = > + g_strdup_printf("webrtc_session%d", g_random_int_range(0, G_MAXINT)); > + g_variant_builder_add(&builder, "{sv}", "session_handle_token", > +- g_variant_new_string(variant_string)); > +- g_free(variant_string); > ++ g_variant_new_string(variant_string.get())); > + variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, > G_MAXINT)); > + g_variant_builder_add(&builder, "{sv}", "handle_token", > +- g_variant_new_string(variant_string)); > ++ g_variant_new_string(variant_string.get())); > + > +- portal_handle_ = PrepareSignalHandle(connection_, variant_string); > ++ portal_handle_ = PrepareSignalHandle(connection_, variant_string.get()); > + session_request_signal_id_ = SetupRequestResponseSignal( > + portal_handle_, OnSessionRequestResponseSignal); > +- g_free(variant_string); > + > + RTC_LOG(LS_INFO) << "Screen cast session requested."; > + g_dbus_proxy_call( > +@@ -509,22 +963,21 @@ void BaseCapturerPipeWire::OnSessionRequ > + BaseCapturerPipeWire* that = > static_cast<BaseCapturerPipeWire*>(user_data); > + RTC_DCHECK(that); > + > +- GError* error = nullptr; > +- GVariant* variant = g_dbus_proxy_call_finish(proxy, result, &error); > ++ Scoped<GError> error; > ++ Scoped<GVariant> variant( > ++ g_dbus_proxy_call_finish(proxy, result, error.receive())); > + if (!variant) { > +- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) > ++ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) > + return; > + RTC_LOG(LS_ERROR) << "Failed to create a screen cast session: " > + << error->message; > +- g_error_free(error); > + that->portal_init_failed_ = true; > + return; > + } > + RTC_LOG(LS_INFO) << "Initializing the screen cast session."; > + > +- gchar* handle = nullptr; > +- g_variant_get_child(variant, 0, "o", &handle); > +- g_variant_unref(variant); > ++ Scoped<gchar> handle; > ++ g_variant_get_child(variant.get(), 0, "o", &handle); > + if (!handle) { > + RTC_LOG(LS_ERROR) << "Failed to initialize the screen cast session."; > + if (that->session_request_signal_id_) { > +@@ -536,8 +989,6 @@ void BaseCapturerPipeWire::OnSessionRequ > + return; > + } > + > +- g_free(handle); > +- > + RTC_LOG(LS_INFO) << "Subscribing to the screen cast session."; > + } > + > +@@ -557,11 +1008,11 @@ void BaseCapturerPipeWire::OnSessionRequ > + << "Received response for the screen cast session subscription."; > + > + guint32 portal_response; > +- GVariant* response_data; > +- g_variant_get(parameters, "(u@a{sv})", &portal_response, &response_data); > +- g_variant_lookup(response_data, "session_handle", "s", > ++ Scoped<GVariant> response_data; > ++ g_variant_get(parameters, "(u@a{sv})", &portal_response, > ++ response_data.receive()); > ++ g_variant_lookup(response_data.get(), "session_handle", "s", > + &that->session_handle_); > +- g_variant_unref(response_data); > + > + if (!that->session_handle_ || portal_response) { > + RTC_LOG(LS_ERROR) > +@@ -575,23 +1026,23 @@ void BaseCapturerPipeWire::OnSessionRequ > + > + void BaseCapturerPipeWire::SourcesRequest() { > + GVariantBuilder builder; > +- gchar* variant_string; > ++ Scoped<gchar> variant_string; > + > + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); > + // We want to record monitor content. > +- g_variant_builder_add(&builder, "{sv}", "types", > +- g_variant_new_uint32(capture_source_type_)); > ++ g_variant_builder_add( > ++ &builder, "{sv}", "types", > ++ g_variant_new_uint32(static_cast<uint32_t>(capture_source_type_))); > + // We don't want to allow selection of multiple sources. > + g_variant_builder_add(&builder, "{sv}", "multiple", > + g_variant_new_boolean(false)); > + variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, > G_MAXINT)); > + g_variant_builder_add(&builder, "{sv}", "handle_token", > +- g_variant_new_string(variant_string)); > ++ g_variant_new_string(variant_string.get())); > + > +- sources_handle_ = PrepareSignalHandle(connection_, variant_string); > ++ sources_handle_ = PrepareSignalHandle(connection_, variant_string.get()); > + sources_request_signal_id_ = SetupRequestResponseSignal( > + sources_handle_, OnSourcesRequestResponseSignal); > +- g_free(variant_string); > + > + RTC_LOG(LS_INFO) << "Requesting sources from the screen cast session."; > + g_dbus_proxy_call( > +@@ -608,22 +1059,21 @@ void BaseCapturerPipeWire::OnSourcesRequ > + BaseCapturerPipeWire* that = > static_cast<BaseCapturerPipeWire*>(user_data); > + RTC_DCHECK(that); > + > +- GError* error = nullptr; > +- GVariant* variant = g_dbus_proxy_call_finish(proxy, result, &error); > ++ Scoped<GError> error; > ++ Scoped<GVariant> variant( > ++ g_dbus_proxy_call_finish(proxy, result, error.receive())); > + if (!variant) { > +- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) > ++ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) > + return; > + RTC_LOG(LS_ERROR) << "Failed to request the sources: " << > error->message; > +- g_error_free(error); > + that->portal_init_failed_ = true; > + return; > + } > + > + RTC_LOG(LS_INFO) << "Sources requested from the screen cast session."; > + > +- gchar* handle = nullptr; > +- g_variant_get_child(variant, 0, "o", &handle); > +- g_variant_unref(variant); > ++ Scoped<gchar> handle; > ++ g_variant_get_child(variant.get(), 0, "o", handle.receive()); > + if (!handle) { > + RTC_LOG(LS_ERROR) << "Failed to initialize the screen cast session."; > + if (that->sources_request_signal_id_) { > +@@ -635,8 +1085,6 @@ void BaseCapturerPipeWire::OnSourcesRequ > + return; > + } > + > +- g_free(handle); > +- > + RTC_LOG(LS_INFO) << "Subscribed to sources signal."; > + } > + > +@@ -668,17 +1116,16 @@ void BaseCapturerPipeWire::OnSourcesRequ > + > + void BaseCapturerPipeWire::StartRequest() { > + GVariantBuilder builder; > +- gchar* variant_string; > ++ Scoped<gchar> variant_string; > + > + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); > + variant_string = g_strdup_printf("webrtc%d", g_random_int_range(0, > G_MAXINT)); > + g_variant_builder_add(&builder, "{sv}", "handle_token", > +- g_variant_new_string(variant_string)); > ++ g_variant_new_string(variant_string.get())); > + > +- start_handle_ = PrepareSignalHandle(connection_, variant_string); > ++ start_handle_ = PrepareSignalHandle(connection_, variant_string.get()); > + start_request_signal_id_ = > + SetupRequestResponseSignal(start_handle_, > OnStartRequestResponseSignal); > +- g_free(variant_string); > + > + // "Identifier for the application window", this is Wayland, so not > "x11:...". > + const gchar parent_window[] = ""; > +@@ -698,23 +1145,22 @@ void BaseCapturerPipeWire::OnStartReques > + BaseCapturerPipeWire* that = > static_cast<BaseCapturerPipeWire*>(user_data); > + RTC_DCHECK(that); > + > +- GError* error = nullptr; > +- GVariant* variant = g_dbus_proxy_call_finish(proxy, result, &error); > ++ Scoped<GError> error; > ++ Scoped<GVariant> variant( > ++ g_dbus_proxy_call_finish(proxy, result, error.receive())); > + if (!variant) { > +- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) > ++ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) > + return; > + RTC_LOG(LS_ERROR) << "Failed to start the screen cast session: " > + << error->message; > +- g_error_free(error); > + that->portal_init_failed_ = true; > + return; > + } > + > + RTC_LOG(LS_INFO) << "Initializing the start of the screen cast session."; > + > +- gchar* handle = nullptr; > +- g_variant_get_child(variant, 0, "o", &handle); > +- g_variant_unref(variant); > ++ Scoped<gchar> handle; > ++ g_variant_get_child(variant.get(), 0, "o", handle.receive()); > + if (!handle) { > + RTC_LOG(LS_ERROR) > + << "Failed to initialize the start of the screen cast session."; > +@@ -727,8 +1173,6 @@ void BaseCapturerPipeWire::OnStartReques > + return; > + } > + > +- g_free(handle); > +- > + RTC_LOG(LS_INFO) << "Subscribed to the start signal."; > + } > + > +@@ -746,9 +1190,10 @@ void BaseCapturerPipeWire::OnStartReques > + > + RTC_LOG(LS_INFO) << "Start signal received."; > + guint32 portal_response; > +- GVariant* response_data; > +- GVariantIter* iter = nullptr; > +- g_variant_get(parameters, "(u@a{sv})", &portal_response, &response_data); > ++ Scoped<GVariant> response_data; > ++ Scoped<GVariantIter> iter; > ++ g_variant_get(parameters, "(u@a{sv})", &portal_response, > ++ response_data.receive()); > + if (portal_response || !response_data) { > + RTC_LOG(LS_ERROR) << "Failed to start the screen cast session."; > + that->portal_init_failed_ = true; > +@@ -758,28 +1203,28 @@ void BaseCapturerPipeWire::OnStartReques > + // Array of PipeWire streams. See > + // > https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml > + // documentation for <method name="Start">. > +- if (g_variant_lookup(response_data, "streams", "a(ua{sv})", &iter)) { > +- GVariant* variant; > ++ if (g_variant_lookup(response_data.get(), "streams", "a(ua{sv})", > ++ iter.receive())) { > ++ Scoped<GVariant> variant; > + > +- while (g_variant_iter_next(iter, "@(ua{sv})", &variant)) { > ++ while (g_variant_iter_next(iter.get(), "@(ua{sv})", variant.receive())) > { > + guint32 stream_id; > +- gint32 width; > +- gint32 height; > +- GVariant* options; > ++ guint32 type; > ++ Scoped<GVariant> options; > + > +- g_variant_get(variant, "(u@a{sv})", &stream_id, &options); > +- RTC_DCHECK(options != nullptr); > ++ g_variant_get(variant.get(), "(u@a{sv})", &stream_id, > options.receive()); > ++ RTC_DCHECK(options.get()); > + > +- g_variant_lookup(options, "size", "(ii)", &width, &height); > ++ if (g_variant_lookup(options.get(), "source_type", "u", &type)) { > ++ that->capture_source_type_ = > ++ static_cast<BaseCapturerPipeWire::CaptureSourceType>(type); > ++ } > + > +- that->desktop_size_.set(width, height); > ++ that->pw_stream_node_id_ = stream_id; > + > +- g_variant_unref(options); > +- g_variant_unref(variant); > ++ break; > + } > + } > +- g_variant_iter_free(iter); > +- g_variant_unref(response_data); > + > + that->OpenPipeWireRemote(); > + } > +@@ -807,35 +1252,30 @@ void BaseCapturerPipeWire::OnOpenPipeWir > + BaseCapturerPipeWire* that = > static_cast<BaseCapturerPipeWire*>(user_data); > + RTC_DCHECK(that); > + > +- GError* error = nullptr; > +- GUnixFDList* outlist = nullptr; > +- GVariant* variant = g_dbus_proxy_call_with_unix_fd_list_finish( > +- proxy, &outlist, result, &error); > ++ Scoped<GError> error; > ++ Scoped<GUnixFDList> outlist; > ++ Scoped<GVariant> variant(g_dbus_proxy_call_with_unix_fd_list_finish( > ++ proxy, outlist.receive(), result, error.receive())); > + if (!variant) { > +- if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) > ++ if (g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_CANCELLED)) > + return; > + RTC_LOG(LS_ERROR) << "Failed to open the PipeWire remote: " > + << error->message; > +- g_error_free(error); > + that->portal_init_failed_ = true; > + return; > + } > + > + gint32 index; > +- g_variant_get(variant, "(h)", &index); > ++ g_variant_get(variant.get(), "(h)", &index); > + > +- if ((that->pw_fd_ = g_unix_fd_list_get(outlist, index, &error)) == -1) { > ++ if ((that->pw_fd_ = > ++ g_unix_fd_list_get(outlist.get(), index, error.receive())) == > -1) { > + RTC_LOG(LS_ERROR) << "Failed to get file descriptor from the list: " > + << error->message; > +- g_error_free(error); > +- g_variant_unref(variant); > + that->portal_init_failed_ = true; > + return; > + } > + > +- g_variant_unref(variant); > +- g_object_unref(outlist); > +- > + that->InitPipeWire(); > + } > + > +@@ -854,15 +1294,18 @@ void BaseCapturerPipeWire::CaptureFrame( > + return; > + } > + > ++ webrtc::MutexLock lock(¤t_frame_lock_); > + if (!current_frame_) { > + callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); > + return; > + } > + > +- std::unique_ptr<DesktopFrame> result(new > BasicDesktopFrame(desktop_size_)); > ++ DesktopSize frame_size = video_size_; > ++ > ++ std::unique_ptr<DesktopFrame> result(new BasicDesktopFrame(frame_size)); > + result->CopyPixelsFrom( > +- current_frame_, (desktop_size_.width() * kBytesPerPixel), > +- DesktopRect::MakeWH(desktop_size_.width(), desktop_size_.height())); > ++ current_frame_.get(), (frame_size.width() * kBytesPerPixel), > ++ DesktopRect::MakeWH(frame_size.width(), frame_size.height())); > + if (!result) { > + callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); > + return; > +@@ -887,4 +1330,11 @@ bool BaseCapturerPipeWire::SelectSource( > + return true; > + } > + > ++// static > ++std::unique_ptr<DesktopCapturer> BaseCapturerPipeWire::CreateRawCapturer( > ++ const DesktopCaptureOptions& options) { > ++ return std::make_unique<BaseCapturerPipeWire>( > ++ BaseCapturerPipeWire::CaptureSourceType::kAny); > ++} > ++ > + } // namespace webrtc > +--- > 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 > +@@ -10,18 +10,23 @@ > + > + #ifndef MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ > + #define MODULES_DESKTOP_CAPTURE_LINUX_BASE_CAPTURER_PIPEWIRE_H_ > +- > + #include <gio/gio.h> > + #define typeof __typeof__ > + #include <pipewire/pipewire.h> > + #include <spa/param/video/format-utils.h> > ++#if PW_CHECK_VERSION(0, 3, 0) > ++#include <spa/utils/result.h> > ++#endif > + > ++#include "absl/types/optional.h" > + #include "modules/desktop_capture/desktop_capture_options.h" > + #include "modules/desktop_capture/desktop_capturer.h" > + #include "rtc_base/constructor_magic.h" > ++#include "rtc_base/synchronization/mutex.h" > + > + namespace webrtc { > + > ++#if !PW_CHECK_VERSION(0, 3, 0) > + class PipeWireType { > + public: > + spa_type_media_type media_type; > +@@ -29,14 +34,25 @@ class PipeWireType { > + spa_type_format_video format_video; > + spa_type_video_format video_format; > + }; > ++#endif > + > + class BaseCapturerPipeWire : public DesktopCapturer { > + public: > +- enum CaptureSourceType { Screen = 1, Window }; > ++ // Values are set based on source type property in > ++ // xdg-desktop-portal/screencast > ++ // > https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml > ++ enum class CaptureSourceType : uint32_t { > ++ kScreen = 0b01, > ++ kWindow = 0b10, > ++ kAny = 0b11 > ++ }; > + > + explicit BaseCapturerPipeWire(CaptureSourceType source_type); > + ~BaseCapturerPipeWire() override; > + > ++ static std::unique_ptr<DesktopCapturer> CreateRawCapturer( > ++ const DesktopCaptureOptions& options); > ++ > + // DesktopCapturer interface. > + void Start(Callback* delegate) override; > + void CaptureFrame() override; > +@@ -45,6 +61,21 @@ class BaseCapturerPipeWire : public Desk > + > + private: > + // PipeWire types --> > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ struct pw_context* pw_context_ = nullptr; > ++ struct pw_core* pw_core_ = nullptr; > ++ struct pw_stream* pw_stream_ = nullptr; > ++ struct pw_thread_loop* pw_main_loop_ = nullptr; > ++ > ++ spa_hook spa_core_listener_; > ++ spa_hook spa_stream_listener_; > ++ > ++ // event handlers > ++ pw_core_events pw_core_events_ = {}; > ++ pw_stream_events pw_stream_events_ = {}; > ++ > ++ struct spa_video_info_raw spa_video_format_; > ++#else > + pw_core* pw_core_ = nullptr; > + pw_type* pw_core_type_ = nullptr; > + pw_stream* pw_stream_ = nullptr; > +@@ -60,11 +91,13 @@ class BaseCapturerPipeWire : public Desk > + pw_remote_events pw_remote_events_ = {}; > + > + spa_video_info_raw* spa_video_format_ = nullptr; > ++#endif > + > ++ guint32 pw_stream_node_id_ = 0; > + gint32 pw_fd_ = -1; > + > + CaptureSourceType capture_source_type_ = > +- BaseCapturerPipeWire::CaptureSourceType::Screen; > ++ BaseCapturerPipeWire::CaptureSourceType::kScreen; > + > + // <-- end of PipeWire types > + > +@@ -79,10 +112,12 @@ class BaseCapturerPipeWire : public Desk > + guint sources_request_signal_id_ = 0; > + guint start_request_signal_id_ = 0; > + > ++ DesktopSize video_size_; > + DesktopSize desktop_size_ = {}; > + DesktopCaptureOptions options_ = {}; > + > +- uint8_t* current_frame_ = nullptr; > ++ webrtc::Mutex current_frame_lock_; > ++ std::unique_ptr<uint8_t[]> current_frame_; > + Callback* callback_ = nullptr; > + > + bool portal_init_failed_ = false; > +@@ -91,21 +126,32 @@ class BaseCapturerPipeWire : public Desk > + void InitPipeWire(); > + void InitPipeWireTypes(); > + > +- void CreateReceivingStream(); > ++ pw_stream* CreateReceivingStream(); > + void HandleBuffer(pw_buffer* buffer); > + > + void ConvertRGBxToBGRx(uint8_t* frame, uint32_t size); > + > ++#if PW_CHECK_VERSION(0, 3, 0) > ++ static void OnCoreError(void* data, > ++ uint32_t id, > ++ int seq, > ++ int res, > ++ const char* message); > ++ static void OnStreamParamChanged(void* data, > ++ uint32_t id, > ++ const struct spa_pod* format); > ++#else > + static void OnStateChanged(void* data, > + pw_remote_state old_state, > + pw_remote_state state, > + const char* error); > ++ static void OnStreamFormatChanged(void* data, const struct spa_pod* > format); > ++#endif > + static void OnStreamStateChanged(void* data, > + pw_stream_state old_state, > + pw_stream_state state, > + const char* error_message); > + > +- static void OnStreamFormatChanged(void* data, const struct spa_pod* > format); > + static void OnStreamProcess(void* data); > + static void OnNewBuffer(void* data, uint32_t id); > + > +--- > a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire.sigs > ++++ /dev/null > +@@ -1,44 +0,0 @@ > +-// Copyright 2018 The WebRTC project authors. All rights reserved. > +-// Use of this source code is governed by a BSD-style license that can be > +-// found in the LICENSE file. > +- > +-//------------------------------------------------ > +-// Functions from PipeWire used in capturer code. > +-//------------------------------------------------ > +- > +-// core.h > +-void pw_core_destroy(pw_core *core); > +-pw_type *pw_core_get_type(pw_core *core); > +-pw_core * pw_core_new(pw_loop *main_loop, pw_properties *props); > +- > +-// loop.h > +-void pw_loop_destroy(pw_loop *loop); > +-pw_loop * pw_loop_new(pw_properties *properties); > +- > +-// pipewire.h > +-void pw_init(int *argc, char **argv[]); > +- > +-// properties.h > +-pw_properties * pw_properties_new_string(const char *args); > +- > +-// remote.h > +-void pw_remote_add_listener(pw_remote *remote, spa_hook *listener, const > pw_remote_events *events, void *data); > +-int pw_remote_connect_fd(pw_remote *remote, int fd); > +-void pw_remote_destroy(pw_remote *remote); > +-pw_remote * pw_remote_new(pw_core *core, pw_properties *properties, size_t > user_data_size); > +- > +-// stream.h > +-void pw_stream_add_listener(pw_stream *stream, spa_hook *listener, const > pw_stream_events *events, void *data); > +-int pw_stream_connect(pw_stream *stream, enum pw_direction direction, const > char *port_path, enum pw_stream_flags flags, const spa_pod **params, uint32_t > n_params); > +-pw_buffer *pw_stream_dequeue_buffer(pw_stream *stream); > +-void pw_stream_destroy(pw_stream *stream); > +-void pw_stream_finish_format(pw_stream *stream, int res, const spa_pod > **params, uint32_t n_params); > +-pw_stream * pw_stream_new(pw_remote *remote, const char *name, > pw_properties *props); > +-int pw_stream_queue_buffer(pw_stream *stream, pw_buffer *buffer); > +-int pw_stream_set_active(pw_stream *stream, bool active); > +- > +-// thread-loop.h > +-void pw_thread_loop_destroy(pw_thread_loop *loop); > +-pw_thread_loop * pw_thread_loop_new(pw_loop *loop, const char *name); > +-int pw_thread_loop_start(pw_thread_loop *loop); > +-void pw_thread_loop_stop(pw_thread_loop *loop); > +--- /dev/null > ++++ > b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire02.sigs > +@@ -0,0 +1,47 @@ > ++// Copyright 2018 The WebRTC project authors. All rights reserved. > ++// Use of this source code is governed by a BSD-style license that can be > ++// found in the LICENSE file. > ++ > ++//------------------------------------------------ > ++// Functions from PipeWire used in capturer code. > ++//------------------------------------------------ > ++ > ++// core.h > ++void pw_core_destroy(pw_core *core); > ++pw_type *pw_core_get_type(pw_core *core); > ++pw_core * pw_core_new(pw_loop *main_loop, pw_properties *props); > ++ > ++// loop.h > ++void pw_loop_destroy(pw_loop *loop); > ++pw_loop * pw_loop_new(pw_properties *properties); > ++ > ++// pipewire.h > ++void pw_init(int *argc, char **argv[]); > ++ > ++// properties.h > ++pw_properties * pw_properties_new_string(const char *args); > ++ > ++// remote.h > ++void pw_remote_add_listener(pw_remote *remote, spa_hook *listener, const > pw_remote_events *events, void *data); > ++int pw_remote_connect_fd(pw_remote *remote, int fd); > ++void pw_remote_destroy(pw_remote *remote); > ++pw_remote * pw_remote_new(pw_core *core, pw_properties *properties, size_t > user_data_size); > ++enum pw_remote_state pw_remote_get_state(pw_remote *remote, const char > **error); > ++ > ++// stream.h > ++void pw_stream_add_listener(pw_stream *stream, spa_hook *listener, const > pw_stream_events *events, void *data); > ++int pw_stream_connect(pw_stream *stream, enum pw_direction direction, const > char *port_path, enum pw_stream_flags flags, const spa_pod **params, uint32_t > n_params); > ++pw_buffer *pw_stream_dequeue_buffer(pw_stream *stream); > ++void pw_stream_destroy(pw_stream *stream); > ++void pw_stream_finish_format(pw_stream *stream, int res, const spa_pod > **params, uint32_t n_params); > ++pw_stream * pw_stream_new(pw_remote *remote, const char *name, > pw_properties *props); > ++int pw_stream_queue_buffer(pw_stream *stream, pw_buffer *buffer); > ++int pw_stream_set_active(pw_stream *stream, bool active); > ++ > ++// thread-loop.h > ++void pw_thread_loop_destroy(pw_thread_loop *loop); > ++pw_thread_loop * pw_thread_loop_new(pw_loop *loop, const char *name); > ++int pw_thread_loop_start(pw_thread_loop *loop); > ++void pw_thread_loop_stop(pw_thread_loop *loop); > ++void pw_thread_loop_lock(struct pw_thread_loop *loop); > ++void pw_thread_loop_unlock(struct pw_thread_loop *loop); > +--- /dev/null > ++++ > b/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/pipewire03.sigs > +@@ -0,0 +1,46 @@ > ++// Copyright 2018 The WebRTC project authors. All rights reserved. > ++// Use of this source code is governed by a BSD-style license that can be > ++// found in the LICENSE file. > ++ > ++//------------------------------------------------ > ++// Functions from PipeWire used in capturer code. > ++//------------------------------------------------ > ++ > ++// core.h > ++int pw_core_disconnect(pw_core *core); > ++ > ++// loop.h > ++void pw_loop_destroy(pw_loop *loop); > ++pw_loop * pw_loop_new(const spa_dict *props); > ++ > ++ > ++// pipewire.h > ++void pw_init(int *argc, char **argv[]); > ++ > ++// properties.h > ++pw_properties * pw_properties_new_string(const char *args); > ++ > ++// stream.h > ++void pw_stream_add_listener(pw_stream *stream, spa_hook *listener, const > pw_stream_events *events, void *data); > ++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); > ++pw_buffer *pw_stream_dequeue_buffer(pw_stream *stream); > ++void pw_stream_destroy(pw_stream *stream); > ++pw_stream * pw_stream_new(pw_core *core, const char *name, pw_properties > *props); > ++int pw_stream_queue_buffer(pw_stream *stream, pw_buffer *buffer); > ++int pw_stream_set_active(pw_stream *stream, bool active); > ++int pw_stream_update_params(pw_stream *stream, const spa_pod **params, > uint32_t n_params); > ++ > ++// thread-loop.h > ++void pw_thread_loop_destroy(pw_thread_loop *loop); > ++pw_thread_loop * pw_thread_loop_new(const char *name, const spa_dict > *props); > ++int pw_thread_loop_start(pw_thread_loop *loop); > ++void pw_thread_loop_stop(pw_thread_loop *loop); > ++void pw_thread_loop_lock(pw_thread_loop *loop); > ++void pw_thread_loop_unlock(pw_thread_loop *loop); > ++pw_loop * pw_thread_loop_get_loop(pw_thread_loop *loop); > ++ > ++ > ++// context.h > ++void pw_context_destroy(pw_context *context); > ++pw_context *pw_context_new(pw_loop *main_loop, pw_properties *props, size_t > user_data_size); > ++pw_core * pw_context_connect(pw_context *context, pw_properties > *properties, size_t user_data_size); > +--- > a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc > ++++ /dev/null > +@@ -1,29 +0,0 @@ > +-/* > +- * Copyright 2018 The WebRTC project authors. All Rights Reserved. > +- * > +- * Use of this source code is governed by a BSD-style license > +- * that can be found in the LICENSE file in the root of the source > +- * tree. An additional intellectual property rights grant can be found > +- * in the file PATENTS. All contributing project authors may > +- * be found in the AUTHORS file in the root of the source tree. > +- */ > +- > +-#include "modules/desktop_capture/linux/screen_capturer_pipewire.h" > +- > +-#include <memory> > +- > +- > +-namespace webrtc { > +- > +-ScreenCapturerPipeWire::ScreenCapturerPipeWire() > +- : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Screen) > {} > +-ScreenCapturerPipeWire::~ScreenCapturerPipeWire() {} > +- > +-// static > +-std::unique_ptr<DesktopCapturer> > +-ScreenCapturerPipeWire::CreateRawScreenCapturer( > +- const DesktopCaptureOptions& options) { > +- return std::make_unique<ScreenCapturerPipeWire>(); > +-} > +- > +-} // namespace webrtc > +--- > a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.h > ++++ /dev/null > +@@ -1,33 +0,0 @@ > +-/* > +- * Copyright 2018 The WebRTC project authors. All Rights Reserved. > +- * > +- * Use of this source code is governed by a BSD-style license > +- * that can be found in the LICENSE file in the root of the source > +- * tree. An additional intellectual property rights grant can be found > +- * in the file PATENTS. All contributing project authors may > +- * be found in the AUTHORS file in the root of the source tree. > +- */ > +- > +-#ifndef MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_PIPEWIRE_H_ > +-#define MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_PIPEWIRE_H_ > +- > +-#include <memory> > +- > +-#include "modules/desktop_capture/linux/base_capturer_pipewire.h" > +- > +-namespace webrtc { > +- > +-class ScreenCapturerPipeWire : public BaseCapturerPipeWire { > +- public: > +- ScreenCapturerPipeWire(); > +- ~ScreenCapturerPipeWire() override; > +- > +- static std::unique_ptr<DesktopCapturer> CreateRawScreenCapturer( > +- const DesktopCaptureOptions& options); > +- > +- RTC_DISALLOW_COPY_AND_ASSIGN(ScreenCapturerPipeWire); > +-}; > +- > +-} // namespace webrtc > +- > +-#endif // MODULES_DESKTOP_CAPTURE_LINUX_SCREEN_CAPTURER_PIPEWIRE_H_ > +--- > a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc > ++++ /dev/null > +@@ -1,29 +0,0 @@ > +-/* > +- * Copyright 2018 The WebRTC project authors. All Rights Reserved. > +- * > +- * Use of this source code is governed by a BSD-style license > +- * that can be found in the LICENSE file in the root of the source > +- * tree. An additional intellectual property rights grant can be found > +- * in the file PATENTS. All contributing project authors may > +- * be found in the AUTHORS file in the root of the source tree. > +- */ > +- > +-#include "modules/desktop_capture/linux/window_capturer_pipewire.h" > +- > +-#include <memory> > +- > +- > +-namespace webrtc { > +- > +-WindowCapturerPipeWire::WindowCapturerPipeWire() > +- : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Window) > {} > +-WindowCapturerPipeWire::~WindowCapturerPipeWire() {} > +- > +-// static > +-std::unique_ptr<DesktopCapturer> > +-WindowCapturerPipeWire::CreateRawWindowCapturer( > +- const DesktopCaptureOptions& options) { > +- return std::make_unique<WindowCapturerPipeWire>(); > +-} > +- > +-} // namespace webrtc > +--- > a/src/3rdparty/chromium/third_party/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.h > ++++ /dev/null > +@@ -1,33 +0,0 @@ > +-/* > +- * Copyright 2018 The WebRTC project authors. All Rights Reserved. > +- * > +- * Use of this source code is governed by a BSD-style license > +- * that can be found in the LICENSE file in the root of the source > +- * tree. An additional intellectual property rights grant can be found > +- * in the file PATENTS. All contributing project authors may > +- * be found in the AUTHORS file in the root of the source tree. > +- */ > +- > +-#ifndef MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_PIPEWIRE_H_ > +-#define MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_PIPEWIRE_H_ > +- > +-#include <memory> > +- > +-#include "modules/desktop_capture/linux/base_capturer_pipewire.h" > +- > +-namespace webrtc { > +- > +-class WindowCapturerPipeWire : public BaseCapturerPipeWire { > +- public: > +- WindowCapturerPipeWire(); > +- ~WindowCapturerPipeWire() override; > +- > +- static std::unique_ptr<DesktopCapturer> CreateRawWindowCapturer( > +- const DesktopCaptureOptions& options); > +- > +- RTC_DISALLOW_COPY_AND_ASSIGN(WindowCapturerPipeWire); > +-}; > +- > +-} // namespace webrtc > +- > +-#endif // MODULES_DESKTOP_CAPTURE_LINUX_WINDOW_CAPTURER_PIPEWIRE_H_ > +--- > 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 > +@@ -14,7 +14,7 @@ > + #include "modules/desktop_capture/desktop_capturer.h" > + > + #if defined(WEBRTC_USE_PIPEWIRE) > +-#include "modules/desktop_capture/linux/screen_capturer_pipewire.h" > ++#include "modules/desktop_capture/linux/base_capturer_pipewire.h" > + #endif // defined(WEBRTC_USE_PIPEWIRE) > + > + #if defined(WEBRTC_USE_X11) > +@@ -28,7 +28,7 @@ std::unique_ptr<DesktopCapturer> Desktop > + const DesktopCaptureOptions& options) { > + #if defined(WEBRTC_USE_PIPEWIRE) > + if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) > { > +- return ScreenCapturerPipeWire::CreateRawScreenCapturer(options); > ++ return BaseCapturerPipeWire::CreateRawCapturer(options); > + } > + #endif // defined(WEBRTC_USE_PIPEWIRE) > + > +--- > 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 > +@@ -14,7 +14,7 @@ > + #include "modules/desktop_capture/desktop_capturer.h" > + > + #if defined(WEBRTC_USE_PIPEWIRE) > +-#include "modules/desktop_capture/linux/window_capturer_pipewire.h" > ++#include "modules/desktop_capture/linux/base_capturer_pipewire.h" > + #endif // defined(WEBRTC_USE_PIPEWIRE) > + > + #if defined(WEBRTC_USE_X11) > +@@ -28,7 +28,7 @@ std::unique_ptr<DesktopCapturer> Desktop > + const DesktopCaptureOptions& options) { > + #if defined(WEBRTC_USE_PIPEWIRE) > + if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) > { > +- return WindowCapturerPipeWire::CreateRawWindowCapturer(options); > ++ return BaseCapturerPipeWire::CreateRawCapturer(options); > + } > + #endif // defined(WEBRTC_USE_PIPEWIRE) > + > +--- a/src/3rdparty/chromium/third_party/webrtc/webrtc.gni > ++++ b/src/3rdparty/chromium/third_party/webrtc/webrtc.gni > +@@ -117,6 +117,10 @@ declare_args() { > + # Set this to link PipeWire directly instead of using the dlopen. > + rtc_link_pipewire = false > + > ++ # Set this to use certain PipeWire version > ++ # Currently we support PipeWire 0.2 (default) and PipeWire 0.3 > ++ rtc_pipewire_version = "0.2" > ++ > + # Enable to use the Mozilla internal settings. > + build_with_mozilla = false > + > diff --git a/debian/patches/python3.patch b/debian/patches/python3.patch > index 9837209..1ed6e4c 100644 > --- a/debian/patches/python3.patch > +++ b/debian/patches/python3.patch > @@ -109,7 +109,7 @@ Forwarded: not-needed > return(true) > --- a/src/buildtools/configure.json > +++ b/src/buildtools/configure.json > -@@ -295,9 +295,9 @@ > +@@ -301,9 +301,9 @@ > "label": "system ninja", > "type": "detectNinja" > }, > @@ -122,7 +122,7 @@ Forwarded: not-needed > "log": "location" > }, > "webengine-winversion": { > -@@ -374,7 +374,7 @@ > +@@ -380,7 +380,7 @@ > && features.webengine-gperf > && features.webengine-bison > && features.webengine-flex > @@ -131,7 +131,7 @@ Forwarded: not-needed > && features.webengine-nodejs > && (!config.sanitizer || > features.webengine-sanitizer) > && (!config.linux || features.pkg-config) > -@@ -400,7 +400,7 @@ > +@@ -406,7 +406,7 @@ > && features.webengine-gperf > && features.webengine-bison > && features.webengine-flex > @@ -140,7 +140,7 @@ Forwarded: not-needed > && (!config.sanitizer || > features.webengine-sanitizer) > && (!config.linux || features.pkg-config) > && (!config.linux || > features.webengine-host-pkg-config) > -@@ -423,12 +423,12 @@ > +@@ -429,12 +429,12 @@ > "autoDetect": "features.private_tests", > "output": [ "privateFeature" ] > }, > diff --git a/debian/patches/series b/debian/patches/series > index 9b396af..3b8f52b 100644 > --- a/debian/patches/series > +++ b/debian/patches/series > @@ -23,5 +23,5 @@ mips64el-bad-define.patch > mipsel-syscall-ranges.patch > mips64el-kernel_stat64.patch > armhf-no-thumb.patch > -gcc-12.patch > disable-catapult.patch > +pipewire-0.3.patch > diff --git a/debian/rules b/debian/rules > index 0cbc395..0cb0ced 100755 > --- a/debian/rules > +++ b/debian/rules > @@ -44,6 +44,7 @@ config_args = -proprietary-codecs \ > -system-opus \ > -system-webp \ > -system-webengine-icu \ > + -webengine-webrtc-pipewire \ > -webengine-kerberos > > touch_files = > src/3rdparty/chromium/third_party/devtools-frontend/src/front_end/third_party/lighthouse/lighthouse-dt-bundle.js > \ > @@ -200,7 +201,7 @@ get-orig-source: > @set -eux && \ > TEMPDIR=$$(mktemp -d) && \ > VERSION=${DEB_VERSION_UPSTREAM:+dfsg=} && \ > - SUBMODULE_COMMIT=e0fd3a5d3ce79d43dee6e0bad16a71123d9a14b3 && \ > + SUBMODULE_COMMIT=e48df7803c7c98b0b2471c94057d32e44a301ad5 && \ > echo "$${GET_FILES_EXCLUDED}" >$${TEMPDIR}/get_files_excluded.py && \ > cd $${TEMPDIR} && \ > wget https://github.com/qt/qtwebengine/archive/v$${VERSION}-lts.tar.gz > && \ -- Sebastian Ramacher