You've already forked FFmpeg
mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-08-15 14:13:16 +02:00
vaapi_h265: Add constant-bitrate encode support
Signed-off-by: Anton Khirnov <anton@khirnov.net>
This commit is contained in:
committed by
Anton Khirnov
parent
fcf536b130
commit
f70e462793
@@ -182,6 +182,16 @@ typedef struct VAAPIEncodeH265Context {
|
|||||||
int fixed_qp_b;
|
int fixed_qp_b;
|
||||||
|
|
||||||
int64_t last_idr_frame;
|
int64_t last_idr_frame;
|
||||||
|
|
||||||
|
// Rate control configuration.
|
||||||
|
struct {
|
||||||
|
VAEncMiscParameterBuffer misc;
|
||||||
|
VAEncMiscParameterRateControl rc;
|
||||||
|
} rc_params;
|
||||||
|
struct {
|
||||||
|
VAEncMiscParameterBuffer misc;
|
||||||
|
VAEncMiscParameterHRD hrd;
|
||||||
|
} hrd_params;
|
||||||
} VAAPIEncodeH265Context;
|
} VAAPIEncodeH265Context;
|
||||||
|
|
||||||
|
|
||||||
@@ -806,6 +816,19 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
|
|||||||
vseq->max_transform_hierarchy_depth_intra = 3;
|
vseq->max_transform_hierarchy_depth_intra = 3;
|
||||||
|
|
||||||
vseq->vui_parameters_present_flag = 0;
|
vseq->vui_parameters_present_flag = 0;
|
||||||
|
|
||||||
|
vseq->bits_per_second = avctx->bit_rate;
|
||||||
|
if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
|
||||||
|
vseq->vui_num_units_in_tick = avctx->framerate.num;
|
||||||
|
vseq->vui_time_scale = avctx->framerate.den;
|
||||||
|
} else {
|
||||||
|
vseq->vui_num_units_in_tick = avctx->time_base.num;
|
||||||
|
vseq->vui_time_scale = 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -841,8 +864,7 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
|
|||||||
|
|
||||||
vpic->pic_fields.bits.screen_content_flag = 0;
|
vpic->pic_fields.bits.screen_content_flag = 0;
|
||||||
vpic->pic_fields.bits.enable_gpu_weighted_prediction = 0;
|
vpic->pic_fields.bits.enable_gpu_weighted_prediction = 0;
|
||||||
|
vpic->pic_fields.bits.cu_qp_delta_enabled_flag = 1;
|
||||||
//vpic->pic_fields.bits.cu_qp_delta_enabled_flag = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -1125,6 +1147,79 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static av_cold int vaapi_encode_h265_init_constant_bitrate(AVCodecContext *avctx)
|
||||||
|
{
|
||||||
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
||||||
|
VAAPIEncodeH265Context *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 : 20),
|
||||||
|
.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 = 30;
|
||||||
|
priv->fixed_qp_p = 30;
|
||||||
|
priv->fixed_qp_b = 30;
|
||||||
|
|
||||||
|
av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %d bps.\n",
|
||||||
|
avctx->bit_rate);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static av_cold int vaapi_encode_h265_init_fixed_qp(AVCodecContext *avctx)
|
||||||
|
{
|
||||||
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
||||||
|
VAAPIEncodeH265Context *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_h265_init_internal(AVCodecContext *avctx)
|
static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx)
|
||||||
{
|
{
|
||||||
static const VAConfigAttrib default_config_attributes[] = {
|
static const VAConfigAttrib default_config_attributes[] = {
|
||||||
@@ -1133,13 +1228,11 @@ static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx)
|
|||||||
{ .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) },
|
||||||
{ .type = VAConfigAttribRateControl,
|
|
||||||
.value = VA_RC_CQP },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VAAPIEncodeContext *ctx = avctx->priv_data;
|
VAAPIEncodeContext *ctx = avctx->priv_data;
|
||||||
VAAPIEncodeH265Context *priv = ctx->priv_data;
|
VAAPIEncodeH265Context *priv = ctx->priv_data;
|
||||||
int i;
|
int i, err;
|
||||||
|
|
||||||
switch (avctx->profile) {
|
switch (avctx->profile) {
|
||||||
case FF_PROFILE_HEVC_MAIN:
|
case FF_PROFILE_HEVC_MAIN:
|
||||||
@@ -1174,26 +1267,19 @@ static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (avctx->bit_rate > 0) {
|
if (avctx->bit_rate > 0) {
|
||||||
av_log(avctx, AV_LOG_ERROR, "H.265 constant-bitrate encoding "
|
ctx->va_rc_mode = VA_RC_CBR;
|
||||||
"is not supported.\n");
|
err = vaapi_encode_h265_init_constant_bitrate(avctx);
|
||||||
return AVERROR_PATCHWELCOME;
|
} else {
|
||||||
|
ctx->va_rc_mode = VA_RC_CQP;
|
||||||
|
err = vaapi_encode_h265_init_fixed_qp(avctx);
|
||||||
}
|
}
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
ctx->va_rc_mode = VA_RC_CQP;
|
ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) {
|
||||||
|
.type = VAConfigAttribRateControl,
|
||||||
priv->fixed_qp_p = avctx->global_quality;
|
.value = ctx->va_rc_mode,
|
||||||
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, "QP = %d / %d / %d for IDR / P / B frames.\n",
|
|
||||||
priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
|
|
||||||
|
|
||||||
ctx->nb_recon_frames = 20;
|
ctx->nb_recon_frames = 20;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user