[FFmpeg-cvslog] Merge commit '92fdea37477b5a2d1329e5ef0773e24473fa8f12'

Derek Buitenhuis git at videolan.org
Wed May 11 20:41:07 CEST 2016


ffmpeg | branch: master | Derek Buitenhuis <derek.buitenhuis at gmail.com> | Wed May 11 19:40:30 2016 +0100| [8ed427f9f92fd45c2510c019dba932acda74817f] | committer: Derek Buitenhuis

Merge commit '92fdea37477b5a2d1329e5ef0773e24473fa8f12'

These are all trivial to merge.

* commit '92fdea37477b5a2d1329e5ef0773e24473fa8f12':
  vaapi_h265: Add -qp option, use it to replace use of -global_quality
  vaapi_h265: Add constant-bitrate encode support
  vaapi_h264: Add encode quality option (for quality-speed tradeoff)
  vaapi_h264: Add -qp option, use it to replace use of -global_quality
  vaapi_encode: Add support for codec-local options
  vaapi_h264: Add constant-bitrate encode support
  vaapi_encode: Refactor slightly to allow easier setting of global options

Merged-by: Derek Buitenhuis <derek.buitenhuis at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=8ed427f9f92fd45c2510c019dba932acda74817f
---

 libavcodec/vaapi_encode.c       |   14 +++
 libavcodec/vaapi_encode.h       |   15 ++-
 libavcodec/vaapi_encode_h264.c  |  196 ++++++++++++++++++++++++++++++++-------
 libavcodec/vaapi_encode_h265.c  |  171 +++++++++++++++++++++++++++-------
 libavcodec/vaapi_encode_mjpeg.c |   22 +++--
 5 files changed, 342 insertions(+), 76 deletions(-)

diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index 24b05a9..329b33c 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -202,6 +202,19 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
 
     pic->nb_param_buffers = 0;
 
+    if (pic->encode_order == 0) {
+        // Global parameter buffers are set on the first picture only.
+
+        for (i = 0; i < ctx->nb_global_params; i++) {
+            err = vaapi_encode_make_param_buffer(avctx, pic,
+                                                 VAEncMiscParameterBufferType,
+                                                 (char*)ctx->global_params[i],
+                                                 ctx->global_params_size[i]);
+            if (err < 0)
+                goto fail;
+        }
+    }
+
     if (pic->type == PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) {
         err = vaapi_encode_make_param_buffer(avctx, pic,
                                              VAEncSequenceParameterBufferType,
@@ -892,6 +905,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx,
     }
 
     ctx->codec = type;
+    ctx->codec_options = ctx->codec_options_data;
 
     ctx->priv_data = av_mallocz(type->priv_data_size);
     if (!ctx->priv_data) {
diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h
index ceab416..b67168b 100644
--- a/libavcodec/vaapi_encode.h
+++ b/libavcodec/vaapi_encode.h
@@ -32,6 +32,8 @@ struct VAAPIEncodeType;
 struct VAAPIEncodePicture;
 
 enum {
+    MAX_CONFIG_ATTRIBUTES  = 4,
+    MAX_GLOBAL_PARAMS      = 4,
     MAX_PICTURE_REFERENCES = 2,
     MAX_PICTURE_SLICES     = 1,
     MAX_PARAM_BUFFERS      = 16,
@@ -128,15 +130,19 @@ typedef struct VAAPIEncodeContext {
     AVBufferRef    *recon_frames_ref;
     AVHWFramesContext *recon_frames;
 
-    VAConfigAttrib *config_attributes;
+    VAConfigAttrib  config_attributes[MAX_CONFIG_ATTRIBUTES];
     int          nb_config_attributes;
 
+    VAEncMiscParameterBuffer *global_params[MAX_GLOBAL_PARAMS];
+    size_t          global_params_size[MAX_GLOBAL_PARAMS];
+    int          nb_global_params;
+
     // Per-sequence parameter structure (VAEncSequenceParameterBuffer*).
     void           *codec_sequence_params;
 
     // Per-sequence parameters found in the per-picture parameter
     // structure (VAEncPictureParameterBuffer*).
-    void *codec_picture_params;
+    void           *codec_picture_params;
 
     // Current encoding window, in display (input) order.
     VAAPIEncodePicture *pic_start, *pic_end;
@@ -166,6 +172,11 @@ typedef struct VAAPIEncodeContext {
     int p_counter;
     int end_of_stream;
 
+    // Codec-local options are allocated to follow this structure in
+    // memory (in the AVCodec definition, set priv_data_size to
+    // sizeof(VAAPIEncodeContext) + sizeof(VAAPIEncodeFooOptions)).
+    void *codec_options;
+    char codec_options_data[0];
 } VAAPIEncodeContext;
 
 
diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
index 12bd71d..0a99bb1 100644
--- a/libavcodec/vaapi_encode_h264.c
+++ b/libavcodec/vaapi_encode_h264.c
@@ -104,9 +104,30 @@ typedef struct VAAPIEncodeH264Context {
     int64_t idr_pic_count;
     int64_t last_idr_frame;
 
-    // RefPicList management.
+    // Rate control configuration.
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterRateControl rc;
+    } rc_params;
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterHRD hrd;
+    } hrd_params;
+
+#if VA_CHECK_VERSION(0, 36, 0)
+    // Speed-quality tradeoff setting.
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterBufferQualityLevel quality;
+    } quality_params;
+#endif
 } VAAPIEncodeH264Context;
 
+typedef struct VAAPIEncodeH264Options {
+    int qp;
+    int quality;
+} VAAPIEncodeH264Options;
+
 
 #define vseq_var(name)     vseq->name, name
 #define vseq_field(name)   vseq->seq_fields.bits.name, name
@@ -506,6 +527,19 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
         } else {
             vseq->frame_cropping_flag = 0;
         }
