diff options
author | Lynne <dev@lynne.ee> | 2020-11-20 18:23:42 +0100 |
---|---|---|
committer | Lynne <dev@lynne.ee> | 2020-11-25 23:06:34 +0100 |
commit | 993d8d94296e72cf5a1185fac573ba3c6ce3113d (patch) | |
tree | e667778ceb37879ce4c99b448fe8fff99e03c8e6 | |
parent | dd3486101825dbe956405b7d96a5c5ac7f866158 (diff) | |
download | ffmpeg-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.c | 36 |
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; |