Opened 2 years ago

Closed 21 months ago

#9967 closed enhancement (fixed)

[vaapi] av_hwframe_map with AV_PIX_FMT_PRIME_FD calls vaExportSurfaceHandle, but not vaSyncSurface

Reported by: goffioul Owned by:
Priority: normal Component: avutil
Version: unspecified Keywords: vaapi
Cc: Blocked By:
Blocking: Reproduced by developer: no
Analyzed by developer: no

Description

When mapping a VA-API frame with av_hwframe_map and AV_PIX_FMT_PRIME_FD, vaExportSurfaceHandle is called to create the file descriptor, but it does not call vaSyncSurface. As a result, mmap'ing the file descriptor and reading from it may not yield correct result and lead to tearing artefact.

Technically, the client app could probably call vaSyncSurface itself, but that would require accessing internals of ffmpeg, e.g. to access the VA display. It would be cleaner if the VA-API bits were entirely managed by ffmpeg.

Change History (5)

comment:1 by Carl Eugen Hoyos, 2 years ago

Keywords: vaapi added
Version: unspecified

comment:2 by Fei Wang, 21 months ago

Could you verify if the patch fixed your issue? Thanks!
https://github.com/intel-media-ci/ffmpeg/pull/626

comment:3 by goffioul, 21 months ago

@wangfei: I'm sorry, I won't be able to confirm, my client code has moved on too much and is not mapping anymore the VA-API frame to a prime fd. I can however confirm that at the time I submitted this bug, I was using the following patch locally, which effectively avoided the tearing artefact. While not being identical, it should be functionally equivalent. The main difference is that vaSynSurface was called aftervaExportSurfaceHandle.

diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c
index 01ac91c33b..e2d0217fe1 100644
--- a/libavutil/hwcontext_vaapi.c
+++ b/libavutil/hwcontext_vaapi.c
@@ -1306,6 +1306,7 @@ static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst,
                "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
         return AVERROR(EIO);
     }
+    vaSyncSurface(hwctx->display, surface_id);

     drm_desc = av_mallocz(sizeof(*drm_desc));
     if (!drm_desc) {

in reply to:  3 comment:4 by Fei Wang, 21 months ago

Replying to goffioul:

@wangfei: I'm sorry, I won't be able to confirm, my client code has moved on too much and is not mapping anymore the VA-API frame to a prime fd. I can however confirm that at the time I submitted this bug, I was using the following patch locally, which effectively avoided the tearing artefact. While not being identical, it should be functionally equivalent. The main difference is that vaSynSurface was called aftervaExportSurfaceHandle.

diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c
index 01ac91c33b..e2d0217fe1 100644
--- a/libavutil/hwcontext_vaapi.c
+++ b/libavutil/hwcontext_vaapi.c
@@ -1306,6 +1306,7 @@ static int vaapi_map_to_drm_esh(AVHWFramesContext *hwfc, AVFrame *dst,
                "%d (%s).\n", surface_id, vas, vaErrorStr(vas));
         return AVERROR(EIO);
     }
+    vaSyncSurface(hwctx->display, surface_id);

     drm_desc = av_mallocz(sizeof(*drm_desc));
     if (!drm_desc) {

Hi @goffioul, It should have same effect to sync surface before or after export its dma fd. Prefer to follow the description in libva to add it before export. I will submit my patch into ML. And thanks for your information.

comment:5 by Fei Wang, 21 months ago

Resolution: fixed
Status: newclosed

Patch upstreamed. Tks.

Note: See TracTickets for help on using tickets.