|
|
@ -104,7 +104,15 @@ typedef struct VAAPIEncodeH264Context { |
|
|
|
int64_t idr_pic_count; |
|
|
|
int64_t idr_pic_count; |
|
|
|
int64_t last_idr_frame; |
|
|
|
int64_t last_idr_frame; |
|
|
|
|
|
|
|
|
|
|
|
// RefPicList management.
|
|
|
|
// Rate control configuration.
|
|
|
|
|
|
|
|
struct { |
|
|
|
|
|
|
|
VAEncMiscParameterBuffer misc; |
|
|
|
|
|
|
|
VAEncMiscParameterRateControl rc; |
|
|
|
|
|
|
|
} rc_params; |
|
|
|
|
|
|
|
struct { |
|
|
|
|
|
|
|
VAEncMiscParameterBuffer misc; |
|
|
|
|
|
|
|
VAEncMiscParameterHRD hrd; |
|
|
|
|
|
|
|
} hrd_params; |
|
|
|
} VAAPIEncodeH264Context; |
|
|
|
} VAAPIEncodeH264Context; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -506,6 +514,19 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx) |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
vseq->frame_cropping_flag = 0; |
|
|
|
vseq->frame_cropping_flag = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vseq->bits_per_second = avctx->bit_rate; |
|
|
|
|
|
|
|
if (avctx->framerate.num > 0 && avctx->framerate.den > 0) { |
|
|
|
|
|
|
|
vseq->num_units_in_tick = avctx->framerate.num; |
|
|
|
|
|
|
|
vseq->time_scale = 2 * avctx->framerate.den; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
vseq->num_units_in_tick = avctx->time_base.num; |
|
|
|
|
|
|
|
vseq->time_scale = 2 * avctx->time_base.den; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vseq->intra_period = ctx->p_per_i * (ctx->b_per_p + 1); |
|
|
|
|
|
|
|
vseq->intra_idr_period = vseq->intra_period; |
|
|
|
|
|
|
|
vseq->ip_period = ctx->b_per_p + 1; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
@ -690,13 +711,84 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx, |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static av_cold int vaapi_encode_h264_init_constant_bitrate(AVCodecContext *avctx) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
VAAPIEncodeContext *ctx = avctx->priv_data; |
|
|
|
|
|
|
|
VAAPIEncodeH264Context *priv = ctx->priv_data; |
|
|
|
|
|
|
|
int hrd_buffer_size; |
|
|
|
|
|
|
|
int hrd_initial_buffer_fullness; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (avctx->rc_buffer_size) |
|
|
|
|
|
|
|
hrd_buffer_size = avctx->rc_buffer_size; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
hrd_buffer_size = avctx->bit_rate; |
|
|
|
|
|
|
|
if (avctx->rc_initial_buffer_occupancy) |
|
|
|
|
|
|
|
hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy; |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
priv->rc_params.misc.type = VAEncMiscParameterTypeRateControl; |
|
|
|
|
|
|
|
priv->rc_params.rc = (VAEncMiscParameterRateControl) { |
|
|
|
|
|
|
|
.bits_per_second = avctx->bit_rate, |
|
|
|
|
|
|
|
.target_percentage = 66, |
|
|
|
|
|
|
|
.window_size = 1000, |
|
|
|
|
|
|
|
.initial_qp = (avctx->qmax >= 0 ? avctx->qmax : 40), |
|
|
|
|
|
|
|
.min_qp = (avctx->qmin >= 0 ? avctx->qmin : 18), |
|
|
|
|
|
|
|
.basic_unit_size = 0, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
ctx->global_params[ctx->nb_global_params] = |
|
|
|
|
|
|
|
&priv->rc_params.misc; |
|
|
|
|
|
|
|
ctx->global_params_size[ctx->nb_global_params++] = |
|
|
|
|
|
|
|
sizeof(priv->rc_params); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
priv->hrd_params.misc.type = VAEncMiscParameterTypeHRD; |
|
|
|
|
|
|
|
priv->hrd_params.hrd = (VAEncMiscParameterHRD) { |
|
|
|
|
|
|
|
.initial_buffer_fullness = hrd_initial_buffer_fullness, |
|
|
|
|
|
|
|
.buffer_size = hrd_buffer_size, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
ctx->global_params[ctx->nb_global_params] = |
|
|
|
|
|
|
|
&priv->hrd_params.misc; |
|
|
|
|
|
|
|
ctx->global_params_size[ctx->nb_global_params++] = |
|
|
|
|
|
|
|
sizeof(priv->hrd_params); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// These still need to be set for pic_init_qp/slice_qp_delta.
|
|
|
|
|
|
|
|
priv->fixed_qp_idr = 26; |
|
|
|
|
|
|
|
priv->fixed_qp_p = 26; |
|
|
|
|
|
|
|
priv->fixed_qp_b = 26; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %d bps.\n", |
|
|
|
|
|
|
|
avctx->bit_rate); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static av_cold int vaapi_encode_h264_init_fixed_qp(AVCodecContext *avctx) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
VAAPIEncodeContext *ctx = avctx->priv_data; |
|
|
|
|
|
|
|
VAAPIEncodeH264Context *priv = ctx->priv_data; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
priv->fixed_qp_p = avctx->global_quality; |
|
|
|
|
|
|
|
if (avctx->i_quant_factor > 0.0) |
|
|
|
|
|
|
|
priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor + |
|
|
|
|
|
|
|
avctx->i_quant_offset) + 0.5); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
priv->fixed_qp_idr = priv->fixed_qp_p; |
|
|
|
|
|
|
|
if (avctx->b_quant_factor > 0.0) |
|
|
|
|
|
|
|
priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor + |
|
|
|
|
|
|
|
avctx->b_quant_offset) + 0.5); |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
priv->fixed_qp_b = priv->fixed_qp_p; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = " |
|
|
|
|
|
|
|
"%d / %d / %d for IDR / P / B frames.\n", |
|
|
|
|
|
|
|
priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx) |
|
|
|
static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx) |
|
|
|
{ |
|
|
|
{ |
|
|
|
static const VAConfigAttrib default_config_attributes[] = { |
|
|
|
static const VAConfigAttrib default_config_attributes[] = { |
|
|
|
{ .type = VAConfigAttribRTFormat, |
|
|
|
{ .type = VAConfigAttribRTFormat, |
|
|
|
.value = VA_RT_FORMAT_YUV420 }, |
|
|
|
.value = VA_RT_FORMAT_YUV420 }, |
|
|
|
{ .type = VAConfigAttribRateControl, |
|
|
|
|
|
|
|
.value = VA_RC_CQP }, |
|
|
|
|
|
|
|
{ .type = VAConfigAttribEncPackedHeaders, |
|
|
|
{ .type = VAConfigAttribEncPackedHeaders, |
|
|
|
.value = (VA_ENC_PACKED_HEADER_SEQUENCE | |
|
|
|
.value = (VA_ENC_PACKED_HEADER_SEQUENCE | |
|
|
|
VA_ENC_PACKED_HEADER_SLICE) }, |
|
|
|
VA_ENC_PACKED_HEADER_SLICE) }, |
|
|
@ -704,7 +796,7 @@ static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx) |
|
|
|
|
|
|
|
|
|
|
|
VAAPIEncodeContext *ctx = avctx->priv_data; |
|
|
|
VAAPIEncodeContext *ctx = avctx->priv_data; |
|
|
|
VAAPIEncodeH264Context *priv = ctx->priv_data; |
|
|
|
VAAPIEncodeH264Context *priv = ctx->priv_data; |
|
|
|
int i; |
|
|
|
int i, err; |
|
|
|
|
|
|
|
|
|
|
|
switch (avctx->profile) { |
|
|
|
switch (avctx->profile) { |
|
|
|
case FF_PROFILE_H264_CONSTRAINED_BASELINE: |
|
|
|
case FF_PROFILE_H264_CONSTRAINED_BASELINE: |
|
|
@ -745,8 +837,6 @@ static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx) |
|
|
|
} |
|
|
|
} |
|
|
|
ctx->va_entrypoint = VAEntrypointEncSlice; |
|
|
|
ctx->va_entrypoint = VAEntrypointEncSlice; |
|
|
|
|
|
|
|
|
|
|
|
ctx->va_rc_mode = VA_RC_CQP; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ctx->input_width = avctx->width; |
|
|
|
ctx->input_width = avctx->width; |
|
|
|
ctx->input_height = avctx->height; |
|
|
|
ctx->input_height = avctx->height; |
|
|
|
ctx->aligned_width = FFALIGN(ctx->input_width, 16); |
|
|
|
ctx->aligned_width = FFALIGN(ctx->input_width, 16); |
|
|
@ -754,30 +844,25 @@ static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx) |
|
|
|
priv->mb_width = ctx->aligned_width / 16; |
|
|
|
priv->mb_width = ctx->aligned_width / 16; |
|
|
|
priv->mb_height = ctx->aligned_height / 16; |
|
|
|
priv->mb_height = ctx->aligned_height / 16; |
|
|
|
|
|
|
|
|
|
|
|
if (avctx->bit_rate > 0) { |
|
|
|
|
|
|
|
av_log(avctx, AV_LOG_ERROR, "Constant bitrate encoding is not " |
|
|
|
|
|
|
|
"supported!\n"); |
|
|
|
|
|
|
|
return AVERROR_PATCHWELCOME; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) { |
|
|
|
for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) { |
|
|
|
ctx->config_attributes[ctx->nb_config_attributes++] = |
|
|
|
ctx->config_attributes[ctx->nb_config_attributes++] = |
|
|
|
default_config_attributes[i]; |
|
|
|
default_config_attributes[i]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
priv->fixed_qp_p = avctx->global_quality; |
|
|
|
if (avctx->bit_rate > 0) { |
|
|
|
if (avctx->i_quant_factor > 0.0) |
|
|
|
ctx->va_rc_mode = VA_RC_CBR; |
|
|
|
priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor + |
|
|
|
err = vaapi_encode_h264_init_constant_bitrate(avctx); |
|
|
|
avctx->i_quant_offset) + 0.5); |
|
|
|
} else { |
|
|
|
else |
|
|
|
ctx->va_rc_mode = VA_RC_CQP; |
|
|
|
priv->fixed_qp_idr = priv->fixed_qp_p; |
|
|
|
err = vaapi_encode_h264_init_fixed_qp(avctx); |
|
|
|
if (avctx->b_quant_factor > 0.0) |
|
|
|
} |
|
|
|
priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor + |
|
|
|
if (err < 0) |
|
|
|
avctx->b_quant_offset) + 0.5); |
|
|
|
return err; |
|
|
|
else |
|
|
|
|
|
|
|
priv->fixed_qp_b = priv->fixed_qp_p; |
|
|
|
ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) { |
|
|
|
av_log(avctx, AV_LOG_DEBUG, "QP = %d / %d / %d for IDR / P / B frames.\n", |
|
|
|
.type = VAConfigAttribRateControl, |
|
|
|
priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b); |
|
|
|
.value = ctx->va_rc_mode, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
ctx->nb_recon_frames = 20; |
|
|
|
ctx->nb_recon_frames = 20; |
|
|
|
|
|
|
|
|
|
|
|