[FFmpeg-devel] [PATCH, RFC] lavc/vaapi_encode_h265: add support for low power mode for HEVC encode

Linjie Fu linjie.fu at intel.com
Thu Mar 5 09:41:00 EET 2020


Enable hevc_vaapi vdenc:
    - media-driver require CTU size must be set as 64x64 at low power mode
    - cu_qp_delta_enabled_flag should be enabled for low power mode
    - diff_cu_qp_delta_depth == log2_diff_max_min_luma_coding_block_size
    - low delay B to replace P frame
    - same ref_pic_list0/ref_pic_list1

Signed-off-by: Linjie Fu <linjie.fu at intel.com>
---
This should be rebased after the encoding query is supported in [1] and
low delay B support [2] for HEVC in media driver.

Sent out and request for comments.

[1] https://patchwork.ffmpeg.org/project/ffmpeg/patch/20200305002528.11418-3-sw@jkqxz.net/
[2] https://github.com/intel/libva/commit/f094de317b4f498b57d47d8b0823a2a24cb125e1

 libavcodec/vaapi_encode_h265.c | 34 ++++++++++++++++++++++++++++------
 1 file changed, 28 insertions(+), 6 deletions(-)

diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index 538862a..12f0e6f 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -437,9 +437,12 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
     // These have to come from the capabilities of the encoder.  We have no
     // way to query them, so just hardcode parameters which work on the Intel
     // driver.
-    // CTB size from 8x8 to 32x32.
+    // CTB size from 8x8 to 32x32. (64x64 when using low power mode for hw limitation)
     sps->log2_min_luma_coding_block_size_minus3   = 0;
-    sps->log2_diff_max_min_luma_coding_block_size = 2;
+    if (ctx->low_power)
+        sps->log2_diff_max_min_luma_coding_block_size = 3;
+    else
+        sps->log2_diff_max_min_luma_coding_block_size = 2;
     // Transform size from 4x4 to 32x32.
     sps->log2_min_luma_transform_block_size_minus2   = 0;
     sps->log2_diff_max_min_luma_transform_block_size = 3;
@@ -553,8 +556,10 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
 
     pps->init_qp_minus26 = priv->fixed_qp_idr - 26;
 
-    pps->cu_qp_delta_enabled_flag = (ctx->va_rc_mode != VA_RC_CQP);
-    pps->diff_cu_qp_delta_depth   = 0;
+    // driver requires enablement of cu_qp_delta_enabled_flag for low power mode encoding
+    pps->cu_qp_delta_enabled_flag = (ctx->va_rc_mode != VA_RC_CQP || ctx->low_power);
+    pps->diff_cu_qp_delta_depth   = pps->cu_qp_delta_enabled_flag && ctx->low_power ?
+                                        sps->log2_diff_max_min_luma_coding_block_size : 0;
 
     pps->pps_loop_filter_across_slices_enabled_flag = 1;
 
@@ -873,6 +878,7 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
                                                VAAPIEncodeSlice *slice)
 {
     VAAPIEncodeH265Context           *priv = avctx->priv_data;
+    VAAPIEncodeContext                *ctx = avctx->priv_data;
     VAAPIEncodeH265Picture           *hpic = pic->priv_data;
     const H265RawSPS                  *sps = &priv->raw_sps;
     const H265RawPPS                  *pps = &priv->raw_pps;
@@ -893,6 +899,9 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
     sh->slice_segment_address           = slice->block_start;
 
     sh->slice_type = hpic->slice_type;
+    // driver requires low delay B frame in low power mode
+    if (sh->slice_type == HEVC_SLICE_P && ctx->low_power)
+        sh->slice_type = HEVC_SLICE_B;
 
     sh->slice_pic_order_cnt_lsb = hpic->pic_order_cnt &
         (1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4)) - 1;
@@ -1059,6 +1068,16 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
         vslice->ref_pic_list1[0] = vpic->reference_frames[1];
     }
 
+    // Driver requires low delay B frame and matched ref_pic_list0/1[]
+    // for low power mode
+    if (pic->type == PICTURE_TYPE_P && ctx->low_power) {
+        vslice->slice_type = HEVC_SLICE_B;
+        for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) {
+            vslice->ref_pic_list1[i].picture_id = vslice->ref_pic_list0[i].picture_id;
+            vslice->ref_pic_list1[i].flags      = vslice->ref_pic_list0[i].flags;
+        }
+    }
+
     return 0;
 }
 
@@ -1175,8 +1194,11 @@ static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx)
     ctx->surface_width  = FFALIGN(avctx->width,  16);
     ctx->surface_height = FFALIGN(avctx->height, 16);
 
-    // CTU size is currently hard-coded to 32.
-    ctx->slice_block_width = ctx->slice_block_height = 32;
+    // CTU size is currently hard-coded to 32. (64 x 64 when using low power mode)
+    if (ctx->low_power)
+        ctx->slice_block_width = ctx->slice_block_height = 64;
+    else
+        ctx->slice_block_width = ctx->slice_block_height = 32;
 
     if (priv->qp > 0)
         ctx->explicit_qp = priv->qp;
-- 
2.7.4



More information about the ffmpeg-devel mailing list