[FFmpeg-devel] [PATCH] lavc/vaapi_decode: Set surfaces reference pool size according to SPS for H.264/HEVC

Linjie Fu linjie.fu at intel.com
Wed Nov 6 06:53:57 EET 2019


Set surfaces pool used for storing reference frames dynamically
according to SPS.(reference framecount, reordered frame number, etc)

Compared to a fixed pool size for H.264 and HEVC, the usage of
GPU memory could be improved.

CMD:
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128
        -i bbb_sunflower_1080p_30fps_normal.mp4 -f null -
Source:
    https://download.blender.org/demo/movies/BBB/

GEM Object memory usage:
    watch cat /sys/kernel/debug/dri/0/i915_gem_objects
Before:
    ~112M
After:
    ~80M

Signed-off-by: Linjie Fu <linjie.fu at intel.com>
---
 libavcodec/vaapi_decode.c | 39 ++++++++++++++++++---------------------
 libavcodec/vaapi_decode.h |  3 +++
 libavcodec/vaapi_h264.c   | 11 ++++++++++-
 libavcodec/vaapi_hevc.c   | 11 ++++++++++-
 libavcodec/vaapi_vp8.c    |  8 +++++++-
 libavcodec/vaapi_vp9.c    |  8 +++++++-
 6 files changed, 55 insertions(+), 25 deletions(-)

diff --git a/libavcodec/vaapi_decode.c b/libavcodec/vaapi_decode.c
index 69512e1d45..5fc9767802 100644
--- a/libavcodec/vaapi_decode.c
+++ b/libavcodec/vaapi_decode.c
@@ -408,7 +408,8 @@ static const struct {
 static int vaapi_decode_make_config(AVCodecContext *avctx,
                                     AVBufferRef *device_ref,
                                     VAConfigID *va_config,
-                                    AVBufferRef *frames_ref)
+                                    AVBufferRef *frames_ref,
+                                    int dpb_size)
 {
     AVVAAPIHWConfig       *hwconfig    = NULL;
     AVHWFramesConstraints *constraints = NULL;
@@ -549,22 +550,8 @@ static int vaapi_decode_make_config(AVCodecContext *avctx,
         if (err < 0)
             goto fail;
 
-        frames->initial_pool_size = 1;
-        // Add per-codec number of surfaces used for storing reference frames.
-        switch (avctx->codec_id) {
-        case AV_CODEC_ID_H264:
-        case AV_CODEC_ID_HEVC:
-            frames->initial_pool_size += 16;
-            break;
-        case AV_CODEC_ID_VP9:
-            frames->initial_pool_size += 8;
-            break;
-        case AV_CODEC_ID_VP8:
-            frames->initial_pool_size += 3;
-            break;
-        default:
-            frames->initial_pool_size += 2;
-        }
+        if (dpb_size > 0)
+            frames->initial_pool_size = dpb_size + 1;
     }
 
     av_hwframe_constraints_free(&constraints);
@@ -583,8 +570,9 @@ fail:
     return err;
 }
 
