[Libva] [Libva-intel-driver][PATCH 04/18] Check bitrate control related parameters in sequence and misc parameters
Xiang, Haihao
haihao.xiang at intel.com
Thu Sep 8 05:22:05 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,
> > + VAEncMiscParameterRateC
> > ontrol *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,
> > + VAEncMiscParameterFrameRat
> > e *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_contex
> > t,
> > + (VAEncMiscPara
> > meterFrameRate *)misc_param->data);
> > + break;
> > +
> > + case VAEncMiscParameterTypeRateControl:
> > + intel_encoder_check_rate_control_parameter(ctx,
> > + encoder_con
> > text,
> > + (VAEncMiscP
> > arameterRateControl *)misc_param->data);
> > + break;
> > +
> > + case VAEncMiscParameterTypeHRD:
> > + intel_encoder_check_hrd_parameter(ctx,
> > + encoder_context,
> > + (VAEncMiscParameterH
> > RD *)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.
Other codec also use similar variables in our driver, if a variable
e.g. num_bframes_in_gop is not used for VP8/VP9, we can set it to 0 or
ignore it.
>
> Another small concern is which bit_rate should be used if both the
> SPS
> and Misc_rateControl define the bit-rate?
According to the comment for bits_per_second in va_enc_xxx.h, the
initial bitrate value is specified by bits_per_second in SPS, but it
can be modified later by VAEncMiscParameterRateControl.
So both SPS and VAEncMiscParameterRateControl define the bit-rate, the
latter should be used.
>
> Thanks
> Yakui
>
> > void *vme_context;
> > void *mfc_context;
> > void *enc_priv_state;
>
More information about the Libva
mailing list