summaryrefslogtreecommitdiff
path: root/libavcodec/vaapi_encode.c
diff options
context:
space:
mode:
authorLinjie Fu <linjie.fu@intel.com>2022-05-05 17:07:14 +0800
committerHaihao Xiang <haihao.xiang@intel.com>2022-06-06 13:56:10 +0800
commit99446c74cf5f67635931312f23126b4c1f0274ef (patch)
tree8e6592730990776b63e786ffccf1003726a17f0f /libavcodec/vaapi_encode.c
parent5929ea6d4b1d979a5d888c3692fe24957a57e9c4 (diff)
downloadffmpeg-99446c74cf5f67635931312f23126b4c1f0274ef.tar.gz
lavc/vaapi_encode: add support for maxframesize
Add support for max frame size: - max_frame_size (bytes) to indicate the max allowed size for frame. Control each encoded frame size into target limitation size by adjusting whole frame's average QP value. The driver will use multi passes to adjust average QP setp by step to achieve the target, and the result may not strictly guaranteed. Frame size may exceed target alone with using the maximum average QP value. The failure always happens on the intra(especially the first intra frame of a new GOP) frames or set max_frame_size with a very small number. example cmdline: ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -f rawvideo \ -v verbose -s:v 352x288 -i ./input.yuv -vf format=nv12,hwupload \ -c:v h264_vaapi -profile:v main -g 30 -rc_mode VBR -b:v 500k \ -bf 3 -max_frame_size 40000 -vframes 100 -y ./max_frame_size.h264 Max frame size was enabled since VA-API version (0, 33, 0), but query is available since (1, 5, 0). It will be passed as a parameter in picParam and should be set for each frame. Signed-off-by: Linjie Fu <linjie.fu@intel.com> Signed-off-by: Fei Wang <fei.w.wang@intel.com>
Diffstat (limited to 'libavcodec/vaapi_encode.c')
-rw-r--r--libavcodec/vaapi_encode.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index 0e2f5ed447..284ce29888 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -365,6 +365,17 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
goto fail;
}
+#if VA_CHECK_VERSION(1, 5, 0)
+ if (ctx->max_frame_size) {
+ err = vaapi_encode_make_misc_param_buffer(avctx, pic,
+ VAEncMiscParameterTypeMaxFrameSize,
+ &ctx->mfs_params,
+ sizeof(ctx->mfs_params));
+ if (err < 0)
+ goto fail;
+ }
+#endif
+
if (pic->type == PICTURE_TYPE_IDR) {
if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
ctx->codec->write_sequence_header) {
@@ -1869,6 +1880,63 @@ rc_mode_found:
return 0;
}
+static av_cold int vaapi_encode_init_max_frame_size(AVCodecContext *avctx)
+{
+#if VA_CHECK_VERSION(1, 5, 0)
+ VAAPIEncodeContext *ctx = avctx->priv_data;
+ VAConfigAttrib attr = { VAConfigAttribMaxFrameSize };
+ VAStatus vas;
+
+ if (ctx->va_rc_mode == VA_RC_CQP) {
+ ctx->max_frame_size = 0;
+ av_log(avctx, AV_LOG_ERROR, "Max frame size is invalid in CQP rate "
+ "control mode.\n");
+ return AVERROR(EINVAL);
+ }
+
+ vas = vaGetConfigAttributes(ctx->hwctx->display,
+ ctx->va_profile,
+ ctx->va_entrypoint,
+ &attr, 1);
+ if (vas != VA_STATUS_SUCCESS) {
+ ctx->max_frame_size = 0;
+ av_log(avctx, AV_LOG_ERROR, "Failed to query max frame size "
+ "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
+ return AVERROR_EXTERNAL;
+ }
+
+ if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
+ ctx->max_frame_size = 0;
+ av_log(avctx, AV_LOG_ERROR, "Max frame size attribute "
+ "is not supported.\n");
+ return AVERROR(EINVAL);
+ } else {
+ VAConfigAttribValMaxFrameSize attr_mfs;
+ attr_mfs.value = attr.value;
+ // Prefer to use VAEncMiscParameterTypeMaxFrameSize for max frame size.
+ if (!attr_mfs.bits.max_frame_size && attr_mfs.bits.multiple_pass) {
+ ctx->max_frame_size = 0;
+ av_log(avctx, AV_LOG_ERROR, "Driver only supports multiple pass "
+ "max frame size which has not been implemented in FFmpeg.\n");
+ return AVERROR(EINVAL);
+ }
+
+ ctx->mfs_params = (VAEncMiscParameterBufferMaxFrameSize){
+ .max_frame_size = ctx->max_frame_size * 8,
+ };
+
+ av_log(avctx, AV_LOG_VERBOSE, "Set max frame size: %d bytes.\n",
+ ctx->max_frame_size);
+ }
+#else
+ av_log(avctx, AV_LOG_ERROR, "The max frame size option is not supported with "
+ "this VAAPI version.\n");
+ return AVERROR(EINVAL);
+#endif
+
+ return 0;
+}
+
static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx)
{
VAAPIEncodeContext *ctx = avctx->priv_data;
@@ -2548,6 +2616,12 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
goto fail;
}
+ if (ctx->max_frame_size) {
+ err = vaapi_encode_init_max_frame_size(avctx);
+ if (err < 0)
+ goto fail;
+ }
+
vas = vaCreateConfig(ctx->hwctx->display,
ctx->va_profile, ctx->va_entrypoint,
ctx->config_attributes, ctx->nb_config_attributes,