[Libva] [Libva-intel-driver][PATCH 04/18] Check bitrate control related parameters in sequence and misc parameters
Zhao Yakui
yakui.zhao at intel.com
Wed Sep 7 03:23:22 UTC 2016
On 09/06/2016 11:41 PM, Xiang, Haihao wrote:
> Currently only used for H.264 encoding
>
> Signed-off-by: Xiang, Haihao<haihao.xiang at intel.com>
> ---
> src/i965_encoder.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++--
> src/i965_encoder.h | 12 ++++
> 2 files changed, 190 insertions(+), 6 deletions(-)
>
> diff --git a/src/i965_encoder.c b/src/i965_encoder.c
> index d045881..50f735a 100644
> --- a/src/i965_encoder.c
> +++ b/src/i965_encoder.c
> @@ -293,10 +293,179 @@ intel_encoder_check_jpeg_yuv_surface(VADriverContextP ctx,
> }
>
> static VAStatus
> +intel_encoder_check_brc_h264_sequence_parameter(VADriverContextP ctx,
> + struct encode_state *encode_state,
> + struct intel_encoder_context *encoder_context)
> +{
> + VAEncSequenceParameterBufferH264 *seq_param = (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
> + unsigned short num_pframes_in_gop, num_bframes_in_gop;
> + unsigned int bits_per_second, framerate_per_100s;
> +
> + if (!encoder_context->is_new_sequence)
> + return VA_STATUS_SUCCESS;
> +
> + assert(seq_param);
> + bits_per_second = seq_param->bits_per_second;
> + framerate_per_100s = seq_param->time_scale * 100 / (2 * seq_param->num_units_in_tick);
> + encoder_context->brc.num_iframes_in_gop = 1; // Always 1
> +
> + if (seq_param->intra_period == 0) { // E.g. IDRPP... / IDR(PBB)... (no IDR/I any more)
> + if (seq_param->ip_period == 0)
> + goto error;
> +
> + encoder_context->brc.gop_size = (unsigned int)(framerate_per_100s / 100.0 + 0.5); // fake
> + num_pframes_in_gop = (encoder_context->brc.gop_size +
> + seq_param->ip_period - 1) / seq_param->ip_period - 1;
> + } else if (seq_param->intra_period == 1) { // E.g. IDRIII...
> + encoder_context->brc.gop_size = 1;
> + num_pframes_in_gop = 0;
> + } else {
> + if (seq_param->ip_period == 0)
> + goto error;
> +
> + encoder_context->brc.gop_size = seq_param->intra_period;
> + num_pframes_in_gop = (encoder_context->brc.gop_size +
> + seq_param->ip_period - 1) / seq_param->ip_period - 1;
> + }
> +
> + num_bframes_in_gop = (encoder_context->brc.gop_size -
> + encoder_context->brc.num_iframes_in_gop - num_pframes_in_gop);
> +
> + if (num_pframes_in_gop != encoder_context->brc.num_pframes_in_gop ||
> + num_bframes_in_gop != encoder_context->brc.num_bframes_in_gop ||
> + bits_per_second != encoder_context->brc.bits_per_second ||
> + framerate_per_100s != encoder_context->brc.framerate_per_100s) {
> + encoder_context->brc.num_pframes_in_gop = num_pframes_in_gop;
> + encoder_context->brc.num_bframes_in_gop = num_bframes_in_gop;
> + encoder_context->brc.bits_per_second = bits_per_second;
> + encoder_context->brc.framerate_per_100s = framerate_per_100s;
> + encoder_context->brc.need_reset = 1;
> + }
> +
> + if (!encoder_context->brc.hrd_buffer_size ||
> + !encoder_context->brc.hrd_initial_buffer_fullness) {
> + encoder_context->brc.hrd_buffer_size = seq_param->bits_per_second<< 1;
> + encoder_context->brc.hrd_initial_buffer_fullness = seq_param->bits_per_second;
> + }
> +
> + return VA_STATUS_SUCCESS;
> +
> +error:
> + return VA_STATUS_ERROR_INVALID_PARAMETER;
> +}
> +
> +static VAStatus
> +intel_encoder_check_brc_sequence_parameter(VADriverContextP ctx,
> + struct encode_state *encode_state,
> + struct intel_encoder_context *encoder_context)
> +{
> + if (encoder_context->codec == CODEC_H264 ||
> + encoder_context->codec == CODEC_H264_MVC)
> + return intel_encoder_check_brc_h264_sequence_parameter(ctx, encode_state, encoder_context);
> +
> + // TODO: other codecs
> + return VA_STATUS_SUCCESS;
> +}
> +
> +static void
> +intel_encoder_check_rate_control_parameter(VADriverContextP ctx,
> + struct intel_encoder_context *encoder_context,
> + VAEncMiscParameterRateControl *misc)
> +{
> + // TODO: for VBR
> + if (encoder_context->brc.bits_per_second != misc->bits_per_second) {
> + encoder_context->brc.bits_per_second = misc->bits_per_second;
> + encoder_context->brc.need_reset = 1;
> + }
> +}
> +
> +static void
> +intel_encoder_check_hrd_parameter(VADriverContextP ctx,
> + struct intel_encoder_context *encoder_context,
> + VAEncMiscParameterHRD *misc)
> +{
> + if (encoder_context->brc.hrd_buffer_size != misc->buffer_size ||
> + encoder_context->brc.hrd_initial_buffer_fullness != misc->initial_buffer_fullness) {
> + encoder_context->brc.hrd_buffer_size = misc->buffer_size;
> + encoder_context->brc.hrd_initial_buffer_fullness = misc->initial_buffer_fullness;
> + encoder_context->brc.need_reset = 1;
> + }
> +}
> +
> +static void
> +intel_encoder_check_framerate_parameter(VADriverContextP ctx,
> + struct intel_encoder_context *encoder_context,
> + VAEncMiscParameterFrameRate *misc)
> +{
> + int framerate_per_100s;
> +
> + if (misc->framerate& 0xffff0000)
> + framerate_per_100s = (misc->framerate& 0xffff) * 100 / ((misc->framerate>> 16)& 0xffff);
> + else
> + framerate_per_100s = misc->framerate * 100;
> +
> + if (encoder_context->brc.framerate_per_100s != framerate_per_100s) {
> + encoder_context->brc.framerate_per_100s = framerate_per_100s;
> + encoder_context->brc.need_reset = 1;
> + }
> +}
> +
> +static VAStatus
> +intel_encoder_check_brc_parameter(VADriverContextP ctx,
> + struct encode_state *encode_state,
> + struct intel_encoder_context *encoder_context)
> +{
> + VAStatus ret;
> + VAEncMiscParameterBuffer *misc_param;
> + int i;
> +
> + if (!(encoder_context->rate_control_mode& (VA_RC_CBR | VA_RC_VBR)))
> + return VA_STATUS_SUCCESS;
> +
> + ret = intel_encoder_check_brc_sequence_parameter(ctx, encode_state, encoder_context);
> +
> + if (ret)
> + return ret;
> +
> + for (i = 0; i< ARRAY_ELEMS(encode_state->misc_param); i++) {
> + if (!encode_state->misc_param[i] || !encode_state->misc_param[i]->buffer)
> + continue;
> +
> + misc_param = (VAEncMiscParameterBuffer *)encode_state->misc_param[i]->buffer;
> +
> + switch (misc_param->type) {
> + case VAEncMiscParameterTypeFrameRate:
> + intel_encoder_check_framerate_parameter(ctx,
> + encoder_context,
> + (VAEncMiscParameterFrameRate *)misc_param->data);
> + break;
> +
> + case VAEncMiscParameterTypeRateControl:
> + intel_encoder_check_rate_control_parameter(ctx,
> + encoder_context,
> + (VAEncMiscParameterRateControl *)misc_param->data);
> + break;
> +
> + case VAEncMiscParameterTypeHRD:
> + intel_encoder_check_hrd_parameter(ctx,
> + encoder_context,
> + (VAEncMiscParameterHRD *)misc_param->data);
> + break;
> +
> + default:
> + break;
> + }
> + }
> +
> + return VA_STATUS_SUCCESS;
> +}
> +
> +static VAStatus
> intel_encoder_check_misc_parameter(VADriverContextP ctx,
> struct encode_state *encode_state,
> struct intel_encoder_context *encoder_context)
> {
> + VAStatus ret = VA_STATUS_SUCCESS;
>
> if (encode_state->misc_param[VAEncMiscParameterTypeQualityLevel]&&
> encode_state->misc_param[VAEncMiscParameterTypeQualityLevel]->buffer) {
> @@ -306,14 +475,16 @@ intel_encoder_check_misc_parameter(VADriverContextP ctx,
>
> if (encoder_context->quality_level == 0)
> encoder_context->quality_level = ENCODER_DEFAULT_QUALITY;
> - else if (encoder_context->quality_level> encoder_context->quality_range)
> - goto error;
> - }
> + else if (encoder_context->quality_level> encoder_context->quality_range) {
> + ret = VA_STATUS_ERROR_INVALID_PARAMETER;
> + goto out;
> + }
> + }
>
> - return VA_STATUS_SUCCESS;
> + ret = intel_encoder_check_brc_parameter(ctx, encode_state, encoder_context);
>
> -error:
> - return VA_STATUS_ERROR_INVALID_PARAMETER;
> +out:
> + return ret;
> }
>
> static VAStatus
> @@ -782,6 +953,7 @@ intel_encoder_end_picture(VADriverContextP ctx,
>
> encoder_context->mfc_pipeline(ctx, profile, encode_state, encoder_context);
> encoder_context->num_frames_in_sequence++;
> + encoder_context->brc.need_reset = 0;
>
> return VA_STATUS_SUCCESS;
> }
> diff --git a/src/i965_encoder.h b/src/i965_encoder.h
> index de20ef9..808a336 100644
> --- a/src/i965_encoder.h
> +++ b/src/i965_encoder.h
> @@ -63,6 +63,18 @@ struct intel_encoder_context
> unsigned int frame_width_in_mbs;
> unsigned int frame_height_in_mbs;
>
> + struct {
> + unsigned short gop_size;
> + unsigned short num_iframes_in_gop;
> + unsigned short num_pframes_in_gop;
> + unsigned short num_bframes_in_gop;
> + unsigned int bits_per_second;
> + unsigned int framerate_per_100s;
> + unsigned int hrd_buffer_size;
> + unsigned int hrd_initial_buffer_fullness;
> + unsigned int need_reset;
> + } brc;
> +
how about naming it as h264_brc? It seems that the above definition is
mainly for the H264 encoding.
For the other codec it will use the different definition.
Another small concern is which bit_rate should be used if both the SPS
and Misc_rateControl define the bit-rate?
Thanks
Yakui
> void *vme_context;
> void *mfc_context;
> void *enc_priv_state;
More information about the Libva
mailing list