diff mbox series

[FFmpeg-devel,V3,1/3] libavcodec/vaapi_encode: Add new API adaption to vaapi_encode

Message ID 20220208030549.340748-1-wenbin.chen@intel.com
State New
Headers show
Series [FFmpeg-devel,V3,1/3] libavcodec/vaapi_encode: Add new API adaption to vaapi_encode | expand

Checks

Context Check Description
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished
andriy/make_ppc success Make finished
andriy/make_fate_ppc success Make fate finished

Commit Message

Wenbin Chen Feb. 8, 2022, 3:05 a.m. UTC
Add vaSyncBuffer to VAAPI encoder. Old version API vaSyncSurface wait
surface to complete. When surface is used for multiple operation, it
waits all operations to finish. vaSyncBuffer only wait one channel to
finish.

Add wait param to vaapi_encode_wait() to prepare for the async_depth
option. "wait=1" means wait until operation ready. "wait=0" means
query operation's status. If it is ready return 0, if it is still
in progress return EAGAIN.

Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
---
 libavcodec/vaapi_encode.c | 47 +++++++++++++++++++++++++++++++++------
 1 file changed, 40 insertions(+), 7 deletions(-)

Comments

Xiang, Haihao Feb. 11, 2022, 4:07 a.m. UTC | #1
On Tue, 2022-02-08 at 11:05 +0800, Wenbin Chen wrote:
> Add vaSyncBuffer to VAAPI encoder. Old version API vaSyncSurface wait
> surface to complete. When surface is used for multiple operation, it
> waits all operations to finish. vaSyncBuffer only wait one channel to
> finish.
> 
> Add wait param to vaapi_encode_wait() to prepare for the async_depth
> option. "wait=1" means wait until operation ready. "wait=0" means
> query operation's status. If it is ready return 0, if it is still
> in progress return EAGAIN.
> 
> Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
> ---
>  libavcodec/vaapi_encode.c | 47 +++++++++++++++++++++++++++++++++------
>  1 file changed, 40 insertions(+), 7 deletions(-)
> 
> diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
> index 3bf379b1a0..b87b58a42b 100644
> --- a/libavcodec/vaapi_encode.c
> +++ b/libavcodec/vaapi_encode.c
> @@ -134,7 +134,8 @@ static int
> vaapi_encode_make_misc_param_buffer(AVCodecContext *avctx,
>  }
>  
>  static int vaapi_encode_wait(AVCodecContext *avctx,
> -                             VAAPIEncodePicture *pic)
> +                             VAAPIEncodePicture *pic,
> +                             uint8_t wait)
>  {
>      VAAPIEncodeContext *ctx = avctx->priv_data;
>      VAStatus vas;
> @@ -150,11 +151,43 @@ static int vaapi_encode_wait(AVCodecContext *avctx,
>             "(input surface %#x).\n", pic->display_order,
>             pic->encode_order, pic->input_surface);
>  
> -    vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface);
> -    if (vas != VA_STATUS_SUCCESS) {
> -        av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: "
> -               "%d (%s).\n", vas, vaErrorStr(vas));
> +#if VA_CHECK_VERSION(1, 9, 0)
> +    // Try vaSyncBuffer.
> +    vas = vaSyncBuffer(ctx->hwctx->display,
> +                       pic->output_buffer,
> +                       wait ? VA_TIMEOUT_INFINITE : 0);
> +    if (vas == VA_STATUS_ERROR_TIMEDOUT) {
> +        return AVERROR(EAGAIN);
> +    } else if (vas != VA_STATUS_SUCCESS && vas !=
> VA_STATUS_ERROR_UNIMPLEMENTED) {
> +        av_log(avctx, AV_LOG_ERROR, "Failed to sync to output buffer
> completion: "
> +                "%d (%s).\n", vas, vaErrorStr(vas));
>          return AVERROR(EIO);

We may add has_sync_buffer_func flag in this patch, and run the above code when
ctx->has_sync_buffer_func is true. If so, we needn't check whether vaSyncBuffer
is implemented again. 

Thanks
Haihao


> +    } else if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
> +    // If vaSyncBuffer is not implemented, try old version API.
> +#endif
> +    {
> +        if (!wait) {
> +            VASurfaceStatus surface_status;
> +            vas = vaQuerySurfaceStatus(ctx->hwctx->display,
> +                                    pic->input_surface,
> +                                    &surface_status);
> +            if (vas == VA_STATUS_SUCCESS &&
> +                surface_status != VASurfaceReady &&
> +                surface_status != VASurfaceSkipped) {
> +                return AVERROR(EAGAIN);
> +            } else if (vas != VA_STATUS_SUCCESS) {
> +                av_log(avctx, AV_LOG_ERROR, "Failed to query surface status:
> "
> +                    "%d (%s).\n", vas, vaErrorStr(vas));
> +                return AVERROR(EIO);
> +            }
> +        } else {
> +            vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface);
> +            if (vas != VA_STATUS_SUCCESS) {
> +                av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture
> completion: "
> +                    "%d (%s).\n", vas, vaErrorStr(vas));
> +                return AVERROR(EIO);
> +            }
> +        }
>      }
>  
>      // Input is definitely finished with now.
> @@ -633,7 +666,7 @@ static int vaapi_encode_output(AVCodecContext *avctx,
>      uint8_t *ptr;
>      int err;
>  
> -    err = vaapi_encode_wait(avctx, pic);
> +    err = vaapi_encode_wait(avctx, pic, 1);
>      if (err < 0)
>          return err;
>  
> @@ -695,7 +728,7 @@ fail:
>  static int vaapi_encode_discard(AVCodecContext *avctx,
>                                  VAAPIEncodePicture *pic)
>  {
> -    vaapi_encode_wait(avctx, pic);
> +    vaapi_encode_wait(avctx, pic, 1);
>  
>      if (pic->output_buffer_ref) {
>          av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "
Wenbin Chen Feb. 11, 2022, 5:16 a.m. UTC | #2
> On Tue, 2022-02-08 at 11:05 +0800, Wenbin Chen wrote:
> > Add vaSyncBuffer to VAAPI encoder. Old version API vaSyncSurface wait
> > surface to complete. When surface is used for multiple operation, it
> > waits all operations to finish. vaSyncBuffer only wait one channel to
> > finish.
> >
> > Add wait param to vaapi_encode_wait() to prepare for the async_depth
> > option. "wait=1" means wait until operation ready. "wait=0" means
> > query operation's status. If it is ready return 0, if it is still
> > in progress return EAGAIN.
> >
> > Signed-off-by: Wenbin Chen <wenbin.chen@intel.com>
> > ---
> >  libavcodec/vaapi_encode.c | 47 +++++++++++++++++++++++++++++++++---
> ---
> >  1 file changed, 40 insertions(+), 7 deletions(-)
> >
> > diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
> > index 3bf379b1a0..b87b58a42b 100644
> > --- a/libavcodec/vaapi_encode.c
> > +++ b/libavcodec/vaapi_encode.c
> > @@ -134,7 +134,8 @@ static int
> > vaapi_encode_make_misc_param_buffer(AVCodecContext *avctx,
> >  }
> >
> >  static int vaapi_encode_wait(AVCodecContext *avctx,
> > -                             VAAPIEncodePicture *pic)
> > +                             VAAPIEncodePicture *pic,
> > +                             uint8_t wait)
> >  {
> >      VAAPIEncodeContext *ctx = avctx->priv_data;
> >      VAStatus vas;
> > @@ -150,11 +151,43 @@ static int vaapi_encode_wait(AVCodecContext
> *avctx,
> >             "(input surface %#x).\n", pic->display_order,
> >             pic->encode_order, pic->input_surface);
> >
> > -    vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface);
> > -    if (vas != VA_STATUS_SUCCESS) {
> > -        av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: "
> > -               "%d (%s).\n", vas, vaErrorStr(vas));
> > +#if VA_CHECK_VERSION(1, 9, 0)
> > +    // Try vaSyncBuffer.
> > +    vas = vaSyncBuffer(ctx->hwctx->display,
> > +                       pic->output_buffer,
> > +                       wait ? VA_TIMEOUT_INFINITE : 0);
> > +    if (vas == VA_STATUS_ERROR_TIMEDOUT) {
> > +        return AVERROR(EAGAIN);
> > +    } else if (vas != VA_STATUS_SUCCESS && vas !=
> > VA_STATUS_ERROR_UNIMPLEMENTED) {
> > +        av_log(avctx, AV_LOG_ERROR, "Failed to sync to output buffer
> > completion: "
> > +                "%d (%s).\n", vas, vaErrorStr(vas));
> >          return AVERROR(EIO);
> 
> We may add has_sync_buffer_func flag in this patch, and run the above code
> when
> ctx->has_sync_buffer_func is true. If so, we needn't check whether
> vaSyncBuffer
> is implemented again.
> 
> Thanks
> Haihao

Thanks for your review. I will update the patchset.

Thanks
Wenbin
> 
> 
> > +    } else if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
> > +    // If vaSyncBuffer is not implemented, try old version API.
> > +#endif
> > +    {
> > +        if (!wait) {
> > +            VASurfaceStatus surface_status;
> > +            vas = vaQuerySurfaceStatus(ctx->hwctx->display,
> > +                                    pic->input_surface,
> > +                                    &surface_status);
> > +            if (vas == VA_STATUS_SUCCESS &&
> > +                surface_status != VASurfaceReady &&
> > +                surface_status != VASurfaceSkipped) {
> > +                return AVERROR(EAGAIN);
> > +            } else if (vas != VA_STATUS_SUCCESS) {
> > +                av_log(avctx, AV_LOG_ERROR, "Failed to query surface status:
> > "
> > +                    "%d (%s).\n", vas, vaErrorStr(vas));
> > +                return AVERROR(EIO);
> > +            }
> > +        } else {
> > +            vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface);
> > +            if (vas != VA_STATUS_SUCCESS) {
> > +                av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture
> > completion: "
> > +                    "%d (%s).\n", vas, vaErrorStr(vas));
> > +                return AVERROR(EIO);
> > +            }
> > +        }
> >      }
> >
> >      // Input is definitely finished with now.
> > @@ -633,7 +666,7 @@ static int vaapi_encode_output(AVCodecContext
> *avctx,
> >      uint8_t *ptr;
> >      int err;
> >
> > -    err = vaapi_encode_wait(avctx, pic);
> > +    err = vaapi_encode_wait(avctx, pic, 1);
> >      if (err < 0)
> >          return err;
> >
> > @@ -695,7 +728,7 @@ fail:
> >  static int vaapi_encode_discard(AVCodecContext *avctx,
> >                                  VAAPIEncodePicture *pic)
> >  {
> > -    vaapi_encode_wait(avctx, pic);
> > +    vaapi_encode_wait(avctx, pic, 1);
> >
> >      if (pic->output_buffer_ref) {
> >          av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
diff mbox series

Patch

diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index 3bf379b1a0..b87b58a42b 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -134,7 +134,8 @@  static int vaapi_encode_make_misc_param_buffer(AVCodecContext *avctx,
 }
 
 static int vaapi_encode_wait(AVCodecContext *avctx,
-                             VAAPIEncodePicture *pic)
+                             VAAPIEncodePicture *pic,
+                             uint8_t wait)
 {
     VAAPIEncodeContext *ctx = avctx->priv_data;
     VAStatus vas;
@@ -150,11 +151,43 @@  static int vaapi_encode_wait(AVCodecContext *avctx,
            "(input surface %#x).\n", pic->display_order,
            pic->encode_order, pic->input_surface);
 
-    vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface);
-    if (vas != VA_STATUS_SUCCESS) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: "
-               "%d (%s).\n", vas, vaErrorStr(vas));
+#if VA_CHECK_VERSION(1, 9, 0)
+    // Try vaSyncBuffer.
+    vas = vaSyncBuffer(ctx->hwctx->display,
+                       pic->output_buffer,
+                       wait ? VA_TIMEOUT_INFINITE : 0);
+    if (vas == VA_STATUS_ERROR_TIMEDOUT) {
+        return AVERROR(EAGAIN);
+    } else if (vas != VA_STATUS_SUCCESS && vas != VA_STATUS_ERROR_UNIMPLEMENTED) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to sync to output buffer completion: "
+                "%d (%s).\n", vas, vaErrorStr(vas));
         return AVERROR(EIO);
