diff mbox

[FFmpeg-devel,1/2] lavu/hwcontext_vaapi: cope with race map for YUV420P

Message ID 1565843580-15176-1-git-send-email-linjie.fu@intel.com
State Superseded
Headers show

Commit Message

Fu, Linjie Aug. 15, 2019, 4:33 a.m. UTC
There is a race condition for AV_PIX_FMT_YUV420P when mapping from pix_fmt
to fourcc, both VA_FOURCC_I420 and VA_FOURCC_YV12 could be found by pix_fmt.

Currently, vaapi_get_image_format will go through the query results of
pix_fmt and returned the first matched result according to the declared
order in driver.This may leads to a wrong image_format.

Modify to find image_format via fourcc.

Fix vaapi CSC to I420:
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -f rawvideo
-pix_fmt nv12 -s:v 1280x720 -i NV12.yuv -vf
'format=nv12,hwupload,scale_vaapi=format=yuv420p,hwdownload,format=yuv420p'
-f rawvideo -vsync passthrough -vframes 10 -y aa.yuv

Reviewed-by: Zhong Li <zhong.li@intel.com>
Signed-off-by: Linjie Fu <linjie.fu@intel.com>
---
 libavutil/hwcontext_vaapi.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

Comments

Fu, Linjie Sept. 3, 2019, 8:09 a.m. UTC | #1
> -----Original Message-----
> From: Fu, Linjie
> Sent: Thursday, August 15, 2019 12:33
> To: ffmpeg-devel@ffmpeg.org
> Cc: Fu, Linjie <linjie.fu@intel.com>
> Subject: [PATCH 1/2] lavu/hwcontext_vaapi: cope with race map for
> YUV420P
> 
> There is a race condition for AV_PIX_FMT_YUV420P when mapping from
> pix_fmt
> to fourcc, both VA_FOURCC_I420 and VA_FOURCC_YV12 could be found by
> pix_fmt.
> 
> Currently, vaapi_get_image_format will go through the query results of
> pix_fmt and returned the first matched result according to the declared
> order in driver.This may leads to a wrong image_format.
> 
> Modify to find image_format via fourcc.
> 
> Fix vaapi CSC to I420:
> ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -f rawvideo
> -pix_fmt nv12 -s:v 1280x720 -i NV12.yuv -vf
> 'format=nv12,hwupload,scale_vaapi=format=yuv420p,hwdownload,format=
> yuv420p'
> -f rawvideo -vsync passthrough -vframes 10 -y aa.yuv
> 
> Reviewed-by: Zhong Li <zhong.li@intel.com>
> Signed-off-by: Linjie Fu <linjie.fu@intel.com>
> ---
>  libavutil/hwcontext_vaapi.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
> 
> diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c
> index cf11764..64f14de 100644
> --- a/libavutil/hwcontext_vaapi.c
> +++ b/libavutil/hwcontext_vaapi.c
> @@ -63,6 +63,7 @@ typedef struct VAAPIDevicePriv {
>  typedef struct VAAPISurfaceFormat {
>      enum AVPixelFormat pix_fmt;
>      VAImageFormat image_format;
> +    unsigned int fourcc;
>  } VAAPISurfaceFormat;
> 
>  typedef struct VAAPIDeviceContext {
> @@ -171,15 +172,21 @@ static int
> vaapi_get_image_format(AVHWDeviceContext *hwdev,
>                                    VAImageFormat **image_format)
>  {
>      VAAPIDeviceContext *ctx = hwdev->internal->priv;
> +    VAAPIFormatDescriptor *desc;
>      int i;
> 
> +    desc = vaapi_format_from_pix_fmt(pix_fmt);
> +    if (!desc || !image_format)
> +        goto fail;
> +
>      for (i = 0; i < ctx->nb_formats; i++) {
> -        if (ctx->formats[i].pix_fmt == pix_fmt) {
> -            if (image_format)
> -                *image_format = &ctx->formats[i].image_format;
> +        if (ctx->formats[i].fourcc == desc->fourcc) {
> +            *image_format = &ctx->formats[i].image_format;
>              return 0;
>          }
>      }
> +
> +fail:
>      return AVERROR(EINVAL);
>  }
> 
> @@ -368,6 +375,7 @@ static int vaapi_device_init(AVHWDeviceContext
> *hwdev)
>              av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> %s.\n",
>                     fourcc, av_get_pix_fmt_name(pix_fmt));
>              ctx->formats[ctx->nb_formats].pix_fmt      = pix_fmt;
> +            ctx->formats[ctx->nb_formats].fourcc       = fourcc;
>              ctx->formats[ctx->nb_formats].image_format = image_list[i];
>              ++ctx->nb_formats;
>          }
> --
> 2.7.4

Ping?
Apart from the CSC issue, this also enables directly hwmap for yuv420p
in ffmpeg vaapi and is able to improve the performance by eliminating
redundant memory copy.

Tested on local KBL environment, from 45 fps to 70 fps
		hwdownload		hwmap=mode=direct
YUV420P	45 fps			70 fps (1.5x)


Cmdline:
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -v verbose -hwaccel_output_format vaapi -i Nature.h264 -vf scale_vaapi=format=yuv420p,hwmap=mode=direct,format=yuv420p -f null -
diff mbox

Patch

diff --git a/libavutil/hwcontext_vaapi.c b/libavutil/hwcontext_vaapi.c
index cf11764..64f14de 100644
--- a/libavutil/hwcontext_vaapi.c
+++ b/libavutil/hwcontext_vaapi.c
@@ -63,6 +63,7 @@  typedef struct VAAPIDevicePriv {
 typedef struct VAAPISurfaceFormat {
     enum AVPixelFormat pix_fmt;
     VAImageFormat image_format;
+    unsigned int fourcc;
 } VAAPISurfaceFormat;
 
 typedef struct VAAPIDeviceContext {
@@ -171,15 +172,21 @@  static int vaapi_get_image_format(AVHWDeviceContext *hwdev,
                                   VAImageFormat **image_format)
 {
     VAAPIDeviceContext *ctx = hwdev->internal->priv;
+    VAAPIFormatDescriptor *desc;
     int i;
 
+    desc = vaapi_format_from_pix_fmt(pix_fmt);
+    if (!desc || !image_format)
+        goto fail;
+
     for (i = 0; i < ctx->nb_formats; i++) {
-        if (ctx->formats[i].pix_fmt == pix_fmt) {
-            if (image_format)
-                *image_format = &ctx->formats[i].image_format;
+        if (ctx->formats[i].fourcc == desc->fourcc) {
+            *image_format = &ctx->formats[i].image_format;
             return 0;
         }
     }
+
+fail:
     return AVERROR(EINVAL);
 }
 
@@ -368,6 +375,7 @@  static int vaapi_device_init(AVHWDeviceContext *hwdev)
             av_log(hwdev, AV_LOG_DEBUG, "Format %#x -> %s.\n",
                    fourcc, av_get_pix_fmt_name(pix_fmt));
             ctx->formats[ctx->nb_formats].pix_fmt      = pix_fmt;
+            ctx->formats[ctx->nb_formats].fourcc       = fourcc;
             ctx->formats[ctx->nb_formats].image_format = image_list[i];
             ++ctx->nb_formats;
         }