+
+        vseq->bits_per_second = avctx->bit_rate;
+        if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
+            vseq->num_units_in_tick = avctx->framerate.num;
+            vseq->time_scale        = 2 * avctx->framerate.den;
+        } else {
+            vseq->num_units_in_tick = avctx->time_base.num;
+            vseq->time_scale        = 2 * avctx->time_base.den;
+        }
+
+        vseq->intra_period     = ctx->p_per_i * (ctx->b_per_p + 1);
+        vseq->intra_idr_period = vseq->intra_period;
+        vseq->ip_period        = ctx->b_per_p + 1;
     }
 
     {
@@ -690,20 +724,94 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx,
     return 0;
 }
 
-static VAConfigAttrib vaapi_encode_h264_config_attributes[] = {
-    { .type  = VAConfigAttribRTFormat,
-      .value = VA_RT_FORMAT_YUV420 },
-    { .type  = VAConfigAttribRateControl,
-      .value = VA_RC_CQP },
-    { .type  = VAConfigAttribEncPackedHeaders,
-      .value = (VA_ENC_PACKED_HEADER_SEQUENCE |
-                VA_ENC_PACKED_HEADER_SLICE) },
-};
+static av_cold int vaapi_encode_h264_init_constant_bitrate(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext      *ctx = avctx->priv_data;
+    VAAPIEncodeH264Context *priv = ctx->priv_data;
+    int hrd_buffer_size;
+    int hrd_initial_buffer_fullness;
+
+    if (avctx->rc_buffer_size)
+        hrd_buffer_size = avctx->rc_buffer_size;
+    else
+        hrd_buffer_size = avctx->bit_rate;
+    if (avctx->rc_initial_buffer_occupancy)
+        hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
+    else
+        hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
+
+    priv->rc_params.misc.type = VAEncMiscParameterTypeRateControl;
+    priv->rc_params.rc = (VAEncMiscParameterRateControl) {
+        .bits_per_second   = avctx->bit_rate,
+        .target_percentage = 66,
+        .window_size       = 1000,
+        .initial_qp        = (avctx->qmax >= 0 ? avctx->qmax : 40),
+        .min_qp            = (avctx->qmin >= 0 ? avctx->qmin : 18),
+        .basic_unit_size   = 0,
+    };
+    ctx->global_params[ctx->nb_global_params] =
+        &priv->rc_params.misc;
+    ctx->global_params_size[ctx->nb_global_params++] =
+        sizeof(priv->rc_params);
+
+    priv->hrd_params.misc.type = VAEncMiscParameterTypeHRD;
+    priv->hrd_params.hrd = (VAEncMiscParameterHRD) {
+        .initial_buffer_fullness = hrd_initial_buffer_fullness,
+        .buffer_size             = hrd_buffer_size,
+    };
+    ctx->global_params[ctx->nb_global_params] =
+        &priv->hrd_params.misc;
+    ctx->global_params_size[ctx->nb_global_params++] =
+        sizeof(priv->hrd_params);
+
+    // These still need to be  set for pic_init_qp/slice_qp_delta.
+    priv->fixed_qp_idr = 26;
+    priv->fixed_qp_p   = 26;
+    priv->fixed_qp_b   = 26;
+
+    av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %d bps.\n",
+           avctx->bit_rate);
+    return 0;
+}
+
+static av_cold int vaapi_encode_h264_init_fixed_qp(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext      *ctx = avctx->priv_data;
+    VAAPIEncodeH264Context *priv = ctx->priv_data;
+    VAAPIEncodeH264Options  *opt = ctx->codec_options;
+
+    priv->fixed_qp_p = opt->qp;
+    if (avctx->i_quant_factor > 0.0)
+        priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor +
+                                    avctx->i_quant_offset) + 0.5);
+    else
+        priv->fixed_qp_idr = priv->fixed_qp_p;
+    if (avctx->b_quant_factor > 0.0)
+        priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor +
+                                  avctx->b_quant_offset) + 0.5);
+    else
+        priv->fixed_qp_b = priv->fixed_qp_p;
+
+    av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
+           "%d / %d / %d for IDR / P / B frames.\n",
+           priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
+    return 0;
+}
 
 static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx)
 {
+    static const VAConfigAttrib default_config_attributes[] = {
+        { .type  = VAConfigAttribRTFormat,
+          .value = VA_RT_FORMAT_YUV420 },
+        { .type  = VAConfigAttribEncPackedHeaders,
+          .value = (VA_ENC_PACKED_HEADER_SEQUENCE |
+                    VA_ENC_PACKED_HEADER_SLICE) },
+    };
+
     VAAPIEncodeContext      *ctx = avctx->priv_data;
     VAAPIEncodeH264Context *priv = ctx->priv_data;
+    VAAPIEncodeH264Options  *opt = ctx->codec_options;
+    int i, err;
 
     switch (avctx->profile) {
     case FF_PROFILE_H264_CONSTRAINED_BASELINE:
@@ -744,8 +852,6 @@ static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx)
     }
     ctx->va_entrypoint = VAEntrypointEncSlice;
 
