mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-01-24 13:56:33 +02:00
vaapi_encode: Clean up the GOP structure configuration
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).
This commit is contained in:
parent
8479f99c7d
commit
bf726c26fd
@ -671,7 +671,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;
|
||||
@ -694,7 +694,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();
|
||||
if (!pic)
|
||||
goto fail;
|
||||
@ -1213,7 +1213,6 @@ static av_cold int vaapi_encode_config_attributes(AVCodecContext *avctx)
|
||||
int i;
|
||||
|
||||
VAConfigAttrib attr[] = {
|
||||
{ VAConfigAttribEncMaxRefFrames },
|
||||
{ VAConfigAttribEncPackedHeaders },
|
||||
};
|
||||
|
||||
@ -1236,24 +1235,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
|
||||
@ -1469,6 +1450,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;
|
||||
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)
|
||||
@ -1640,7 +1669,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) {
|
||||
@ -1695,6 +1724,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;
|
||||
@ -1749,14 +1782,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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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 },
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user