[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