-    ctx->va_rc_mode  = VA_RC_CQP;
-
     ctx->input_width    = avctx->width;
     ctx->input_height   = avctx->height;
     ctx->aligned_width  = FFALIGN(ctx->input_width,  16);
@@ -753,29 +859,41 @@ static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx)
     priv->mb_width      = ctx->aligned_width  / 16;
     priv->mb_height     = ctx->aligned_height / 16;
 
+    for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
+        ctx->config_attributes[ctx->nb_config_attributes++] =
+            default_config_attributes[i];
+    }
+
     if (avctx->bit_rate > 0) {
-        av_log(avctx, AV_LOG_ERROR, "Constant bitrate encoding is not "
-               "supported!\n");
-        return AVERROR_PATCHWELCOME;
+        ctx->va_rc_mode = VA_RC_CBR;
+        err = vaapi_encode_h264_init_constant_bitrate(avctx);
+    } else {
+        ctx->va_rc_mode = VA_RC_CQP;
+        err = vaapi_encode_h264_init_fixed_qp(avctx);
     }
+    if (err < 0)
+        return err;
 
-    priv->fixed_qp_p = avctx->global_quality;
-    if (avctx->i_quant_factor > 0.0)
-        priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor +
-                                    avctx->i_quant_offset) + 0.5);
-    else
-        priv->fixed_qp_idr = priv->fixed_qp_p;
-    if (avctx->b_quant_factor > 0.0)
-        priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor +
-                                  avctx->b_quant_offset) + 0.5);
-    else
-        priv->fixed_qp_b = priv->fixed_qp_p;
-    av_log(avctx, AV_LOG_DEBUG, "QP = %d / %d / %d for IDR / P / B frames.\n",
-           priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
+    ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) {
+        .type  = VAConfigAttribRateControl,
+        .value = ctx->va_rc_mode,
+    };
 
