pipewire_utils.h (2881B)
1 /* 2 * Copyright 2022 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef MODULES_PORTAL_PIPEWIRE_UTILS_H_ 12 #define MODULES_PORTAL_PIPEWIRE_UTILS_H_ 13 14 #include <asm-generic/ioctl.h> 15 #include <sys/ioctl.h> 16 #include <sys/mman.h> 17 18 #include <cerrno> 19 #include <cstdint> 20 21 // static 22 struct dma_buf_sync { 23 uint64_t flags; 24 }; 25 #define DMA_BUF_SYNC_READ (1 << 0) 26 #define DMA_BUF_SYNC_START (0 << 2) 27 #define DMA_BUF_SYNC_END (1 << 2) 28 #define DMA_BUF_BASE 'b' 29 #define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) 30 31 struct pw_thread_loop; 32 33 namespace webrtc { 34 35 constexpr int kInvalidPipeWireFd = -1; 36 37 // Prepare PipeWire so that it is ready to be used. If it needs to be dlopen'd 38 // this will do so. Note that this does not guarantee a PipeWire server is 39 // running nor does it establish a connection to one. 40 bool InitializePipeWire(); 41 42 // Locks pw_thread_loop in the current scope 43 class PipeWireThreadLoopLock { 44 public: 45 explicit PipeWireThreadLoopLock(pw_thread_loop* loop); 46 ~PipeWireThreadLoopLock(); 47 48 private: 49 pw_thread_loop* const loop_; 50 }; 51 52 // We should synchronize DMA Buffer object access from CPU to avoid potential 53 // cache incoherency and data loss. 54 // See 55 // https://01.org/linuxgraphics/gfx-docs/drm/driver-api/dma-buf.html#cpu-access-to-dma-buffer-objects 56 static bool SyncDmaBuf(int fd, uint64_t start_or_end) { 57 struct dma_buf_sync sync = {0}; 58 59 sync.flags = start_or_end | DMA_BUF_SYNC_READ; 60 61 while (true) { 62 int ret; 63 ret = ioctl(fd, DMA_BUF_IOCTL_SYNC, &sync); 64 if (ret == -1 && errno == EINTR) { 65 continue; 66 } else if (ret == -1) { 67 return false; 68 } else { 69 break; 70 } 71 } 72 73 return true; 74 } 75 76 class ScopedBuf { 77 public: 78 ScopedBuf() {} 79 ScopedBuf(uint8_t* map, int map_size, int fd, bool is_dma_buf = false) 80 : map_(map), map_size_(map_size), fd_(fd), is_dma_buf_(is_dma_buf) {} 81 ~ScopedBuf() { 82 if (map_ != MAP_FAILED) { 83 if (is_dma_buf_) { 84 SyncDmaBuf(fd_, DMA_BUF_SYNC_END); 85 } 86 munmap(map_, map_size_); 87 } 88 } 89 90 explicit operator bool() { return map_ != MAP_FAILED; } 91 92 void initialize(uint8_t* map, int map_size, int fd, bool is_dma_buf = false) { 93 map_ = map; 94 map_size_ = map_size; 95 is_dma_buf_ = is_dma_buf; 96 fd_ = fd; 97 98 if (is_dma_buf_) { 99 SyncDmaBuf(fd_, DMA_BUF_SYNC_START); 100 } 101 } 102 103 uint8_t* get() { return map_; } 104 105 protected: 106 uint8_t* map_ = static_cast<uint8_t*>(MAP_FAILED); 107 int map_size_; 108 int fd_; 109 bool is_dma_buf_; 110 }; 111 112 } // namespace webrtc 113 114 #endif // MODULES_PORTAL_PIPEWIRE_UTILS_H_