-int ff_vaapi_common_frame_params(AVCodecContext *avctx,
-                                 AVBufferRef *hw_frames_ctx)
+int ff_vaapi_frame_params_with_dpb_size(AVCodecContext *avctx,
+                                        AVBufferRef *hw_frames_ctx,
+                                        int dpb_size)
 {
     AVHWFramesContext *hw_frames = (AVHWFramesContext *)hw_frames_ctx->data;
     AVHWDeviceContext *device_ctx = hw_frames->device_ctx;
@@ -597,7 +585,7 @@ int ff_vaapi_common_frame_params(AVCodecContext *avctx,
     hwctx = device_ctx->hwctx;
 
     err = vaapi_decode_make_config(avctx, hw_frames->device_ref, &va_config,
-                                   hw_frames_ctx);
+                                   hw_frames_ctx, dpb_size);
     if (err)
         return err;
 
@@ -607,6 +595,13 @@ int ff_vaapi_common_frame_params(AVCodecContext *avctx,
     return 0;
 }
 
+int ff_vaapi_common_frame_params(AVCodecContext *avctx,
+                                 AVBufferRef *hw_frames_ctx)
+{
+    // Set common dpb_size for vc1/mjpeg/mpeg2/mpeg4.
+    return ff_vaapi_frame_params_with_dpb_size(avctx, hw_frames_ctx, 2);
+}
+
 int ff_vaapi_decode_init(AVCodecContext *avctx)
 {
     VAAPIDecodeContext *ctx = avctx->internal->hwaccel_priv_data;
@@ -666,7 +661,9 @@ int ff_vaapi_decode_init(AVCodecContext *avctx)
     ctx->hwctx  = ctx->device->hwctx;
 
     err = vaapi_decode_make_config(avctx, ctx->frames->device_ref,
-                                   &ctx->va_config, avctx->hw_frames_ctx);
+                                   &ctx->va_config, avctx->hw_frames_ctx,
+                                   0);
+
     if (err)
         goto fail;
 
diff --git a/libavcodec/vaapi_decode.h b/libavcodec/vaapi_decode.h
index 6b415dd1d3..c3e74bf9c7 100644
--- a/libavcodec/vaapi_decode.h
+++ b/libavcodec/vaapi_decode.h
@@ -98,6 +98,9 @@ int ff_vaapi_decode_cancel(AVCodecContext *avctx,
 int ff_vaapi_decode_init(AVCodecContext *avctx);
 int ff_vaapi_decode_uninit(AVCodecContext *avctx);
 
+int ff_vaapi_frame_params_with_dpb_size(AVCodecContext *avctx,
+                                        AVBufferRef *hw_frames_ctx,
+                                        int dpb_size);
 int ff_vaapi_common_frame_params(AVCodecContext *avctx,
                                  AVBufferRef *hw_frames_ctx);
 
diff --git a/libavcodec/vaapi_h264.c b/libavcodec/vaapi_h264.c
index dd2a657160..8d7f5c2004 100644
--- a/libavcodec/vaapi_h264.c
+++ b/libavcodec/vaapi_h264.c
@@ -385,6 +385,15 @@ static int vaapi_h264_decode_slice(AVCodecContext *avctx,
     return 0;
 }
 
+static int ff_vaapi_h264_frame_params(AVCodecContext *avctx,
+                                   AVBufferRef *hw_frames_ctx)
+{
+    const H264Context *h = avctx->priv_data;
+    const SPS       *sps = h->ps.sps;
+    return ff_vaapi_frame_params_with_dpb_size(avctx, hw_frames_ctx,
+                                               sps->ref_frame_count + sps->num_reorder_frames);
+}
+
 const AVHWAccel ff_h264_vaapi_hwaccel = {
     .name                 = "h264_vaapi",
     .type                 = AVMEDIA_TYPE_VIDEO,
@@ -396,7 +405,7 @@ const AVHWAccel ff_h264_vaapi_hwaccel = {
     .frame_priv_data_size = sizeof(VAAPIDecodePicture),
     .init                 = &ff_vaapi_decode_init,
     .uninit               = &ff_vaapi_decode_uninit,
-    .frame_params         = &ff_vaapi_common_frame_params,
+    .frame_params         = &ff_vaapi_h264_frame_params,
     .priv_data_size       = sizeof(VAAPIDecodeContext),
     .caps_internal        = HWACCEL_CAP_ASYNC_SAFE,
 };
diff --git a/libavcodec/vaapi_hevc.c b/libavcodec/vaapi_hevc.c
index c69d63d8ec..41e973626c 100644
--- a/libavcodec/vaapi_hevc.c
+++ b/libavcodec/vaapi_hevc.c
@@ -421,6 +421,15 @@ static int vaapi_hevc_decode_slice(AVCodecContext *avctx,
     return 0;
 }
 
+static int ff_vaapi_hevc_frame_params(AVCodecContext *avctx,
+                                   AVBufferRef *hw_frames_ctx)
+{
+    const HEVCContext *s = avctx->priv_data;
+    const HEVCSPS   *sps = s->ps.sps;
+    return ff_vaapi_frame_params_with_dpb_size(avctx, hw_frames_ctx,
+                                               sps->temporal_layer[sps->max_sub_layers - 1].max_dec_pic_buffering);
+}
+
 const AVHWAccel ff_hevc_vaapi_hwaccel = {
     .name                 = "hevc_vaapi",
     .type                 = AVMEDIA_TYPE_VIDEO,
@@ -432,7 +441,7 @@ const AVHWAccel ff_hevc_vaapi_hwaccel = {
     .frame_priv_data_size = sizeof(VAAPIDecodePictureHEVC),
     .init                 = ff_vaapi_decode_init,
     .uninit               = ff_vaapi_decode_uninit,
-    .frame_params         = ff_vaapi_common_frame_params,
+    .frame_params         = ff_vaapi_hevc_frame_params,
     .priv_data_size       = sizeof(VAAPIDecodeContext),
     .caps_internal        = HWACCEL_CAP_ASYNC_SAFE,
 };
diff --git a/libavcodec/vaapi_vp8.c b/libavcodec/vaapi_vp8.c
index 2426b30f13..4b74b9e0ad 100644
--- a/libavcodec/vaapi_vp8.c
+++ b/libavcodec/vaapi_vp8.c
@@ -220,6 +220,12 @@ fail:
     return err;
 }
 
+static int ff_vaapi_vp8_frame_params(AVCodecContext *avctx,
+                                  AVBufferRef *hw_frames_ctx)
+{
+    return ff_vaapi_frame_params_with_dpb_size(avctx, hw_frames_ctx, 3);
+}
+
 const AVHWAccel ff_vp8_vaapi_hwaccel = {
     .name                 = "vp8_vaapi",
     .type                 = AVMEDIA_TYPE_VIDEO,
@@ -231,7 +237,7 @@ const AVHWAccel ff_vp8_vaapi_hwaccel = {
     .frame_priv_data_size = sizeof(VAAPIDecodePicture),
     .init                 = &ff_vaapi_decode_init,
     .uninit               = &ff_vaapi_decode_uninit,
-    .frame_params         = &ff_vaapi_common_frame_params,
+    .frame_params         = &ff_vaapi_vp8_frame_params,
     .priv_data_size       = sizeof(VAAPIDecodeContext),
     .caps_internal        = HWACCEL_CAP_ASYNC_SAFE,
 };
diff --git a/libavcodec/vaapi_vp9.c b/libavcodec/vaapi_vp9.c
index f384ba7873..ce15701405 100644
--- a/libavcodec/vaapi_vp9.c
+++ b/libavcodec/vaapi_vp9.c
@@ -168,6 +168,12 @@ static int vaapi_vp9_decode_slice(AVCodecContext *avctx,
     return 0;
 }
 
+static int ff_vaapi_vp9_frame_params(AVCodecContext *avctx,
+                                  AVBufferRef *hw_frames_ctx)
+{
+    return ff_vaapi_frame_params_with_dpb_size(avctx, hw_frames_ctx, 8);
+}
+
 const AVHWAccel ff_vp9_vaapi_hwaccel = {
     .name                 = "vp9_vaapi",
     .type                 = AVMEDIA_TYPE_VIDEO,
@@ -179,7 +185,7 @@ const AVHWAccel ff_vp9_vaapi_hwaccel = {
     .frame_priv_data_size = sizeof(VAAPIDecodePicture),
     .init                 = ff_vaapi_decode_init,
     .uninit               = ff_vaapi_decode_uninit,
-    .frame_params         = ff_vaapi_common_frame_params,
+    .frame_params         = ff_vaapi_vp9_frame_params,
     .priv_data_size       = sizeof(VAAPIDecodeContext),
     .caps_internal        = HWACCEL_CAP_ASYNC_SAFE,
 };
-- 
2.17.1



More information about the ffmpeg-devel mailing list