-    ctx->config_attributes = vaapi_encode_h264_config_attributes;
-    ctx->nb_config_attributes =
-        FF_ARRAY_ELEMS(vaapi_encode_h264_config_attributes);
+    if (opt->quality > 0) {
+#if VA_CHECK_VERSION(0, 36, 0)
+        priv->quality_params.misc.type =
+            VAEncMiscParameterTypeQualityLevel;
+        priv->quality_params.quality.quality_level = opt->quality;
+
+        ctx->global_params[ctx->nb_global_params] =
+            &priv->quality_params.misc;
+        ctx->global_params_size[ctx->nb_global_params++] =
+            sizeof(priv->quality_params);
+#else
+        av_log(avctx, AV_LOG_WARNING, "The encode quality option is not "
+               "supported with this VAAPI version.\n");
+#endif
+    }
 
     ctx->nb_recon_frames = 20;
 
@@ -808,13 +926,23 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
     return ff_vaapi_encode_init(avctx, &vaapi_encode_type_h264);
 }
 
+#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \
+                   offsetof(VAAPIEncodeH264Options, x))
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
+static const AVOption vaapi_encode_h264_options[] = {
+    { "qp", "Constant QP (for P frames; scaled by qfactor/qoffset for I/B)",
+      OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 20 }, 0, 52, FLAGS },
+    { "quality", "Set encode quality (trades off against speed, higher is faster)",
+      OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, FLAGS },
+    { NULL },
+};
+
 static const AVCodecDefault vaapi_encode_h264_defaults[] = {
     { "profile",        "100" },
     { "level",          "51"  },
     { "b",              "0"   },
     { "bf",             "2"   },
     { "g",              "120" },
-    { "global_quality", "20"  },
     { "i_qfactor",      "1.0" },
     { "i_qoffset",      "0.0" },
     { "b_qfactor",      "1.2" },
@@ -825,6 +953,7 @@ static const AVCodecDefault vaapi_encode_h264_defaults[] = {
 static const AVClass vaapi_encode_h264_class = {
     .class_name = "h264_vaapi",
     .item_name  = av_default_item_name,
+    .option     = vaapi_encode_h264_options,
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
@@ -833,7 +962,8 @@ AVCodec ff_h264_vaapi_encoder = {
     .long_name      = NULL_IF_CONFIG_SMALL("H.264/AVC (VAAPI)"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_H264,
-    .priv_data_size = sizeof(VAAPIEncodeContext),
+    .priv_data_size = (sizeof(VAAPIEncodeContext) +
+                       sizeof(VAAPIEncodeH264Options)),
     .init           = &vaapi_encode_h264_init,
     .encode2        = &ff_vaapi_encode2,
     .close          = &ff_vaapi_encode_close,
diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index 87ebd57..05d3aa4 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -182,8 +182,22 @@ typedef struct VAAPIEncodeH265Context {
     int fixed_qp_b;
 
     int64_t last_idr_frame;
+
+    // Rate control configuration.
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterRateControl rc;
+    } rc_params;
+    struct {
+        VAEncMiscParameterBuffer misc;
+        VAEncMiscParameterHRD hrd;
+    } hrd_params;
 } VAAPIEncodeH265Context;
 
+typedef struct VAAPIEncodeH265Options {
+    int qp;
+} VAAPIEncodeH265Options;
+
 
 #define vseq_var(name)     vseq->name, name
 #define vseq_field(name)   vseq->seq_fields.bits.name, name
@@ -806,6 +820,19 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
         vseq->max_transform_hierarchy_depth_intra = 3;
 
         vseq->vui_parameters_present_flag = 0;
+
+        vseq->bits_per_second = avctx->bit_rate;
+        if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
+            vseq->vui_num_units_in_tick = avctx->framerate.num;
+            vseq->vui_time_scale        = avctx->framerate.den;
+        } else {
+            vseq->vui_num_units_in_tick = avctx->time_base.num;
+            vseq->vui_time_scale        = avctx->time_base.den;
+        }
+
+        vseq->intra_period     = ctx->p_per_i * (ctx->b_per_p + 1);
+        vseq->intra_idr_period = vseq->intra_period;
+        vseq->ip_period        = ctx->b_per_p + 1;
     }
 
     {
@@ -841,8 +868,7 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
 
         vpic->pic_fields.bits.screen_content_flag = 0;
         vpic->pic_fields.bits.enable_gpu_weighted_prediction = 0;
-
-        //vpic->pic_fields.bits.cu_qp_delta_enabled_flag = 1;
+        vpic->pic_fields.bits.cu_qp_delta_enabled_flag = 1;
     }
 
     {
@@ -1125,20 +1151,93 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
     return 0;
 }
 
-static VAConfigAttrib vaapi_encode_h265_config_attributes[] = {
-    { .type  = VAConfigAttribRTFormat,
-      .value = VA_RT_FORMAT_YUV420 },
-    { .type  = VAConfigAttribRateControl,
-      .value = VA_RC_CQP },
-    { .type  = VAConfigAttribEncPackedHeaders,
-      .value = (VA_ENC_PACKED_HEADER_SEQUENCE |
-                VA_ENC_PACKED_HEADER_SLICE) },
-};
+static av_cold int vaapi_encode_h265_init_constant_bitrate(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext      *ctx = avctx->priv_data;
+    VAAPIEncodeH265Context *priv = ctx->priv_data;
+    int hrd_buffer_size;
+    int hrd_initial_buffer_fullness;
+
+    if (avctx->rc_buffer_size)
+        hrd_buffer_size = avctx->rc_buffer_size;
+    else
+        hrd_buffer_size = avctx->bit_rate;
+    if (avctx->rc_initial_buffer_occupancy)
+        hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
+    else
+        hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
+
+    priv->rc_params.misc.type = VAEncMiscParameterTypeRateControl;
+    priv->rc_params.rc = (VAEncMiscParameterRateControl) {
+        .bits_per_second   = avctx->bit_rate,
+        .target_percentage = 66,
+        .window_size       = 1000,
+        .initial_qp        = (avctx->qmax >= 0 ? avctx->qmax : 40),
+        .min_qp            = (avctx->qmin >= 0 ? avctx->qmin : 20),
+        .basic_unit_size   = 0,
+    };
+    ctx->global_params[ctx->nb_global_params] =
+        &priv->rc_params.misc;
+    ctx->global_params_size[ctx->nb_global_params++] =
+        sizeof(priv->rc_params);
+
+    priv->hrd_params.misc.type = VAEncMiscParameterTypeHRD;
+    priv->hrd_params.hrd = (VAEncMiscParameterHRD) {
+        .initial_buffer_fullness = hrd_initial_buffer_fullness,
+        .buffer_size             = hrd_buffer_size,
+    };
+    ctx->global_params[ctx->nb_global_params] =
+        &priv->hrd_params.misc;
+    ctx->global_params_size[ctx->nb_global_params++] =
+        sizeof(priv->hrd_params);
+
+    // These still need to be  set for pic_init_qp/slice_qp_delta.
+    priv->fixed_qp_idr = 30;
+    priv->fixed_qp_p   = 30;
+    priv->fixed_qp_b   = 30;
+
+    av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %d bps.\n",
+           avctx->bit_rate);
+    return 0;
+}
+
+static av_cold int vaapi_encode_h265_init_fixed_qp(AVCodecContext *avctx)
+{
+    VAAPIEncodeContext      *ctx = avctx->priv_data;
+    VAAPIEncodeH265Context *priv = ctx->priv_data;
+    VAAPIEncodeH265Options  *opt = ctx->codec_options;
+
+    priv->fixed_qp_p = opt->qp;
+    if (avctx->i_quant_factor > 0.0)
+        priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor +
+                                    avctx->i_quant_offset) + 0.5);
+    else
+        priv->fixed_qp_idr = priv->fixed_qp_p;
+    if (avctx->b_quant_factor > 0.0)
+        priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor +
+                                  avctx->b_quant_offset) + 0.5);
+    else
+        priv->fixed_qp_b = priv->fixed_qp_p;
+
+    av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
+           "%d / %d / %d for IDR / P / B frames.\n",
+           priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
+    return 0;
+}
 
 static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx)
 {
+    static const VAConfigAttrib default_config_attributes[] = {
+        { .type  = VAConfigAttribRTFormat,
+          .value = VA_RT_FORMAT_YUV420 },
+        { .type  = VAConfigAttribEncPackedHeaders,
+          .value = (VA_ENC_PACKED_HEADER_SEQUENCE |
+                    VA_ENC_PACKED_HEADER_SLICE) },
+    };
+
     VAAPIEncodeContext      *ctx = avctx->priv_data;
     VAAPIEncodeH265Context *priv = ctx->priv_data;
+    int i, err;
 
     switch (avctx->profile) {
     case FF_PROFILE_HEVC_MAIN:
@@ -1156,8 +1255,6 @@ static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx)
     }
     ctx->va_entrypoint = VAEntrypointEncSlice;
 
