diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c index 9f2083d1f7..b1f00695c7 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, diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h index 1aea45884b..9716578e5a 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; diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c index 12a0ec2db1..6a77ab1e18 100644 --- a/libavcodec/vaapi_encode_h264.c +++ b/libavcodec/vaapi_encode_h264.c @@ -690,20 +690,21 @@ 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_internal(AVCodecContext *avctx) { + static const VAConfigAttrib default_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) }, + }; + VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH264Context *priv = ctx->priv_data; + int i; switch (avctx->profile) { case FF_PROFILE_H264_CONSTRAINED_BASELINE: @@ -759,6 +760,11 @@ static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx) return AVERROR_PATCHWELCOME; } + for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) { + ctx->config_attributes[ctx->nb_config_attributes++] = + default_config_attributes[i]; + } + 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 + @@ -773,10 +779,6 @@ static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx) 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 = vaapi_encode_h264_config_attributes; - ctx->nb_config_attributes = - FF_ARRAY_ELEMS(vaapi_encode_h264_config_attributes); - ctx->nb_recon_frames = 20; return 0; diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c index 0aa40e31b6..323efd46a7 100644 --- a/libavcodec/vaapi_encode_h265.c +++ b/libavcodec/vaapi_encode_h265.c @@ -1125,20 +1125,21 @@ 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_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) }, + { .type = VAConfigAttribRateControl, + .value = VA_RC_CQP }, + }; + VAAPIEncodeContext *ctx = avctx->priv_data; VAAPIEncodeH265Context *priv = ctx->priv_data; + int i; switch (avctx->profile) { case FF_PROFILE_HEVC_MAIN: @@ -1156,8 +1157,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,6 +1168,19 @@ 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); + 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, "H.265 constant-bitrate encoding " + "is not supported.\n"); + return AVERROR_PATCHWELCOME; + } + + ctx->va_rc_mode = VA_RC_CQP; + 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 + @@ -1183,10 +1195,6 @@ static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx) 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 = vaapi_encode_h265_config_attributes; - ctx->nb_config_attributes = - FF_ARRAY_ELEMS(vaapi_encode_h265_config_attributes); - ctx->nb_recon_frames = 20; return 0; diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c index 3ab3ab1e9f..e3bf191884 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) {