[FFmpeg-devel] [PATCH] libavcodec/vaapi_encode: Change libva call to async way

wenbin.chen at intel.com wenbin.chen at intel.com
Mon Mar 8 04:43:29 EET 2021


From: "Chen,Wenbin" <wenbin.chen at intel.com>

Fix: #7706. After commit 5fdcf85bbffe7451c2, vaapi encoder's performance
drop 20~30%. One reason is that vaRenderPicture() and vaSyncSurface() are
called at the same time (vaRenderPicture() always followed by a
vaSyncSurface()). Now I changed them to be called in a
asynchronous way, which will make better use of hardware.

Another reason of performance drop is that in old version, ffmpeg-vaapi
use CQP as default while the ffmpeg-vaapi of lastest version does not,
so the same command line will have a even bigger performance gap. To
test this patch you'd better specify the bitrate (-b:v XXX).

Signed-off-by: Wenbin CHEN <wenbin.chen at intel.com>
---
 libavcodec/vaapi_encode.c | 42 +++++++++++++++++++++++++++++----------
 libavcodec/vaapi_encode.h |  3 +++
 2 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index 518e5b2c00..851dea3fc2 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -950,8 +950,10 @@ static int vaapi_encode_pick_next(AVCodecContext *avctx,
     if (!pic && ctx->end_of_stream) {
         --b_counter;
         pic = ctx->pic_end;
-        if (pic->encode_issued)
+        if (pic->encode_complete)
             return AVERROR_EOF;
+        else if (pic->encode_issued)
+            return AVERROR(EAGAIN);
     }
 
     if (!pic) {
@@ -1176,20 +1178,34 @@ int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
             return AVERROR(EAGAIN);
     }
 
-    pic = NULL;
-    err = vaapi_encode_pick_next(avctx, &pic);
-    if (err < 0)
-        return err;
-    av_assert0(pic);
+    if (av_fifo_size(ctx->encode_fifo) == 0) {
+        while (!err) {
+            pic = NULL;
+            err = vaapi_encode_pick_next(avctx, &pic);
+            if (err == AVERROR(EAGAIN))
+                break;
+            else if (err < 0)
+                return err;
+            av_assert0(pic);
 
-    pic->encode_order = ctx->encode_order++;
+            pic->encode_order = ctx->encode_order++;
 
-    err = vaapi_encode_issue(avctx, pic);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
-        return err;
+            err = vaapi_encode_issue(avctx, pic);
+            if (err < 0) {
+                av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
+                return err;
+            }
+
+            av_fifo_generic_write(ctx->encode_fifo, &pic, sizeof(pic), NULL);
+        }
     }
 
+    if (av_fifo_size(ctx->encode_fifo) == 0)
+        return err;
+
+    av_fifo_generic_read(ctx->encode_fifo, &pic, sizeof(pic), NULL);
+    ctx->encode_order = pic->encode_order+1;
+
     err = vaapi_encode_output(avctx, pic, pkt);
     if (err < 0) {
         av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err);
@@ -2519,6 +2535,10 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
         }
     }
 
+    ctx->encode_fifo = av_fifo_alloc((MAX_PICTURE_REFERENCES+1)* sizeof(VAAPIEncodePicture *));
+    if (!ctx->encode_fifo)
+        return AVERROR(ENOMEM);
+
     return 0;
 
 fail:
diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h
index b41604a883..89fe8de466 100644
--- a/libavcodec/vaapi_encode.h
+++ b/libavcodec/vaapi_encode.h
@@ -29,6 +29,7 @@
 
 #include "libavutil/hwcontext.h"
 #include "libavutil/hwcontext_vaapi.h"
+#include "libavutil/fifo.h"
 
 #include "avcodec.h"
 #include "hwconfig.h"
@@ -345,6 +346,8 @@ typedef struct VAAPIEncodeContext {
     int             roi_warned;
 
     AVFrame         *frame;
+
+    AVFifoBuffer *encode_fifo;
 } VAAPIEncodeContext;
 
 enum {
-- 
2.25.1



More information about the ffmpeg-devel mailing list