[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