mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
Merge commit '92fdea37477b5a2d1329e5ef0773e24473fa8f12'
These are all trivial to merge. * commit '92fdea37477b5a2d1329e5ef0773e24473fa8f12': vaapi_h265: Add -qp option, use it to replace use of -global_quality vaapi_h265: Add constant-bitrate encode support vaapi_h264: Add encode quality option (for quality-speed tradeoff) vaapi_h264: Add -qp option, use it to replace use of -global_quality vaapi_encode: Add support for codec-local options vaapi_h264: Add constant-bitrate encode support vaapi_encode: Refactor slightly to allow easier setting of global options Merged-by: Derek Buitenhuis <derek.buitenhuis@gmail.com>
This commit is contained in:
commit
8ed427f9f9
@ -202,6 +202,19 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
|
||||
|
||||
pic->nb_param_buffers = 0;
|
||||
|
||||
if (pic->encode_order == 0) {
|
||||
// Global parameter buffers are set on the first picture only.
|
||||
|
||||
for (i = 0; i < ctx->nb_global_params; i++) {
|
||||
err = vaapi_encode_make_param_buffer(avctx, pic,
|
||||
VAEncMiscParameterBufferType,
|
||||
(char*)ctx->global_params[i],
|
||||
ctx->global_params_size[i]);
|
||||
if (err < 0)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (pic->type == PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) {
|
||||
err = vaapi_encode_make_param_buffer(avctx, pic,
|
||||
VAEncSequenceParameterBufferType,
|
||||
@ -892,6 +905,7 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx,
|
||||
}
|
||||
|
||||
ctx->codec = type;
|
||||
ctx->codec_options = ctx->codec_options_data;
|
||||
|
||||
ctx->priv_data = av_mallocz(type->priv_data_size);
|
||||
if (!ctx->priv_data) {
|
||||
|
@ -32,6 +32,8 @@ struct VAAPIEncodeType;
|
||||
struct VAAPIEncodePicture;
|
||||
|
||||
enum {
|
||||
MAX_CONFIG_ATTRIBUTES = 4,
|
||||
MAX_GLOBAL_PARAMS = 4,
|
||||
MAX_PICTURE_REFERENCES = 2,
|
||||
MAX_PICTURE_SLICES = 1,
|
||||
MAX_PARAM_BUFFERS = 16,
|
||||
@ -128,9 +130,13 @@ typedef struct VAAPIEncodeContext {
|
||||
AVBufferRef *recon_frames_ref;
|
||||
AVHWFramesContext *recon_frames;
|
||||
|
||||
VAConfigAttrib *config_attributes;
|
||||
VAConfigAttrib config_attributes[MAX_CONFIG_ATTRIBUTES];
|
||||
int nb_config_attributes;
|
||||
|
||||
VAEncMiscParameterBuffer *global_params[MAX_GLOBAL_PARAMS];
|
||||
size_t global_params_size[MAX_GLOBAL_PARAMS];
|
||||
int nb_global_params;
|
||||
|
||||
// Per-sequence parameter structure (VAEncSequenceParameterBuffer*).
|
||||
void *codec_sequence_params;
|
||||
|
||||
@ -166,6 +172,11 @@ typedef struct VAAPIEncodeContext {
|
||||
int p_counter;
|
||||
int end_of_stream;
|
||||
|
||||
// Codec-local options are allocated to follow this structure in
|
||||
// memory (in the AVCodec definition, set priv_data_size to
|
||||
// sizeof(VAAPIEncodeContext) + sizeof(VAAPIEncodeFooOptions)).
|
||||
void *codec_options;
|
||||
char codec_options_data[0];
|
||||
} VAAPIEncodeContext;
|
||||
|
||||
|
||||
|
@ -104,9 +104,30 @@ typedef struct VAAPIEncodeH264Context {
|
||||
int64_t idr_pic_count;
|
||||
int64_t last_idr_frame;
|
||||
|
||||
// RefPicList management.
|
||||
// Rate control configuration.
|
||||
struct {
|
||||
VAEncMiscParameterBuffer misc;
|
||||
VAEncMiscParameterRateControl rc;
|
||||
} rc_params;
|
||||
struct {
|
||||
VAEncMiscParameterBuffer misc;
|
||||
VAEncMiscParameterHRD hrd;
|
||||
} hrd_params;
|
||||
|
||||
#if VA_CHECK_VERSION(0, 36, 0)
|
||||
// Speed-quality tradeoff setting.
|
||||
struct {
|
||||
VAEncMiscParameterBuffer misc;
|
||||
VAEncMiscParameterBufferQualityLevel quality;
|
||||
} quality_params;
|
||||
#endif
|
||||
} VAAPIEncodeH264Context;
|
||||
|
||||
typedef struct VAAPIEncodeH264Options {
|
||||
int qp;
|
||||
int quality;
|
||||
} VAAPIEncodeH264Options;
|
||||
|
||||
|
||||
#define vseq_var(name) vseq->name, name
|
||||
#define vseq_field(name) vseq->seq_fields.bits.name, name
|
||||
@ -506,6 +527,19 @@ static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
|
||||
} else {
|
||||
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,20 +724,94 @@ static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static VAConfigAttrib vaapi_encode_h264_config_attributes[] = {
|
||||
{ .type = VAConfigAttribRTFormat,
|
||||
.value = VA_RT_FORMAT_YUV420 },
|
||||
{ .type = VAConfigAttribRateControl,
|
||||
.value = VA_RC_CQP },
|
||||
{ .type = VAConfigAttribEncPackedHeaders,
|
||||
.value = (VA_ENC_PACKED_HEADER_SEQUENCE |
|
||||
VA_ENC_PACKED_HEADER_SLICE) },
|
||||
};
|
||||
|
||||
static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx)
|
||||
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;
|
||||
VAAPIEncodeH264Options *opt = ctx->codec_options;
|
||||
|
||||
priv->fixed_qp_p = opt->qp;
|
||||
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 const VAConfigAttrib default_config_attributes[] = {
|
||||
{ .type = VAConfigAttribRTFormat,
|
||||
.value = VA_RT_FORMAT_YUV420 },
|
||||
{ .type = VAConfigAttribEncPackedHeaders,
|
||||
.value = (VA_ENC_PACKED_HEADER_SEQUENCE |
|
||||
VA_ENC_PACKED_HEADER_SLICE) },
|
||||
};
|
||||
|
||||
VAAPIEncodeContext *ctx = avctx->priv_data;
|
||||
VAAPIEncodeH264Context *priv = ctx->priv_data;
|
||||
VAAPIEncodeH264Options *opt = ctx->codec_options;
|
||||
int i, err;
|
||||
|
||||
switch (avctx->profile) {
|
||||
case FF_PROFILE_H264_CONSTRAINED_BASELINE:
|
||||
@ -744,8 +852,6 @@ static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx)
|
||||
}
|
||||
ctx->va_entrypoint = VAEntrypointEncSlice;
|
||||
|
||||
ctx->va_rc_mode = VA_RC_CQP;
|
||||
|
||||
ctx->input_width = avctx->width;
|
||||
ctx->input_height = avctx->height;
|
||||
ctx->aligned_width = FFALIGN(ctx->input_width, 16);
|
||||
@ -753,29 +859,41 @@ static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx)
|
||||
priv->mb_width = ctx->aligned_width / 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++) {
|
||||
ctx->config_attributes[ctx->nb_config_attributes++] =
|
||||
default_config_attributes[i];
|
||||
}
|
||||
|
||||
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, "QP = %d / %d / %d for IDR / P / B frames.\n",
|
||||
priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
|
||||
if (avctx->bit_rate > 0) {
|
||||
ctx->va_rc_mode = VA_RC_CBR;
|
||||
err = vaapi_encode_h264_init_constant_bitrate(avctx);
|
||||
} else {
|
||||
ctx->va_rc_mode = VA_RC_CQP;
|
||||
err = vaapi_encode_h264_init_fixed_qp(avctx);
|
||||
}
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
ctx->config_attributes = vaapi_encode_h264_config_attributes;
|
||||
ctx->nb_config_attributes =
|
||||
FF_ARRAY_ELEMS(vaapi_encode_h264_config_attributes);
|
||||
ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) {
|
||||
.type = VAConfigAttribRateControl,
|
||||
.value = ctx->va_rc_mode,
|
||||
};
|
||||
|
||||
if (opt->quality > 0) {
|
||||
#if VA_CHECK_VERSION(0, 36, 0)
|
||||
priv->quality_params.misc.type =
|
||||
VAEncMiscParameterTypeQualityLevel;
|
||||
priv->quality_params.quality.quality_level = opt->quality;
|
||||
|
||||
ctx->global_params[ctx->nb_global_params] =
|
||||
&priv->quality_params.misc;
|
||||
ctx->global_params_size[ctx->nb_global_params++] =
|
||||
sizeof(priv->quality_params);
|
||||
#else
|
||||
av_log(avctx, AV_LOG_WARNING, "The encode quality option is not "
|
||||
"supported with this VAAPI version.\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
ctx->nb_recon_frames = 20;
|
||||
|
||||
@ -808,13 +926,23 @@ static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
|
||||
return ff_vaapi_encode_init(avctx, &vaapi_encode_type_h264);
|
||||
}
|
||||
|
||||
#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \
|
||||
offsetof(VAAPIEncodeH264Options, x))
|
||||
#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
|
||||
static const AVOption vaapi_encode_h264_options[] = {
|
||||
{ "qp", "Constant QP (for P frames; scaled by qfactor/qoffset for I/B)",
|
||||
OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 20 }, 0, 52, FLAGS },
|
||||
{ "quality", "Set encode quality (trades off against speed, higher is faster)",
|
||||
OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 2, FLAGS },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static const AVCodecDefault vaapi_encode_h264_defaults[] = {
|
||||
{ "profile", "100" },
|
||||
{ "level", "51" },
|
||||
{ "b", "0" },
|
||||
{ "bf", "2" },
|
||||
{ "g", "120" },
|
||||
{ "global_quality", "20" },
|
||||
{ "i_qfactor", "1.0" },
|
||||
{ "i_qoffset", "0.0" },
|
||||
{ "b_qfactor", "1.2" },
|
||||
@ -825,6 +953,7 @@ static const AVCodecDefault vaapi_encode_h264_defaults[] = {
|
||||
static const AVClass vaapi_encode_h264_class = {
|
||||
.class_name = "h264_vaapi",
|
||||
.item_name = av_default_item_name,
|
||||
.option = vaapi_encode_h264_options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
@ -833,7 +962,8 @@ AVCodec ff_h264_vaapi_encoder = {
|
||||
.long_name = NULL_IF_CONFIG_SMALL("H.264/AVC (VAAPI)"),
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_H264,
|
||||
.priv_data_size = sizeof(VAAPIEncodeContext),
|
||||
.priv_data_size = (sizeof(VAAPIEncodeContext) +
|
||||
sizeof(VAAPIEncodeH264Options)),
|
||||
.init = &vaapi_encode_h264_init,
|
||||
.encode2 = &ff_vaapi_encode2,
|
||||
.close = &ff_vaapi_encode_close,
|
||||
|
@ -182,8 +182,22 @@ typedef struct VAAPIEncodeH265Context {
|
||||
int fixed_qp_b;
|
||||
|
||||
int64_t last_idr_frame;
|
||||
|
||||
// Rate control configuration.
|
||||
struct {
|
||||
VAEncMiscParameterBuffer misc;
|
||||
VAEncMiscParameterRateControl rc;
|
||||
} rc_params;
|
||||
struct {
|
||||
VAEncMiscParameterBuffer misc;
|
||||
VAEncMiscParameterHRD hrd;
|
||||
} hrd_params;
|
||||
} VAAPIEncodeH265Context;
|
||||
|
||||
typedef struct VAAPIEncodeH265Options {
|
||||
int qp;
|
||||
} VAAPIEncodeH265Options;
|
||||
|
||||
|
||||
#define vseq_var(name) vseq->name, name
|
||||
#define vseq_field(name) vseq->seq_fields.bits.name, name
|
||||
@ -806,6 +820,19 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
|
||||
vseq->max_transform_hierarchy_depth_intra = 3;
|
||||
|
||||
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 +868,7 @@ static int vaapi_encode_h265_init_sequence_params(AVCodecContext *avctx)
|
||||
|
||||
vpic->pic_fields.bits.screen_content_flag = 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,20 +1151,93 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static VAConfigAttrib vaapi_encode_h265_config_attributes[] = {
|
||||
{ .type = VAConfigAttribRTFormat,
|
||||
.value = VA_RT_FORMAT_YUV420 },
|
||||
{ .type = VAConfigAttribRateControl,
|
||||
.value = VA_RC_CQP },
|
||||
{ .type = VAConfigAttribEncPackedHeaders,
|
||||
.value = (VA_ENC_PACKED_HEADER_SEQUENCE |
|
||||
VA_ENC_PACKED_HEADER_SLICE) },
|
||||
};
|
||||
|
||||
static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx)
|
||||
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;
|
||||
VAAPIEncodeH265Options *opt = ctx->codec_options;
|
||||
|
||||
priv->fixed_qp_p = opt->qp;
|
||||
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 const VAConfigAttrib default_config_attributes[] = {
|
||||
{ .type = VAConfigAttribRTFormat,
|
||||
.value = VA_RT_FORMAT_YUV420 },
|
||||
{ .type = VAConfigAttribEncPackedHeaders,
|
||||
.value = (VA_ENC_PACKED_HEADER_SEQUENCE |
|
||||
VA_ENC_PACKED_HEADER_SLICE) },
|
||||
};
|
||||
|
||||
VAAPIEncodeContext *ctx = avctx->priv_data;
|
||||
VAAPIEncodeH265Context *priv = ctx->priv_data;
|
||||
int i, err;
|
||||
|
||||
switch (avctx->profile) {
|
||||
case FF_PROFILE_HEVC_MAIN:
|
||||
@ -1156,8 +1255,6 @@ static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx)
|
||||
}
|
||||
ctx->va_entrypoint = VAEntrypointEncSlice;
|
||||
|
||||
ctx->va_rc_mode = VA_RC_CQP;
|
||||
|
||||
ctx->input_width = avctx->width;
|
||||
ctx->input_height = avctx->height;
|
||||
ctx->aligned_width = FFALIGN(ctx->input_width, 16);
|
||||
@ -1169,23 +1266,25 @@ static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx)
|
||||
ctx->input_width, ctx->input_height, ctx->aligned_width,
|
||||
ctx->aligned_height, priv->ctu_width, priv->ctu_height);
|
||||
|
||||
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, "QP = %d / %d / %d for IDR / P / B frames.\n",
|
||||
priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
|
||||
ctx->config_attributes[ctx->nb_config_attributes++] =
|
||||
default_config_attributes[i];
|
||||
}
|
||||
|
||||
ctx->config_attributes = vaapi_encode_h265_config_attributes;
|
||||
ctx->nb_config_attributes =
|
||||
FF_ARRAY_ELEMS(vaapi_encode_h265_config_attributes);
|
||||
if (avctx->bit_rate > 0) {
|
||||
ctx->va_rc_mode = VA_RC_CBR;
|
||||
err = vaapi_encode_h265_init_constant_bitrate(avctx);
|
||||
} else {
|
||||
ctx->va_rc_mode = VA_RC_CQP;
|
||||
err = vaapi_encode_h265_init_fixed_qp(avctx);
|
||||
}
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) {
|
||||
.type = VAConfigAttribRateControl,
|
||||
.value = ctx->va_rc_mode,
|
||||
};
|
||||
|
||||
ctx->nb_recon_frames = 20;
|
||||
|
||||
@ -1218,13 +1317,21 @@ static av_cold int vaapi_encode_h265_init(AVCodecContext *avctx)
|
||||
return ff_vaapi_encode_init(avctx, &vaapi_encode_type_h265);
|
||||
}
|
||||
|
||||
#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \
|
||||
offsetof(VAAPIEncodeH265Options, x))
|
||||
#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
|
||||
static const AVOption vaapi_encode_h265_options[] = {
|
||||
{ "qp", "Constant QP (for P frames; scaled by qfactor/qoffset for I/B)",
|
||||
OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, 52, FLAGS },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
static const AVCodecDefault vaapi_encode_h265_defaults[] = {
|
||||
{ "profile", "1" },
|
||||
{ "level", "51" },
|
||||
{ "b", "0" },
|
||||
{ "bf", "2" },
|
||||
{ "g", "120" },
|
||||
{ "global_quality", "25" },
|
||||
{ "i_qfactor", "1.0" },
|
||||
{ "i_qoffset", "0.0" },
|
||||
{ "b_qfactor", "1.2" },
|
||||
@ -1235,6 +1342,7 @@ static const AVCodecDefault vaapi_encode_h265_defaults[] = {
|
||||
static const AVClass vaapi_encode_h265_class = {
|
||||
.class_name = "h265_vaapi",
|
||||
.item_name = av_default_item_name,
|
||||
.option = vaapi_encode_h265_options,
|
||||
.version = LIBAVUTIL_VERSION_INT,
|
||||
};
|
||||
|
||||
@ -1243,7 +1351,8 @@ AVCodec ff_hevc_vaapi_encoder = {
|
||||
.long_name = NULL_IF_CONFIG_SMALL("H.265/HEVC (VAAPI)"),
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_HEVC,
|
||||
.priv_data_size = sizeof(VAAPIEncodeContext),
|
||||
.priv_data_size = (sizeof(VAAPIEncodeContext) +
|
||||
sizeof(VAAPIEncodeH265Options)),
|
||||
.init = &vaapi_encode_h265_init,
|
||||
.encode2 = &ff_vaapi_encode2,
|
||||
.close = &ff_vaapi_encode_close,
|
||||
|
@ -333,17 +333,18 @@ static int vaapi_encode_mjpeg_init_slice_params(AVCodecContext *avctx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static VAConfigAttrib vaapi_encode_mjpeg_config_attributes[] = {
|
||||
static av_cold int vaapi_encode_mjpeg_init_internal(AVCodecContext *avctx)
|
||||
{
|
||||
static const VAConfigAttrib default_config_attributes[] = {
|
||||
{ .type = VAConfigAttribRTFormat,
|
||||
.value = VA_RT_FORMAT_YUV420 },
|
||||
{ .type = VAConfigAttribEncPackedHeaders,
|
||||
.value = VA_ENC_PACKED_HEADER_SEQUENCE },
|
||||
};
|
||||
};
|
||||
|
||||
static av_cold int vaapi_encode_mjpeg_init_internal(AVCodecContext *avctx)
|
||||
{
|
||||
VAAPIEncodeContext *ctx = avctx->priv_data;
|
||||
VAAPIEncodeMJPEGContext *priv = ctx->priv_data;
|
||||
int i;
|
||||
|
||||
ctx->va_profile = VAProfileJPEGBaseline;
|
||||
ctx->va_entrypoint = VAEntrypointEncPicture;
|
||||
@ -353,9 +354,10 @@ static av_cold int vaapi_encode_mjpeg_init_internal(AVCodecContext *avctx)
|
||||
ctx->aligned_width = FFALIGN(ctx->input_width, 8);
|
||||
ctx->aligned_height = FFALIGN(ctx->input_height, 8);
|
||||
|
||||
ctx->config_attributes = vaapi_encode_mjpeg_config_attributes;
|
||||
ctx->nb_config_attributes =
|
||||
FF_ARRAY_ELEMS(vaapi_encode_mjpeg_config_attributes);
|
||||
for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
|
||||
ctx->config_attributes[ctx->nb_config_attributes++] =
|
||||
default_config_attributes[i];
|
||||
}
|
||||
|
||||
priv->quality = avctx->global_quality;
|
||||
if (priv->quality < 1 || priv->quality > 100) {
|
||||
|
Loading…
Reference in New Issue
Block a user