[FFmpeg-devel,3/3] lavc/vaapi_encode_h265: respect "slices" option in h265 vaapi encoder

Submitted by Jun Zhao on July 30, 2018, 11:42 a.m.

Details

Message ID 1532950960-7640-4-git-send-email-mypopydev@gmail.com
State New
Headers show

Commit Message

Jun Zhao July 30, 2018, 11:42 a.m.
Enable multi-slice support in HEVC/H.265 vaapi encoder.

Signed-off-by: Wang, Yi A <yi.a.wang@intel.com>
Signed-off-by: Jun Zhao <jun.zhao@intel.com>
---
 libavcodec/vaapi_encode_h265.c |   30 ++++++++++++++++++++++++------
 1 files changed, 24 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index bbba2b8..cfdbeae 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -618,6 +618,7 @@  static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
     VAAPIEncodeH265Options           *opt = ctx->codec_options;
     VAEncPictureParameterBufferHEVC *vpic = pic->codec_picture_params;
     int i;
+    int slices;
 
     if (pic->type == PICTURE_TYPE_IDR) {
         av_assert0(pic->display_order == pic->encode_order);
@@ -788,7 +789,17 @@  static int vaapi_encode_h265_init_picture_params(AVCodecContext *avctx,
         av_assert0(0 && "invalid picture type");
     }
 
-    pic->nb_slices = 1;
+    slices = 1;
+    if (ctx->max_slices) {
+        if (avctx->slices <= FFMIN(ctx->max_slices, priv->ctu_height)) {
+            slices = FFMAX(avctx->slices, slices);
+        } else {
+            av_log(avctx, AV_LOG_ERROR, "The max slices number per frame "
+                   "cannot more than %d.\n", FFMIN(ctx->max_slices, priv->ctu_height));
+            return AVERROR_INVALIDDATA;
+        }
+    }
+    pic->nb_slices = slices;
 
     return 0;
 }
@@ -814,9 +825,8 @@  static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
 
     sh->slice_pic_parameter_set_id      = pps->pps_pic_parameter_set_id;
 
-    // Currently we only support one slice per frame.
-    sh->first_slice_segment_in_pic_flag = 1;
-    sh->slice_segment_address           = 0;
+    sh->first_slice_segment_in_pic_flag = !!(slice->index == 0);
+    sh->slice_segment_address           = slice->index * priv->ctu_width * (priv->ctu_height / pic->nb_slices);
 
     sh->slice_type = priv->slice_type;
 
@@ -906,7 +916,6 @@  static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
 
     *vslice = (VAEncSliceParameterBufferHEVC) {
         .slice_segment_address = sh->slice_segment_address,
-        .num_ctu_in_slice      = priv->ctu_width * priv->ctu_height,
 
         .slice_type                 = sh->slice_type,
         .slice_pic_parameter_set_id = sh->slice_pic_parameter_set_id,
@@ -927,7 +936,6 @@  static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
         .slice_tc_offset_div2   = sh->slice_tc_offset_div2,
 
         .slice_fields.bits = {
-            .last_slice_of_pic_flag       = 1,
             .dependent_slice_segment_flag = sh->dependent_slice_segment_flag,
             .colour_plane_id              = sh->colour_plane_id,
             .slice_temporal_mvp_enabled_flag =
@@ -945,6 +953,12 @@  static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
             .collocated_from_l0_flag      = sh->collocated_from_l0_flag,
         },
     };
+    if (slice->index == pic->nb_slices - 1) {
+        vslice->num_ctu_in_slice =  priv->ctu_width *  priv->ctu_height
+                                   - slice->index * priv->ctu_width * (priv->ctu_height / pic->nb_slices);
+        vslice->slice_fields.bits.last_slice_of_pic_flag = 1;
+    } else
+        vslice->num_ctu_in_slice = priv->ctu_width * (priv->ctu_height / pic->nb_slices);
 
     for (i = 0; i < FF_ARRAY_ELEMS(vslice->ref_pic_list0); i++) {
         vslice->ref_pic_list0[i].picture_id = VA_INVALID_ID;
@@ -1019,6 +1033,10 @@  static av_cold int vaapi_encode_h265_configure(AVCodecContext *avctx)
         av_assert0(0 && "Invalid RC mode.");
     }
 
+    if (!ctx->max_slices && avctx->slices > 0)
+        av_log(avctx, AV_LOG_WARNING, "The encode slice option is not "
+               "supported with the driver.\n");
+
     return 0;
 }