[FFmpeg-devel] [PATCH] lavc/vaapi_encode_h264: add support for maxframesize
mypopy at gmail.com
mypopy at gmail.com
Tue Apr 23 08:41:34 EEST 2019
On Tue, Apr 23, 2019 at 11:29 AM Linjie Fu <linjie.fu at intel.com> wrote:
>
> Add support for max frame size:
> - max_frame_size (bytes) to indicate the allowed max frame size.
> - pass_num to indicate number of passes.
> - delta_qp to indicate adjust qp value.
>
> Currently only AVC encoder can support this settings in multiple pass case.
> If the frame size exceeds, the encoder will do more pak passes to adjust the
> QP value to control the frame size.
>
> Set Default num_passes to 4 (1~4), set delta_qp[4] = {1, 1, 1, 1}, use
> new_qp for encoder if frame size exceeds the limitation:
> new_qp = base_qp + delta_qp[0] + delta_qp[1] + ...
>
> 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 -bf 3 -max_frame_size 40000 \
> -pass_num 2 -delta_qp 2 -vframes 100 -y ./max_frame_size.h264
>
Some question list as follow:
1. Can I change delta_qp per pass, e,g, 4 pass 1, 2, 3, 4, use
delta_qp[4] like: 1, 2, 4, 8?
2. So let's think about the limiting case, if we setting
max_frame_size = 1 for 1080P, what's the action for this driver?
3. Maybe we can hide the pass_num and delta_qp, only export the
max_frame_size for this case? I don't think export the driver QP
adjustment detail logic to user space is good idea, user will
confused about to how to set/adjust pass_num/delta_qp per pass.
4. Missing docs
5. What's the relationship about other bit rate control like VBR or MBBRC ?
6. Only 264 encoder support this feature? What platform have you tested?
> Signed-off-by: Linjie Fu <linjie.fu at intel.com>
> ---
> libavcodec/vaapi_encode.c | 46 ++++++++++++++++++++++++++++++++++
> libavcodec/vaapi_encode.h | 11 ++++++++
> libavcodec/vaapi_encode_h264.c | 15 +++++++++++
> 3 files changed, 72 insertions(+)
>
> diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
> index 2dda451882..762c42ef13 100644
> --- a/libavcodec/vaapi_encode.c
> +++ b/libavcodec/vaapi_encode.c
> @@ -236,6 +236,14 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
> goto fail;
> }
>
> + if (ctx->max_frame_size) {
> + err = vaapi_encode_make_param_buffer(avctx, pic, VAEncMiscParameterBufferType,
> + (char*) &ctx->mfs_params.misc,
> + sizeof(ctx->mfs_params));
> + if (err < 0)
> + goto fail;
> + }
> +
> if (pic->type == PICTURE_TYPE_IDR) {
> if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
> ctx->codec->write_sequence_header) {
> @@ -1630,6 +1638,38 @@ rc_mode_found:
> return 0;
> }
>
> +static av_cold int vaapi_encode_init_max_frame_size(AVCodecContext *avctx)
> +{
> + VAAPIEncodeContext *ctx = avctx->priv_data;
> +
> + uint32_t max_frame_size = ctx->max_frame_size;
> + uint8_t num_passes = ctx->pass_num;
> + uint8_t *delta_qp = av_mallocz_array(num_passes, sizeof(uint8_t));
> + int err = 0;
> + int i = 0;
> +
> + if (!delta_qp) {
> + err = AVERROR(ENOMEM);
> + return err;
> + }
> + for (i = 0; i <num_passes; i++){
> + delta_qp[i] = ctx->delta_qp;
> + }
> +
> +
> + ctx->mfs_params.misc.type = VAEncMiscParameterTypeMultiPassFrameSize;
> + ctx->mfs_params.mfs.type = VAEncMiscParameterTypeMultiPassFrameSize;
> + ctx->mfs_params.mfs.max_frame_size = max_frame_size;
> + ctx->mfs_params.mfs.num_passes = num_passes;
> + ctx->mfs_params.mfs.delta_qp = delta_qp;
> +
> + av_log(avctx, AV_LOG_VERBOSE, "Max Frame Size: %d bytes, "
> + "num_passes: %d, delta_qp = %d.\n",
> + ctx->max_frame_size, num_passes, ctx->delta_qp);
> +
> + return 0;
> +}
> +
> static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx)
> {
> VAAPIEncodeContext *ctx = avctx->priv_data;
> @@ -2095,6 +2135,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,
> diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h
> index 44a8db566e..557476d226 100644
> --- a/libavcodec/vaapi_encode.h
> +++ b/libavcodec/vaapi_encode.h
> @@ -176,6 +176,13 @@ typedef struct VAAPIEncodeContext {
> // Desired B frame reference depth.
> int desired_b_depth;
>
> + // Max Frame Size
> + int max_frame_size;
> + // Number Of Passes
> + int pass_num;
> + // Delta_qp For Each Pass
> + int delta_qp;
> +
> // Explicitly set RC mode (otherwise attempt to pick from
> // available modes).
> int explicit_rc_mode;
> @@ -268,6 +275,10 @@ typedef struct VAAPIEncodeContext {
> } quality_params;
> #endif
>
> + struct {
> + VAEncMiscParameterBuffer misc;
> + VAEncMiscParameterBufferMultiPassFrameSize mfs;
> + } __attribute__((packed)) mfs_params;
> // Per-sequence parameter structure (VAEncSequenceParameterBuffer*).
> void *codec_sequence_params;
>
> diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
> index 4cf99d7c78..4d55dc2bac 100644
> --- a/libavcodec/vaapi_encode_h264.c
> +++ b/libavcodec/vaapi_encode_h264.c
> @@ -72,6 +72,9 @@ typedef struct VAAPIEncodeH264Context {
> int sei;
> int profile;
> int level;
> + int max_frame_size;
> + int pass_num;
> + int delta_qp;
>
> // Derived settings.
> int mb_width;
> @@ -1233,6 +1236,12 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
> if (priv->qp > 0)
> ctx->explicit_qp = priv->qp;
>
> + if (priv->max_frame_size > 0) {
> + ctx->max_frame_size = priv->max_frame_size;
> + ctx->pass_num = priv->pass_num;
> + ctx->delta_qp = priv->delta_qp;
> + }
> +
> return ff_vaapi_encode_init(avctx);
> }
>
> @@ -1266,6 +1275,12 @@ static const AVOption vaapi_encode_h264_options[] = {
>
> { "aud", "Include AUD",
> OFFSET(aud), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
> + { "max_frame_size", "Maximum frame size (in bytes)",
> + OFFSET(max_frame_size), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
> + { "pass_num", "number of passes, every pass can have different QP, currently can support up to 4 passes",
> + OFFSET(pass_num), AV_OPT_TYPE_INT, { .i64 = 4 }, 0, 4, FLAGS },
> + { "delta_qp", "delta QP for every pass",
> + OFFSET(delta_qp), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 51, FLAGS },
>
> { "sei", "Set SEI to include",
> OFFSET(sei), AV_OPT_TYPE_FLAGS,
> --
> 2.17.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".
--
=======================================
Jun zhao/赵军
+++++++++++++++++++++++++++++++++++++++
More information about the ffmpeg-devel
mailing list