On Tue, Apr 23, 2019 at 11:29 AM Linjie Fu <[email protected]> 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 <[email protected]> > --- > 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 > [email protected] > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > [email protected] with subject "unsubscribe". -- ======================================= Jun zhao/赵军 +++++++++++++++++++++++++++++++++++++++ _______________________________________________ ffmpeg-devel mailing list [email protected] https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email [email protected] with subject "unsubscribe".