-    ctx->va_rc_mode  = VA_RC_CQP;
-
     ctx->input_width    = avctx->width;
     ctx->input_height   = avctx->height;
     ctx->aligned_width  = FFALIGN(ctx->input_width,  16);
@@ -1169,23 +1266,25 @@ static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx)
            ctx->input_width, ctx->input_height, ctx->aligned_width,
            ctx->aligned_height, priv->ctu_width, priv->ctu_height);
 
-    priv->fixed_qp_p = avctx->global_quality;
-    if (avctx->i_quant_factor > 0.0)
-        priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor +
-                                    avctx->i_quant_offset) + 0.5);
-    else
-        priv->fixed_qp_idr = priv->fixed_qp_p;
-    if (avctx->b_quant_factor > 0.0)
-        priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor +
-                                  avctx->b_quant_offset) + 0.5);
-    else
-        priv->fixed_qp_b = priv->fixed_qp_p;
-    av_log(avctx, AV_LOG_DEBUG, "QP = %d / %d / %d for IDR / P / B frames.\n",
-           priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
+    for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
+        ctx->config_attributes[ctx->nb_config_attributes++] =
+            default_config_attributes[i];
+    }
+
+    if (avctx->bit_rate > 0) {
+        ctx->va_rc_mode = VA_RC_CBR;
+        err = vaapi_encode_h265_init_constant_bitrate(avctx);
+    } else {
+        ctx->va_rc_mode = VA_RC_CQP;
+        err = vaapi_encode_h265_init_fixed_qp(avctx);
+    }
+    if (err < 0)
+        return err;
 
-    ctx->config_attributes = vaapi_encode_h265_config_attributes;
-    ctx->nb_config_attributes =
-        FF_ARRAY_ELEMS(vaapi_encode_h265_config_attributes);
+    ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) {
+        .type  = VAConfigAttribRateControl,
+        .value = ctx->va_rc_mode,
+    };
 
     ctx->nb_recon_frames = 20;
 
@@ -1218,13 +1317,21 @@ static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx)
     return ff_vaapi_encode_init(avctx, &vaapi_encode_type_h265);
 }
 
+#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \
+                   offsetof(VAAPIEncodeH265Options, x))
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
+static const AVOption vaapi_encode_h265_options[] = {
+    { "qp", "Constant QP (for P frames; scaled by qfactor/qoffset for I/B)",
+      OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, 52, FLAGS },
+    { NULL },
+};
+
 static const AVCodecDefault vaapi_encode_h265_defaults[] = {
     { "profile",        "1"   },
     { "level",          "51"  },
     { "b",              "0"   },
     { "bf",             "2"   },
     { "g",              "120" },
-    { "global_quality", "25"  },
     { "i_qfactor",      "1.0" },
     { "i_qoffset",      "0.0" },
     { "b_qfactor",      "1.2" },
@@ -1235,6 +1342,7 @@ static const AVCodecDefault vaapi_encode_h265_defaults[] = {
 static const AVClass vaapi_encode_h265_class = {
     .class_name = "h265_vaapi",
     .item_name  = av_default_item_name,
+    .option     = vaapi_encode_h265_options,
     .version    = LIBAVUTIL_VERSION_INT,
 };
 
@@ -1243,7 +1351,8 @@ AVCodec ff_hevc_vaapi_encoder = {
     .long_name      = NULL_IF_CONFIG_SMALL("H.265/HEVC (VAAPI)"),
     .type           = AVMEDIA_TYPE_VIDEO,
     .id             = AV_CODEC_ID_HEVC,
-    .priv_data_size = sizeof(VAAPIEncodeContext),
+    .priv_data_size = (sizeof(VAAPIEncodeContext) +
+                       sizeof(VAAPIEncodeH265Options)),
     .init           = &vaapi_encode_h265_init,
     .encode2        = &ff_vaapi_encode2,
     .close          = &ff_vaapi_encode_close,
diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c
index ef944d1..316b359 100644
--- a/libavcodec/vaapi_encode_mjpeg.c
+++ b/libavcodec/vaapi_encode_mjpeg.c
@@ -333,17 +333,18 @@ static int vaapi_encode_mjpeg_init_slice_params(AVCodecContext *avctx,
     return 0;
 }
 
-static VAConfigAttrib vaapi_encode_mjpeg_config_attributes[] = {
-    { .type  = VAConfigAttribRTFormat,
-      .value = VA_RT_FORMAT_YUV420 },
-    { .type  = VAConfigAttribEncPackedHeaders,
-      .value = VA_ENC_PACKED_HEADER_SEQUENCE },
-};
-
 static av_cold int vaapi_encode_mjpeg_init_internal(AVCodecContext *avctx)
 {
+    static const VAConfigAttrib default_config_attributes[] = {
+        { .type  = VAConfigAttribRTFormat,
+          .value = VA_RT_FORMAT_YUV420 },
+        { .type  = VAConfigAttribEncPackedHeaders,
+          .value = VA_ENC_PACKED_HEADER_SEQUENCE },
+    };
+
     VAAPIEncodeContext       *ctx = avctx->priv_data;
     VAAPIEncodeMJPEGContext *priv = ctx->priv_data;
+    int i;
 
     ctx->va_profile    = VAProfileJPEGBaseline;
     ctx->va_entrypoint = VAEntrypointEncPicture;
@@ -353,9 +354,10 @@ static av_cold int vaapi_encode_mjpeg_init_internal(AVCodecContext *avctx)
     ctx->aligned_width  = FFALIGN(ctx->input_width,  8);
     ctx->aligned_height = FFALIGN(ctx->input_height, 8);
 
-    ctx->config_attributes    = vaapi_encode_mjpeg_config_attributes;
-    ctx->nb_config_attributes =
-        FF_ARRAY_ELEMS(vaapi_encode_mjpeg_config_attributes);
+    for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
+        ctx->config_attributes[ctx->nb_config_attributes++] =
+            default_config_attributes[i];
+    }
 
     priv->quality = avctx->global_quality;
     if (priv->quality < 1 || priv->quality > 100) {


======================================================================




More information about the ffmpeg-cvslog mailing list