diff options
author | Derek Buitenhuis <derek.buitenhuis@gmail.com> | 2016-05-11 19:40:30 +0100 |
---|---|---|
committer | Derek Buitenhuis <derek.buitenhuis@gmail.com> | 2016-05-11 19:40:39 +0100 |
commit | 8ed427f9f92fd45c2510c019dba932acda74817f (patch) | |
tree | 860dca02a5cf782100e7abf6a64a35ddab5f967d | |
parent | bc3d2f25783a4f61b7018800a12182dc46ff8325 (diff) | |
parent | 92fdea37477b5a2d1329e5ef0773e24473fa8f12 (diff) | |
download | ffmpeg-8ed427f9f92fd45c2510c019dba932acda74817f.tar.gz |
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@gmail.com>
-rw-r--r-- | libavcodec/vaapi_encode.c | 14 | ||||
-rw-r--r-- | libavcodec/vaapi_encode.h | 15 | ||||
-rw-r--r-- | libavcodec/vaapi_encode_h264.c | 196 | ||||
-rw-r--r-- | libavcodec/vaapi_encode_h265.c | 171 | ||||
-rw-r--r-- | 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 24b05a9031..329b33cbee 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 ceab4160d2..b67168b1ef 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 12bd71d103..0a99bb19ae 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 87ebd57023..05d3aa41da 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 ef944d1b66..316b3595c8 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) { |