diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:34:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:34:42 +0000 |
commit | da4c7e7ed675c3bf405668739c3012d140856109 (patch) | |
tree | cdd868dba063fecba609a1d819de271f0d51b23e /third_party/libwebrtc/moz-patch-stack/0109.patch | |
parent | Adding upstream version 125.0.3. (diff) | |
download | firefox-da4c7e7ed675c3bf405668739c3012d140856109.tar.xz firefox-da4c7e7ed675c3bf405668739c3012d140856109.zip |
Adding upstream version 126.0.upstream/126.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/moz-patch-stack/0109.patch')
-rw-r--r-- | third_party/libwebrtc/moz-patch-stack/0109.patch | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/third_party/libwebrtc/moz-patch-stack/0109.patch b/third_party/libwebrtc/moz-patch-stack/0109.patch new file mode 100644 index 0000000000..7fcb865db5 --- /dev/null +++ b/third_party/libwebrtc/moz-patch-stack/0109.patch @@ -0,0 +1,243 @@ +From: Jan Grulich <jgrulich@redhat.com> +Date: Tue, 5 Mar 2024 08:38:00 +0000 +Subject: Bug 1876895 - WebRTC backport: Video capture PipeWire: add support + for DMABuf buffer type r=pehrsons,webrtc-reviewers + +This is a simple backport of an WebRTC upstream change. + +Upstream commit: 334e9133dcdecb5d00d991332e05c7b80ae26578 + +Differential Revision: https://phabricator.services.mozilla.com/D202929 +Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/e915ae33e90a5e176f9196a67a201b86e22e498b +--- + .../linux/wayland/shared_screencast_stream.cc | 28 ------- + modules/portal/pipewire_utils.h | 75 +++++++++++++++++++ + .../linux/video_capture_pipewire.cc | 46 +++++++++--- + 3 files changed, 110 insertions(+), 39 deletions(-) + +diff --git a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc +index 61c6957d27..473f913466 100644 +--- a/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc ++++ b/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc +@@ -14,7 +14,6 @@ + #include <libdrm/drm_fourcc.h> + #include <pipewire/pipewire.h> + #include <spa/param/video/format-utils.h> +-#include <sys/mman.h> + + #include <vector> + +@@ -49,33 +48,6 @@ constexpr int CursorMetaSize(int w, int h) { + constexpr PipeWireVersion kDmaBufModifierMinVersion = {0, 3, 33}; + constexpr PipeWireVersion kDropSingleModifierMinVersion = {0, 3, 40}; + +-class ScopedBuf { +- public: +- ScopedBuf() {} +- ScopedBuf(uint8_t* map, int map_size, int fd) +- : map_(map), map_size_(map_size), fd_(fd) {} +- ~ScopedBuf() { +- if (map_ != MAP_FAILED) { +- munmap(map_, map_size_); +- } +- } +- +- explicit operator bool() { return map_ != MAP_FAILED; } +- +- void initialize(uint8_t* map, int map_size, int fd) { +- map_ = map; +- map_size_ = map_size; +- fd_ = fd; +- } +- +- uint8_t* get() { return map_; } +- +- protected: +- uint8_t* map_ = static_cast<uint8_t*>(MAP_FAILED); +- int map_size_; +- int fd_; +-}; +- + class SharedScreenCastStreamPrivate { + public: + SharedScreenCastStreamPrivate(); +diff --git a/modules/portal/pipewire_utils.h b/modules/portal/pipewire_utils.h +index 8344a8cefb..c1327b85c9 100644 +--- a/modules/portal/pipewire_utils.h ++++ b/modules/portal/pipewire_utils.h +@@ -11,6 +11,21 @@ + #ifndef MODULES_PORTAL_PIPEWIRE_UTILS_H_ + #define MODULES_PORTAL_PIPEWIRE_UTILS_H_ + ++#include <errno.h> ++#include <stdint.h> ++#include <sys/ioctl.h> ++#include <sys/mman.h> ++ ++// 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) ++ + struct pw_thread_loop; + + namespace webrtc { +@@ -32,6 +47,66 @@ class PipeWireThreadLoopLock { + pw_thread_loop* const loop_; + }; + ++// We should synchronize DMA Buffer object access from CPU to avoid potential ++// cache incoherency and data loss. ++// See ++// https://01.org/linuxgraphics/gfx-docs/drm/driver-api/dma-buf.html#cpu-access-to-dma-buffer-objects ++static bool 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) { ++ return false; ++ } else { ++ break; ++ } ++ } ++ ++ return true; ++} ++ ++class ScopedBuf { ++ public: ++ ScopedBuf() {} ++ ScopedBuf(uint8_t* map, int map_size, int fd, bool is_dma_buf = false) ++ : map_(map), map_size_(map_size), fd_(fd), is_dma_buf_(is_dma_buf) {} ++ ~ScopedBuf() { ++ if (map_ != MAP_FAILED) { ++ if (is_dma_buf_) { ++ SyncDmaBuf(fd_, DMA_BUF_SYNC_END); ++ } ++ munmap(map_, map_size_); ++ } ++ } ++ ++ explicit operator bool() { return map_ != MAP_FAILED; } ++ ++ void initialize(uint8_t* map, int map_size, int fd, bool is_dma_buf = false) { ++ map_ = map; ++ map_size_ = map_size; ++ is_dma_buf_ = is_dma_buf; ++ fd_ = fd; ++ ++ if (is_dma_buf_) { ++ SyncDmaBuf(fd_, DMA_BUF_SYNC_START); ++ } ++ } ++ ++ uint8_t* get() { return map_; } ++ ++ protected: ++ uint8_t* map_ = static_cast<uint8_t*>(MAP_FAILED); ++ int map_size_; ++ int fd_; ++ bool is_dma_buf_; ++}; ++ + } // namespace webrtc + + #endif // MODULES_PORTAL_PIPEWIRE_UTILS_H_ +diff --git a/modules/video_capture/linux/video_capture_pipewire.cc b/modules/video_capture/linux/video_capture_pipewire.cc +index 8af483636a..319824d3c5 100644 +--- a/modules/video_capture/linux/video_capture_pipewire.cc ++++ b/modules/video_capture/linux/video_capture_pipewire.cc +@@ -178,8 +178,7 @@ int32_t VideoCaptureModulePipeWire::StartCapture( + int res = pw_stream_connect( + stream_, PW_DIRECTION_INPUT, node_id_, + static_cast<enum pw_stream_flags>(PW_STREAM_FLAG_AUTOCONNECT | +- PW_STREAM_FLAG_DONT_RECONNECT | +- PW_STREAM_FLAG_MAP_BUFFERS), ++ PW_STREAM_FLAG_DONT_RECONNECT), + params.data(), params.size()); + if (res != 0) { + RTC_LOG(LS_ERROR) << "Could not connect to camera stream: " +@@ -312,11 +311,11 @@ void VideoCaptureModulePipeWire::OnFormatChanged(const struct spa_pod* format) { + 0); + } + ++ const int buffer_types = ++ (1 << SPA_DATA_DmaBuf) | (1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr); + spa_pod_builder_add( + &builder, SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 1, 32), +- SPA_PARAM_BUFFERS_dataType, +- SPA_POD_CHOICE_FLAGS_Int((1 << SPA_DATA_MemFd) | (1 << SPA_DATA_MemPtr)), +- 0); ++ SPA_PARAM_BUFFERS_dataType, SPA_POD_CHOICE_FLAGS_Int(buffer_types), 0); + params.push_back( + static_cast<spa_pod*>(spa_pod_builder_pop(&builder, &frame))); + +@@ -384,14 +383,15 @@ void VideoCaptureModulePipeWire::ProcessBuffers() { + RTC_CHECK_RUNS_SERIALIZED(&capture_checker_); + + while (pw_buffer* buffer = pw_stream_dequeue_buffer(stream_)) { ++ spa_buffer* spaBuffer = buffer->buffer; + struct spa_meta_header* h; + h = static_cast<struct spa_meta_header*>( +- spa_buffer_find_meta_data(buffer->buffer, SPA_META_Header, sizeof(*h))); ++ spa_buffer_find_meta_data(spaBuffer, SPA_META_Header, sizeof(*h))); + + struct spa_meta_videotransform* videotransform; + videotransform = + static_cast<struct spa_meta_videotransform*>(spa_buffer_find_meta_data( +- buffer->buffer, SPA_META_VideoTransform, sizeof(*videotransform))); ++ spaBuffer, SPA_META_VideoTransform, sizeof(*videotransform))); + if (videotransform) { + VideoRotation rotation = + VideorotationFromPipeWireTransform(videotransform->transform); +@@ -401,11 +401,35 @@ void VideoCaptureModulePipeWire::ProcessBuffers() { + + if (h->flags & SPA_META_HEADER_FLAG_CORRUPTED) { + RTC_LOG(LS_INFO) << "Dropping corruped frame."; +- } else { +- IncomingFrame(static_cast<unsigned char*>(buffer->buffer->datas[0].data), +- buffer->buffer->datas[0].chunk->size, +- configured_capability_); ++ pw_stream_queue_buffer(stream_, buffer); ++ continue; ++ } ++ ++ if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf || ++ spaBuffer->datas[0].type == SPA_DATA_MemFd) { ++ ScopedBuf frame; ++ frame.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, ++ spaBuffer->datas[0].fd, spaBuffer->datas[0].type == SPA_DATA_DmaBuf); ++ ++ if (!frame) { ++ RTC_LOG(LS_ERROR) << "Failed to mmap the memory: " ++ << std::strerror(errno); ++ return; ++ } ++ ++ IncomingFrame( ++ SPA_MEMBER(frame.get(), spaBuffer->datas[0].mapoffset, uint8_t), ++ spaBuffer->datas[0].chunk->size, configured_capability_); ++ } else { // SPA_DATA_MemPtr ++ IncomingFrame(static_cast<uint8_t*>(spaBuffer->datas[0].data), ++ spaBuffer->datas[0].chunk->size, configured_capability_); + } ++ + pw_stream_queue_buffer(stream_, buffer); + } + } |