summaryrefslogtreecommitdiff
path: root/libavcodec
diff options
context:
space:
mode:
authorMark Thompson <sw@jkqxz.net>2016-04-12 23:18:13 +0100
committerAnton Khirnov <anton@khirnov.net>2016-04-15 10:07:05 +0200
commitf70e4627933b8f38a964657aff26ef2d590877b4 (patch)
tree5dd7e89e2c3c97a833c47645d92f675d63a79de5 /libavcodec
parentfcf536b1301475c57a7f94d00b1aebf5d20fe9d3 (diff)
vaapi_h265: Add constant-bitrate encode support
Signed-off-by: Anton Khirnov <anton@khirnov.net>
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/vaapi_encode_h265.c132
1 files changed, 109 insertions, 23 deletions
diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index 323efd46a7..128b5a5e53 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -182,6 +182,16 @@ 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;
@@ -806,6 +816,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 +864,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,6 +1147,79 @@ static int vaapi_encode_h265_init_slice_params(AVCodecContext *avctx,
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 const VAConfigAttrib default_config_attributes[] = {
@@ -1133,13 +1228,11 @@ static av_cold int vaapi_encode_h265_init_internal(AVCodecContext *avctx)
{ .type = VAConfigAttribEncPackedHeaders,
.value = (VA_ENC_PACKED_HEADER_SEQUENCE |
VA_ENC_PACKED_HEADER_SLICE) },
- { .type = VAConfigAttribRateControl,
- .value = VA_RC_CQP },
};
VAAPIEncodeContext *ctx = avctx->priv_data;
VAAPIEncodeH265Context *priv = ctx->priv_data;
- int i;
+ int i, err;
switch (avctx->profile) {
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) {
- av_log(avctx, AV_LOG_ERROR, "H.265 constant-bitrate encoding "
- "is not supported.\n");
- return AVERROR_PATCHWELCOME;
+ 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->va_rc_mode = VA_RC_CQP;
-
- 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->nb_recon_frames = 20;