Skip to content

Commit

Permalink
lavc/vaapi_encode_h265: add private b_strategy option for hevc_vaapi
Browse files Browse the repository at this point in the history
Allow user to choose between I/P/B frames:

- normal
    Ordinary IB..BPB..B GOP structure.
- low delay B-frames:
    IB..B GOP structure, P frames replaced by B frames, allows forward-predict
    only for all B frames, L0 == L1, required by VDENC(low_power),
    optional for VMEPAK.
- reference B-frames:
    Convert P-frames to low delay B-frames, normal B frames still have
    2 different ref_lists and allow bi-prediction.

Low delay B:
<http://what-when-how.com/Tutorial/topic-397pct9eq3/High-Efficiency-Video-Coding-HEVC-288.html>

There is an on-going work in libva and media-driver to add querys
support for low delay b, would add it once it's ready:
intel/libva#220
intel/libva#364
intel/media-driver#721

Rebased a bit for this internal branch.

Signed-off-by: Linjie Fu <linjie.fu@intel.com>
  • Loading branch information
fulinjie authored and feiwan1 committed Mar 21, 2022
1 parent 5556762 commit d6f20f0
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 6 deletions.
16 changes: 16 additions & 0 deletions doc/encoders.texi
Expand Up @@ -3693,6 +3693,22 @@ Some combination of the following values:
Include HDR metadata if the input frames have it
(@emph{mastering_display_colour_volume} and @emph{content_light_level}
messages).

@item b_strategy
Allow user to choose between I/P/B frames and specify the type of B-frames.
@table @samp
@item normal
Normal IBBPBB strategy.

@item low_delay_b
Convert P-frames to B-frames, only forward-predict is allowed for all B frames,
ref_list0 equals to ref_list1, required by VDENC(low_power).

@item ref_b
Convert P-frames to low delay B-frames as references, while normal B frames
still have 2 different ref_lists and allow bi-prediction.
@end table

@end table

@item tiles
Expand Down
21 changes: 16 additions & 5 deletions libavcodec/vaapi_encode.c
Expand Up @@ -1959,15 +1959,26 @@ static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx)
"reference frames.\n");
return AVERROR(EINVAL);
} else if (!(ctx->codec->flags & FLAG_B_PICTURES) ||
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);
ref_l1 < 1 || avctx->max_b_frames < 1 ||
ctx->b_frame_strategy == 1) {
if (ctx->b_frame_strategy == 1)
av_log(avctx, AV_LOG_VERBOSE, "Using intra and low delay "
"B-frames (supported references: %d / %d).\n",
ref_l0, ref_l1);
else
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;
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);
if (ctx->b_frame_strategy == 2)
av_log(avctx, AV_LOG_VERBOSE, "Using intra, reference B- and "
"B-frames (supported references: %d / %d).\n",
ref_l0, ref_l1);
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;
Expand Down
1 change: 1 addition & 0 deletions libavcodec/vaapi_encode.h
Expand Up @@ -341,6 +341,7 @@ typedef struct VAAPIEncodeContext {
int idr_counter;
int gop_counter;
int end_of_stream;
int b_frame_strategy;
uint8_t *delta_qp;

// Whether the driver supports ROI at all.
Expand Down
29 changes: 28 additions & 1 deletion libavcodec/vaapi_encode_h265.c
Expand Up @@ -62,6 +62,7 @@ typedef struct VAAPIEncodeH265Context {
int tier;
int level;
int sei;
int b_frame_strategy;

// Derived settings.
int fixed_qp_idr;
Expand Down Expand Up @@ -914,7 +915,7 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,

sh->slice_type = hpic->slice_type;
// driver requires low delay B frame in low power mode
if (sh->slice_type == HEVC_SLICE_P && ctx->low_power)
if (sh->slice_type == HEVC_SLICE_P && priv->b_frame_strategy)
sh->slice_type = HEVC_SLICE_B;

sh->slice_pic_order_cnt_lsb = hpic->pic_order_cnt &
Expand Down Expand Up @@ -1075,6 +1076,9 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
av_assert0(pic->type == PICTURE_TYPE_P ||
pic->type == PICTURE_TYPE_B);
vslice->ref_pic_list0[0] = vpic->reference_frames[0];
if (priv->b_frame_strategy && pic->type == PICTURE_TYPE_P)
// Reference for low delay B-frame, L0 == L1
vslice->ref_pic_list1[0] = vpic->reference_frames[0];
}
if (pic->nb_refs >= 2) {
// Forward reference for B-frame.
Expand Down Expand Up @@ -1221,6 +1225,21 @@ static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx)
if (priv->qp > 0)
ctx->explicit_qp = priv->qp;

// Low delay B-frames is required for low power encoding.
if (ctx->low_power && priv->b_frame_strategy != 1) {
priv->b_frame_strategy = 1;
av_log(avctx, AV_LOG_WARNING, "Low delay B-frames required "
"for low power encoding.\n");
}

if (priv->b_frame_strategy) {
ctx->b_frame_strategy = priv->b_frame_strategy;
if (ctx->b_frame_strategy == 1)
av_log(avctx, AV_LOG_VERBOSE, "Low delay B-frames enabled.\n");
else
av_log(avctx, AV_LOG_VERBOSE, "Reference B-frames enabled.\n");
}

return ff_vaapi_encode_init(avctx);
}

Expand Down Expand Up @@ -1296,6 +1315,14 @@ static const AVOption vaapi_encode_h265_options[] = {
0, AV_OPT_TYPE_CONST,
{ .i64 = SEI_MASTERING_DISPLAY | SEI_CONTENT_LIGHT_LEVEL },
INT_MIN, INT_MAX, FLAGS, "sei" },
{ "b_strategy", "Strategy to choose between I/P/B-frames",
OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, FLAGS, "b_strategy" },
{ "normal", "Normal IB..BPB..B strategy",
0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS, "b_strategy" },
{ "low_delay_b", "Use low delay B-frames with forward-prediction only",
0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "b_strategy" },
{ "ref_b", "Only convert P-frames to low delay B-frames as references",
0, AV_OPT_TYPE_CONST, { .i64 = 2 }, INT_MIN, INT_MAX, FLAGS, "b_strategy" },

{ "tiles", "Tile columns x rows",
OFFSET(common.tile_cols), AV_OPT_TYPE_IMAGE_SIZE,
Expand Down

0 comments on commit d6f20f0

Please sign in to comment.