Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/FFmpeg/FFmpeg.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Buitenhuis <derek.buitenhuis@gmail.com>2016-05-11 21:40:30 +0300
committerDerek Buitenhuis <derek.buitenhuis@gmail.com>2016-05-11 21:40:39 +0300
commit8ed427f9f92fd45c2510c019dba932acda74817f (patch)
tree860dca02a5cf782100e7abf6a64a35ddab5f967d /libavcodec/vaapi_encode_h264.c
parentbc3d2f25783a4f61b7018800a12182dc46ff8325 (diff)
parent92fdea37477b5a2d1329e5ef0773e24473fa8f12 (diff)
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>
Diffstat (limited to 'libavcodec/vaapi_encode_h264.c')
-rw-r--r--libavcodec/vaapi_encode_h264.c196
1 files changed, 163 insertions, 33 deletions
diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
index 12bd71d103..0a99bb19ae 100644
--- a/libavcodec/vaapi_encode_h264.c
+++ b/libavcodec/vaapi_encode_h264.c
@@ -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_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;
+ for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
+ ctx->config_attributes[ctx->nb_config_attributes++] =
+ default_config_attributes[i];
+ }
+
if (avctx->bit_rate > 0) {
- av_log(avctx, AV_LOG_ERROR, "Constant bitrate encoding is not "
- "supported!\n");
- return AVERROR_PATCHWELCOME;
+ 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;
- 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);
+ ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) {
+ .type = VAConfigAttribRateControl,
+ .value = ctx->va_rc_mode,
+ };
- ctx->config_attributes = vaapi_encode_h264_config_attributes;
- ctx->nb_config_attributes =
- FF_ARRAY_ELEMS(vaapi_encode_h264_config_attributes);
+ 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,