diff options
Diffstat (limited to 'third_party/libwebrtc/moz-patch-stack/0106.patch')
-rw-r--r-- | third_party/libwebrtc/moz-patch-stack/0106.patch | 301 |
1 files changed, 235 insertions, 66 deletions
diff --git a/third_party/libwebrtc/moz-patch-stack/0106.patch b/third_party/libwebrtc/moz-patch-stack/0106.patch index 9f518a2ac0..7fcb865db5 100644 --- a/third_party/libwebrtc/moz-patch-stack/0106.patch +++ b/third_party/libwebrtc/moz-patch-stack/0106.patch @@ -1,74 +1,243 @@ -From: Dan Baker <dbaker@mozilla.com> -Date: Thu, 14 Mar 2024 10:51:00 -0600 -Subject: Bug 1883116 - (fix-e79e722834) add enviroment_factory to libwebrtc - build and enforce providing clock and task_queue when creating Environment +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 -Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/2185cab977988fd4ab03b38dc67f9b06162444da +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 --- - BUILD.gn | 1 + - api/environment/environment_factory.cc | 10 ++++++++++ - api/task_queue/BUILD.gn | 5 +++++ - 3 files changed, 16 insertions(+) + .../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/BUILD.gn b/BUILD.gn -index 7feca08e60..85ead4162f 100644 ---- a/BUILD.gn -+++ b/BUILD.gn -@@ -580,6 +580,7 @@ if (!build_with_chromium) { +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> - if (build_with_mozilla) { - deps += [ -+ "api/environment:environment_factory", - "api/video:video_frame", - "api/video:video_rtp_headers", - "test:rtp_test_utils", -diff --git a/api/environment/environment_factory.cc b/api/environment/environment_factory.cc -index c0b681aa08..6f0ec40dbe 100644 ---- a/api/environment/environment_factory.cc -+++ b/api/environment/environment_factory.cc -@@ -97,12 +97,22 @@ Environment EnvironmentFactory::CreateWithDefaults() && { - if (field_trials_ == nullptr) { - Set(std::make_unique<FieldTrialBasedConfig>()); - } -+#if defined(WEBRTC_MOZILLA_BUILD) -+ // We want to use our clock, not GetRealTimeClockRaw, and we avoid -+ // building the code under third_party/libwebrtc/task_queue. To -+ // ensure we're setting up things correctly, namely providing an -+ // Environment object with a preset task_queue_factory and clock, -+ // we'll do a release assert here. -+ RTC_CHECK(clock_); -+ RTC_CHECK(task_queue_factory_); -+#else - if (clock_ == nullptr) { - Set(Clock::GetRealTimeClock()); - } - if (task_queue_factory_ == nullptr) { - Set(CreateDefaultTaskQueueFactory(field_trials_)); - } -+#endif - if (event_log_ == nullptr) { - Set(std::make_unique<RtcEventLogNull>()); + #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); } -diff --git a/api/task_queue/BUILD.gn b/api/task_queue/BUILD.gn -index b9bc81171f..c24c22a1f6 100644 ---- a/api/task_queue/BUILD.gn -+++ b/api/task_queue/BUILD.gn -@@ -88,6 +88,10 @@ rtc_library("task_queue_test") { - } - rtc_library("default_task_queue_factory") { -+# Mozilla - disable this entire target to avoid inclusion of code we want -+# to avoid. Better here than trying to wack-a-mole for places that list -+# it as a dependency. -+if (!build_with_mozilla) { - visibility = [ "*" ] - if (!is_ios && !is_android) { - # Internally webrtc shouldn't rely on any specific TaskQueue implementation -@@ -126,6 +130,7 @@ rtc_library("default_task_queue_factory") { - sources += [ "default_task_queue_factory_stdlib.cc" ] - deps += [ "../../rtc_base:rtc_task_queue_stdlib" ] ++ 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); } -+} # of if (!build_with_mozilla) { } - - rtc_library("pending_task_safety_flag") { |