+    } else if (vas == VA_STATUS_ERROR_UNIMPLEMENTED)
+    // If vaSyncBuffer is not implemented, try old version API.
+#endif
+    {
+        if (!wait) {
+            VASurfaceStatus surface_status;
+            vas = vaQuerySurfaceStatus(ctx->hwctx->display,
+                                    pic->input_surface,
+                                    &surface_status);
+            if (vas == VA_STATUS_SUCCESS &&
+                surface_status != VASurfaceReady &&
+                surface_status != VASurfaceSkipped) {
+                return AVERROR(EAGAIN);
+            } else if (vas != VA_STATUS_SUCCESS) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to query surface status: "
+                    "%d (%s).\n", vas, vaErrorStr(vas));
+                return AVERROR(EIO);
+            }
+        } else {
+            vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface);
+            if (vas != VA_STATUS_SUCCESS) {
+                av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: "
+                    "%d (%s).\n", vas, vaErrorStr(vas));
+                return AVERROR(EIO);
+            }
+        }
     }
 
     // Input is definitely finished with now.
@@ -633,7 +666,7 @@  static int vaapi_encode_output(AVCodecContext *avctx,
     uint8_t *ptr;
     int err;
 
-    err = vaapi_encode_wait(avctx, pic);
+    err = vaapi_encode_wait(avctx, pic, 1);
     if (err < 0)
         return err;
 
@@ -695,7 +728,7 @@  fail:
 static int vaapi_encode_discard(AVCodecContext *avctx,
                                 VAAPIEncodePicture *pic)
 {
-    vaapi_encode_wait(avctx, pic);
+    vaapi_encode_wait(avctx, pic, 1);
 
     if (pic->output_buffer_ref) {
         av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "