aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLynne <dev@lynne.ee>2020-11-20 18:23:42 +0100
committerLynne <dev@lynne.ee>2020-11-25 23:06:34 +0100
commit993d8d94296e72cf5a1185fac573ba3c6ce3113d (patch)
treee667778ceb37879ce4c99b448fe8fff99e03c8e6
parentdd3486101825dbe956405b7d96a5c5ac7f866158 (diff)
downloadffmpeg-993d8d94296e72cf5a1185fac573ba3c6ce3113d.tar.gz
hwcontext_drm: issue DMA_BUF_IOCTL_SYNC when mapping FDs
This improves performance and helps a little when given FDs without any synchronization fences.
-rw-r--r--libavutil/hwcontext_drm.c36
1 files changed, 31 insertions, 5 deletions
diff --git a/libavutil/hwcontext_drm.c b/libavutil/hwcontext_drm.c
index 32cbde82eb..ceacf683a0 100644
--- a/libavutil/hwcontext_drm.c
+++ b/libavutil/hwcontext_drm.c
@@ -19,6 +19,8 @@
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
+#include <linux/dma-buf.h>
+#include <sys/ioctl.h>
#include <drm.h>
#include <xf86drm.h>
@@ -85,6 +87,8 @@ static int drm_get_buffer(AVHWFramesContext *hwfc, AVFrame *frame)
typedef struct DRMMapping {
// Address and length of each mmap()ed region.
int nb_regions;
+ int sync_flags;
+ int object[AV_DRM_MAX_PLANES];
void *address[AV_DRM_MAX_PLANES];
size_t length[AV_DRM_MAX_PLANES];
} DRMMapping;
@@ -93,10 +97,16 @@ static void drm_unmap_frame(AVHWFramesContext *hwfc,
HWMapDescriptor *hwmap)
{
DRMMapping *map = hwmap->priv;
- int i;
-
- for (i = 0; i < map->nb_regions; i++)
+ struct dma_buf_sync sync = { .flags = DMA_BUF_SYNC_END | map->sync_flags };
+ int i, ret;
+
+ for (i = 0; i < map->nb_regions; i++) {
+ ret = ioctl(map->object[i], DMA_BUF_IOCTL_SYNC, &sync);
+ if (ret)
+ av_log(hwfc, AV_LOG_ERROR, "Failed to issue ioctl sync to DRM object "
+ "%d: %d.\n", map->object[i], errno);
munmap(map->address[i], map->length[i]);
+ }
av_free(map);
}
@@ -105,6 +115,7 @@ static int drm_map_frame(AVHWFramesContext *hwfc,
AVFrame *dst, const AVFrame *src, int flags)
{
const AVDRMFrameDescriptor *desc = (AVDRMFrameDescriptor*)src->data[0];
+ struct dma_buf_sync sync_start = { 0 };
DRMMapping *map;
int err, i, p, plane;
int mmap_prot;
@@ -115,10 +126,16 @@ static int drm_map_frame(AVHWFramesContext *hwfc,
return AVERROR(ENOMEM);
mmap_prot = 0;
- if (flags & AV_HWFRAME_MAP_READ)
+ if (flags & AV_HWFRAME_MAP_READ) {
mmap_prot |= PROT_READ;
- if (flags & AV_HWFRAME_MAP_WRITE)
+ map->sync_flags |= DMA_BUF_SYNC_READ;
+ }
+ if (flags & AV_HWFRAME_MAP_WRITE) {
mmap_prot |= PROT_WRITE;
+ map->sync_flags |= DMA_BUF_SYNC_WRITE;
+ }
+
+ sync_start.flags = DMA_BUF_SYNC_START | map->sync_flags;
av_assert0(desc->nb_objects <= AV_DRM_MAX_PLANES);
for (i = 0; i < desc->nb_objects; i++) {
@@ -133,6 +150,15 @@ static int drm_map_frame(AVHWFramesContext *hwfc,
map->address[i] = addr;
map->length[i] = desc->objects[i].size;
+ map->object[i] = desc->objects[i].fd;
+
+ err = ioctl(desc->objects[i].fd, DMA_BUF_IOCTL_SYNC, &sync_start);
+ if (err) {
+ err = AVERROR(errno);
+ av_log(hwfc, AV_LOG_ERROR, "Failed to issue ioctl sync to DRM object "
+ "%d: %d.\n", desc->objects[i].fd, errno);
+ goto fail;
+ }
}
map->nb_regions = i;