[FFmpeg-devel] [PATCH v2 18/36] vaapi_encode: Clean up the GOP structure configuration
Xiang, Haihao
haihao.xiang at intel.com
Thu Jun 14 09:48:57 EEST 2018
On Fri, 2018-06-08 at 00:43 +0100, Mark Thompson wrote:
> Choose what types of reference frames will be used based on what types
> are available, and make the intra-only mode explicit (GOP size one,
> which must be used for MJPEG).
> ---
> libavcodec/vaapi_encode.c | 83 +++++++++++++++++++++++++++-------------
> -
> libavcodec/vaapi_encode.h | 1 +
> libavcodec/vaapi_encode_h264.c | 4 +-
> libavcodec/vaapi_encode_h265.c | 4 +-
> libavcodec/vaapi_encode_mjpeg.c | 1 +
> libavcodec/vaapi_encode_mpeg2.c | 2 +-
> libavcodec/vaapi_encode_vp8.c | 7 +---
> libavcodec/vaapi_encode_vp9.c | 7 ++--
> 8 files changed, 68 insertions(+), 41 deletions(-)
>
> diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
> index 0e806a29e3..af9224c98f 100644
> --- a/libavcodec/vaapi_encode.c
> +++ b/libavcodec/vaapi_encode.c
> @@ -680,7 +680,7 @@ static int vaapi_encode_get_next(AVCodecContext *avctx,
> return AVERROR(ENOMEM);
>
> if (ctx->input_order == 0 || ctx->force_idr ||
> - ctx->gop_counter >= avctx->gop_size) {
> + ctx->gop_counter >= ctx->gop_size) {
> pic->type = PICTURE_TYPE_IDR;
> ctx->force_idr = 0;
> ctx->gop_counter = 1;
> @@ -703,7 +703,7 @@ static int vaapi_encode_get_next(AVCodecContext *avctx,
> // encode-after it, but not exceeding the GOP size.
>
> for (i = 0; i < ctx->b_per_p &&
> - ctx->gop_counter < avctx->gop_size; i++) {
> + ctx->gop_counter < ctx->gop_size; i++) {
> pic = vaapi_encode_alloc(avctx);
> if (!pic)
> goto fail;
> @@ -1217,7 +1217,6 @@ static av_cold int
> vaapi_encode_config_attributes(AVCodecContext *avctx)
> int i;
>
> VAConfigAttrib attr[] = {
> - { VAConfigAttribEncMaxRefFrames },
> { VAConfigAttribEncPackedHeaders },
> };
>
> @@ -1240,24 +1239,6 @@ static av_cold int
> vaapi_encode_config_attributes(AVCodecContext *avctx)
> continue;
> }
> switch (attr[i].type) {
> - case VAConfigAttribEncMaxRefFrames:
> - {
> - unsigned int ref_l0 = attr[i].value & 0xffff;
> - unsigned int ref_l1 = (attr[i].value >> 16) & 0xffff;
> -
> - if (avctx->gop_size > 1 && ref_l0 < 1) {
> - av_log(avctx, AV_LOG_ERROR, "P frames are not "
> - "supported (%#x).\n", attr[i].value);
> - return AVERROR(EINVAL);
> - }
> - if (avctx->max_b_frames > 0 && ref_l1 < 1) {
> - av_log(avctx, AV_LOG_WARNING, "B frames are not "
> - "supported (%#x) by the underlying driver.\n",
> - attr[i].value);
> - avctx->max_b_frames = 0;
> - }
> - }
> - break;
> case VAConfigAttribEncPackedHeaders:
> if (ctx->va_packed_headers & ~attr[i].value) {
> // This isn't fatal, but packed headers are always
> @@ -1465,6 +1446,54 @@ static av_cold int
> vaapi_encode_init_rate_control(AVCodecContext *avctx)
> return 0;
> }
>
> +static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx)
> +{
> + VAAPIEncodeContext *ctx = avctx->priv_data;
> + VAStatus vas;
> + VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames };
> + uint32_t ref_l0, ref_l1;
> +
> + vas = vaGetConfigAttributes(ctx->hwctx->display,
> + ctx->va_profile,
> + ctx->va_entrypoint,
> + &attr, 1);
> + if (vas != VA_STATUS_SUCCESS) {
> + av_log(avctx, AV_LOG_ERROR, "Failed to query reference frames "
> + "attribute: %d (%s).\n", vas, vaErrorStr(vas));
> + return AVERROR_EXTERNAL;
> + }
> +
> + if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
> + ref_l0 = ref_l1 = 0;
> + } else {
> + ref_l0 = attr.value & 0xffff;
> + ref_l1 = attr.value >> 16 & 0xffff;
> + }
> +
> + if (avctx->gop_size <= 1) {
> + av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n");
> + ctx->gop_size = 1;
> + } else if (ref_l0 < 1) {
> + av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
> + "reference frames.\n");
> + return AVERROR(EINVAL);
> + } else if (ref_l1 < 1 || avctx->max_b_frames < 1) {
> + av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames "
> + "(supported references: %d / %d).\n", ref_l0, ref_l1);
> + ctx->gop_size = avctx->gop_size;
> + ctx->p_per_i = INT_MAX;
How about removing p_per_i? I see p_per_i is used only in the following 'else
if' statement and I don't think ctx->p_counter can be INT_MAX in reality.
} else if (ctx->p_counter >= ctx->p_per_i) {...}
> + ctx->b_per_p = 0;
> + } else {
> + av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames "
> + "(supported references: %d / %d).\n", ref_l0, ref_l1);
> + ctx->gop_size = avctx->gop_size;
> + ctx->p_per_i = INT_MAX;
> + ctx->b_per_p = avctx->max_b_frames;
> + }
> +
> + return 0;
> +}
> +
> static av_cold int vaapi_encode_init_quality(AVCodecContext *avctx)
> {
> #if VA_CHECK_VERSION(0, 36, 0)
> @@ -1636,7 +1665,7 @@ static av_cold int
> vaapi_encode_create_recon_frames(AVCodecContext *avctx)
> ctx->recon_frames->height = ctx->surface_height;
> // At most three IDR/I/P frames and two runs of B frames can be in
> // flight at any one time.
> - ctx->recon_frames->initial_pool_size = 3 + 2 * avctx->max_b_frames;
> + ctx->recon_frames->initial_pool_size = 3 + 2 * ctx->b_per_p;
>
> err = av_hwframe_ctx_init(ctx->recon_frames_ref);
> if (err < 0) {
> @@ -1691,6 +1720,10 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
> if (err < 0)
> goto fail;
>
> + err = vaapi_encode_init_gop_structure(avctx);
> + if (err < 0)
> + goto fail;
> +
> err = vaapi_encode_config_attributes(avctx);
> if (err < 0)
> goto fail;
> @@ -1745,14 +1778,10 @@ av_cold int ff_vaapi_encode_init(AVCodecContext
> *avctx)
> }
>
> ctx->input_order = 0;
> - ctx->output_delay = avctx->max_b_frames;
> + ctx->output_delay = ctx->b_per_p;
> ctx->decode_delay = 1;
> ctx->output_order = - ctx->output_delay - 1;
>
> - // Currently we never generate I frames, only IDR.
> - ctx->p_per_i = INT_MAX;
> - ctx->b_per_p = avctx->max_b_frames;
> -
> if (ctx->codec->sequence_params_size > 0) {
> ctx->codec_sequence_params =
> av_mallocz(ctx->codec->sequence_params_size);
> diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h
> index 6fac4781c3..bbec721bca 100644
> --- a/libavcodec/vaapi_encode.h
> +++ b/libavcodec/vaapi_encode.h
> @@ -224,6 +224,7 @@ typedef struct VAAPIEncodeContext {
> int64_t ts_ring[MAX_REORDER_DELAY * 3];
>
> // Frame type decision.
> + int gop_size;
> int p_per_i;
> int b_per_p;
> int force_idr;
> diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
> index 87c0d9acf3..717be024ca 100644
> --- a/libavcodec/vaapi_encode_h264.c
> +++ b/libavcodec/vaapi_encode_h264.c
> @@ -493,8 +493,8 @@ static int
> vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
> *vseq = (VAEncSequenceParameterBufferH264) {
> .seq_parameter_set_id = sps->seq_parameter_set_id,
> .level_idc = sps->level_idc,
> - .intra_period = avctx->gop_size,
> - .intra_idr_period = avctx->gop_size,
> + .intra_period = ctx->gop_size,
> + .intra_idr_period = ctx->gop_size,
> .ip_period = ctx->b_per_p + 1,
>
> .bits_per_second = ctx->va_bit_rate,
> diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
> index 13ddad79ae..b2d6b8d24d 100644
> --- a/libavcodec/vaapi_encode_h265.c
> +++ b/libavcodec/vaapi_encode_h265.c
> @@ -509,8 +509,8 @@ static int
> vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
> .general_level_idc = vps->profile_tier_level.general_level_idc,
> .general_tier_flag = vps->profile_tier_level.general_tier_flag,
>
> - .intra_period = avctx->gop_size,
> - .intra_idr_period = avctx->gop_size,
> + .intra_period = ctx->gop_size,
> + .intra_idr_period = ctx->gop_size,
> .ip_period = ctx->b_per_p + 1,
> .bits_per_second = ctx->va_bit_rate,
>
> diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c
> index 67ac2fba96..4982cd166f 100644
> --- a/libavcodec/vaapi_encode_mjpeg.c
> +++ b/libavcodec/vaapi_encode_mjpeg.c
> @@ -401,6 +401,7 @@ static av_cold int vaapi_encode_mjpeg_init(AVCodecContext
> *avctx)
> static const AVCodecDefault vaapi_encode_mjpeg_defaults[] = {
> { "global_quality", "80" },
> { "b", "0" },
> + { "g", "1" },
> { NULL },
> };
>
> diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c
> index db72516187..b6edca9158 100644
> --- a/libavcodec/vaapi_encode_mpeg2.c
> +++ b/libavcodec/vaapi_encode_mpeg2.c
> @@ -355,7 +355,7 @@ static int
> vaapi_encode_mpeg2_init_sequence_params(AVCodecContext *avctx)
>
>
> *vseq = (VAEncSequenceParameterBufferMPEG2) {
> - .intra_period = avctx->gop_size,
> + .intra_period = ctx->gop_size,
> .ip_period = ctx->b_per_p + 1,
>
> .picture_width = avctx->width,
> diff --git a/libavcodec/vaapi_encode_vp8.c b/libavcodec/vaapi_encode_vp8.c
> index db67136556..4512609a19 100644
> --- a/libavcodec/vaapi_encode_vp8.c
> +++ b/libavcodec/vaapi_encode_vp8.c
> @@ -66,7 +66,7 @@ static int
> vaapi_encode_vp8_init_sequence_params(AVCodecContext *avctx)
>
> if (!(ctx->va_rc_mode & VA_RC_CQP)) {
> vseq->bits_per_second = ctx->va_bit_rate;
> - vseq->intra_period = avctx->gop_size;
> + vseq->intra_period = ctx->gop_size;
> }
>
> return 0;
> @@ -198,11 +198,6 @@ static av_cold int vaapi_encode_vp8_init(AVCodecContext
> *avctx)
> {
> VAAPIEncodeContext *ctx = avctx->priv_data;
>
> - if (avctx->max_b_frames > 0) {
> - av_log(avctx, AV_LOG_ERROR, "B-frames are not supported.\n");
> - return AVERROR_PATCHWELCOME;
> - }
> -
> ctx->codec = &vaapi_encode_type_vp8;
>
> // Packed headers are not currently supported.
> diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c
> index 2b0658ec1f..d4069ec850 100644
> --- a/libavcodec/vaapi_encode_vp9.c
> +++ b/libavcodec/vaapi_encode_vp9.c
> @@ -72,7 +72,7 @@ static int
> vaapi_encode_vp9_init_sequence_params(AVCodecContext *avctx)
>
> if (!(ctx->va_rc_mode & VA_RC_CQP)) {
> vseq->bits_per_second = ctx->va_bit_rate;
> - vseq->intra_period = avctx->gop_size;
> + vseq->intra_period = ctx->gop_size;
> }
>
> vpic->frame_width_src = avctx->width;
> @@ -86,6 +86,7 @@ static int
> vaapi_encode_vp9_init_sequence_params(AVCodecContext *avctx)
> static int vaapi_encode_vp9_init_picture_params(AVCodecContext *avctx,
> VAAPIEncodePicture *pic)
> {
> + VAAPIEncodeContext *ctx = avctx->priv_data;
> VAAPIEncodeVP9Context *priv = avctx->priv_data;
> VAEncPictureParameterBufferVP9 *vpic = pic->codec_picture_params;
> int i;
> @@ -102,7 +103,7 @@ static int
> vaapi_encode_vp9_init_picture_params(AVCodecContext *avctx,
> break;
> case PICTURE_TYPE_P:
> av_assert0(pic->nb_refs == 1);
> - if (avctx->max_b_frames > 0) {
> + if (ctx->b_per_p > 0) {
> if (priv->last_ref_dir) {
> vpic->ref_flags.bits.ref_frame_ctrl_l0 = 2;
> vpic->ref_flags.bits.ref_gf_idx = 1;
> @@ -174,7 +175,7 @@ static int
> vaapi_encode_vp9_init_picture_params(AVCodecContext *avctx,
> vpic->filter_level = priv->loop_filter_level;
> vpic->sharpness_level = priv->loop_filter_sharpness;
>
> - if (avctx->max_b_frames > 0 && pic->type == PICTURE_TYPE_P)
> + if (ctx->b_per_p > 0 && pic->type == PICTURE_TYPE_P)
> priv->last_ref_dir = !priv->last_ref_dir;
>
> return 0;
More information about the ffmpeg-devel
mailing list