gst: pool: Keep dmabufs mapped

Downstream elements accessing dmabufs from the CPU currently need to map
and unmap buffers on every frame.
While the kernel's page cache avoids most overhead, this still requires a
round-trip through the kernel and possibly non-negligible work in
`dma_buf_mmap()`. Keeping the buffers mapped avoids that without causing
additional syncronization work, as the later should only happen when
`DMA_BUF_IOCTL_SYNC` is triggered in `gst_dmabuf_mem_map()`.

A common scenario where this matters is clients using cameras. The
downstream elements in question may not be aware of dmabufs - e.g.
`videoconvert` - or fail to import the dmabuf and fall back to import
from memory - e.g. `glupload`.

Notes:
 - GstShmAllocator implicitly does this already.
 - We could also do this in the MemFd case, however I'm less convinced
   about the trade-offs.
This commit is contained in:
Robert Mader 2025-08-23 14:58:18 +02:00
parent 95497f8777
commit 5f3ae4376e

View file

@ -158,9 +158,28 @@ void gst_pipewire_pool_wrap_buffer (GstPipeWirePool *pool, struct pw_buffer *b)
gst_memory_resize (gmem, d->mapoffset, d->maxsize);
}
else if(d->type == SPA_DATA_DmaBuf) {
GstMapInfo info = { 0 };
GstFdMemoryFlags fd_flags = GST_FD_MEMORY_FLAG_NONE;
if (d->flags & SPA_DATA_FLAG_MAPPABLE && d->flags & SPA_DATA_FLAG_READABLE)
fd_flags |= GST_FD_MEMORY_FLAG_KEEP_MAPPED;
gmem = gst_fd_allocator_alloc (pool->dmabuf_allocator, dup(d->fd),
d->mapoffset + d->maxsize, GST_FD_MEMORY_FLAG_NONE);
d->mapoffset + d->maxsize, fd_flags);
gst_memory_resize (gmem, d->mapoffset, d->maxsize);
if (fd_flags & GST_FD_MEMORY_FLAG_KEEP_MAPPED) {
GstMapFlags map_flags = GST_MAP_READ;
if (d->flags & SPA_DATA_FLAG_WRITABLE)
map_flags |= GST_MAP_WRITE;
if (gst_memory_map (gmem, &info, map_flags)) {
gst_memory_unmap (gmem, &info);
} else {
GST_ERROR_OBJECT (pool, "mmaping buffer failed");
}
}
}
else if (d->type == SPA_DATA_MemPtr) {
gmem = gst_memory_new_wrapped (0, d->data, d->maxsize, 0,