[Libva] [PATCH 23/31] ENC: kernel related parameter check function for AVC encoder

Sean V Kelley seanvk at posteo.de
Tue Jan 10 23:38:05 UTC 2017


From: Pengfei Qu <Pengfei.Qu at intel.com>

Signed-off-by: Pengfei Qu <Pengfei.Qu at intel.com>
Reviewed-by: Sean V Kelley <seanvk at posteo.de>
---
 src/gen9_avc_encoder.c | 388 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 388 insertions(+)

diff --git a/src/gen9_avc_encoder.c b/src/gen9_avc_encoder.c
index f8dc45c6..04cf30f0 100755
--- a/src/gen9_avc_encoder.c
+++ b/src/gen9_avc_encoder.c
@@ -4795,3 +4795,391 @@ gen9_avc_kernel_destroy(struct encoder_vme_mfc_context * vme_context)
     gen8_gpe_context_destroy(&avc_ctx->context_sfd.gpe_contexts);
 
 }
+
+/*
+vme pipeline
+*/
+static void
+gen9_avc_update_parameters(VADriverContextP ctx,
+                             VAProfile profile,
+                             struct encode_state *encode_state,
+                             struct intel_encoder_context *encoder_context)
+{
+    struct encoder_vme_mfc_context * vme_context = (struct encoder_vme_mfc_context *)encoder_context->vme_context;
+    struct generic_enc_codec_state * generic_state = (struct generic_enc_codec_state * )vme_context->generic_enc_state;
+    struct avc_enc_state * avc_state = (struct avc_enc_state * )vme_context->private_enc_state;
+    VAEncSequenceParameterBufferH264 *seq_param;
+    VAEncPictureParameterBufferH264 *pic_param ;
+    VAEncSliceParameterBufferH264 * slice_param;
+    int i,j;
+    unsigned int preset = generic_state->preset;
+
+    /* seq/pic/slice parameter setting */
+    generic_state->b16xme_supported = gen9_avc_super_hme[preset];
+    generic_state->b32xme_supported = gen9_avc_ultra_hme[preset];
+
+    avc_state->seq_param =  (VAEncSequenceParameterBufferH264 *)encode_state->seq_param_ext->buffer;
+    avc_state->pic_param = (VAEncPictureParameterBufferH264 *)encode_state->pic_param_ext->buffer;
+
+
+    avc_state->enable_avc_ildb = 0;
+    avc_state->slice_num = 0;
+    for (j = 0; j < encode_state->num_slice_params_ext && avc_state->enable_avc_ildb == 0; j++) {
+        assert(encode_state->slice_params_ext && encode_state->slice_params_ext[j]->buffer);
+        slice_param = (VAEncSliceParameterBufferH264 *)encode_state->slice_params_ext[j]->buffer;
+
+        for (i = 0; i < encode_state->slice_params_ext[j]->num_elements; i++) {
+            assert((slice_param->slice_type == SLICE_TYPE_I) ||
+                   (slice_param->slice_type == SLICE_TYPE_SI) ||
+                   (slice_param->slice_type == SLICE_TYPE_P) ||
+                   (slice_param->slice_type == SLICE_TYPE_SP) ||
+                   (slice_param->slice_type == SLICE_TYPE_B));
+
+            if (slice_param->disable_deblocking_filter_idc != 1) {
+                avc_state->enable_avc_ildb = 1;
+            }
+
+            avc_state->slice_param[i] = slice_param;
+            slice_param++;
+            avc_state->slice_num++;
+        }
+    }
+
+    /* how many slices support by now? 1 slice or multi slices, but row slice.not slice group. */
+    seq_param = avc_state->seq_param;
+    pic_param = avc_state->pic_param;
+    slice_param = avc_state->slice_param[0];
+
+    generic_state->frame_type = avc_state->slice_param[0]->slice_type;
+
+    if (slice_param->slice_type == SLICE_TYPE_I ||
+        slice_param->slice_type == SLICE_TYPE_SI)
+        generic_state->frame_type = SLICE_TYPE_I;
+    else if(slice_param->slice_type == SLICE_TYPE_P)
+        generic_state->frame_type = SLICE_TYPE_P;
+    else if(slice_param->slice_type == SLICE_TYPE_B)
+        generic_state->frame_type = SLICE_TYPE_B;
+    if (profile == VAProfileH264High)
+        avc_state->transform_8x8_mode_enable = !!pic_param->pic_fields.bits.transform_8x8_mode_flag;
+    else
+        avc_state->transform_8x8_mode_enable = 0;
+
+    /* rc init*/
+    if(generic_state->brc_enabled &&(!generic_state->brc_inited || generic_state->brc_need_reset ))
+    {
+        generic_state->target_bit_rate = ALIGN(seq_param->bits_per_second, 1000) / 1000;
+        generic_state->init_vbv_buffer_fullness_in_bit = seq_param->bits_per_second;
+        generic_state->vbv_buffer_size_in_bit = (uint64_t)seq_param->bits_per_second << 1;
+        generic_state->frames_per_100s = 3000; /* 30fps */
+    }
+
+    generic_state->gop_size = seq_param->intra_period;
+    generic_state->gop_ref_distance = seq_param->ip_period;
+
+    if (generic_state->internal_rate_mode == INTEL_BRC_CBR) {
+        generic_state->max_bit_rate = generic_state->target_bit_rate;
+        generic_state->min_bit_rate = generic_state->target_bit_rate;
+    }
+
+    if(generic_state->frame_type == SLICE_TYPE_I || generic_state->first_frame)
+    {
+        gen9_avc_update_misc_parameters(ctx, encode_state, encoder_context);
+    }
+
+    generic_state->preset = encoder_context->quality_level;
+    if(encoder_context->quality_level == INTEL_PRESET_UNKNOWN)
+    {
+        generic_state->preset = INTEL_PRESET_RT_SPEED;
+    }
+    generic_state->kernel_mode = gen9_avc_kernel_mode[generic_state->preset];
+
+    if(!generic_state->brc_inited)
+    {
+        generic_state->brc_init_reset_input_bits_per_frame = ((double)(generic_state->max_bit_rate * 1000) * 100) / generic_state->frames_per_100s;;
+        generic_state->brc_init_current_target_buf_full_in_bits = generic_state->init_vbv_buffer_fullness_in_bit;
+        generic_state->brc_init_reset_buf_size_in_bits = generic_state->vbv_buffer_size_in_bit;
+        generic_state->brc_target_size = generic_state->init_vbv_buffer_fullness_in_bit;
+    }
+
+
+    generic_state->curr_pak_pass = 0;
+    generic_state->num_pak_passes = MAX_AVC_PAK_PASS_NUM;
+
+    if (generic_state->internal_rate_mode == INTEL_BRC_CBR ||
+        generic_state->internal_rate_mode == INTEL_BRC_VBR)
+        generic_state->brc_enabled = 1;
+    else
+        generic_state->brc_enabled = 0;
+
+    if (generic_state->brc_enabled &&
+        (!generic_state->init_vbv_buffer_fullness_in_bit ||
+         !generic_state->vbv_buffer_size_in_bit ||
+         !generic_state->max_bit_rate ||
+         !generic_state->target_bit_rate ||
+         !generic_state->frames_per_100s))
+    {
+        WARN_ONCE("Rate control parameter is required for BRC\n");
+        generic_state->brc_enabled = 0;
+    }
+
+    if (!generic_state->brc_enabled) {
+        generic_state->target_bit_rate = 0;
+        generic_state->max_bit_rate = 0;
+        generic_state->min_bit_rate = 0;
+        generic_state->init_vbv_buffer_fullness_in_bit = 0;
+        generic_state->vbv_buffer_size_in_bit = 0;
+        generic_state->num_pak_passes = 2;
+    } else {
+        generic_state->num_pak_passes = MAX_AVC_PAK_PASS_NUM;
+    }
+
+
+    generic_state->frame_width_in_mbs = seq_param->picture_width_in_mbs;
+    generic_state->frame_height_in_mbs = seq_param->picture_height_in_mbs;
+    generic_state->frame_width_in_pixel = generic_state->frame_width_in_mbs * 16;
+    generic_state->frame_height_in_pixel = generic_state->frame_height_in_mbs * 16;
+
+    generic_state->frame_width_4x  = ALIGN(generic_state->frame_width_in_pixel/4,16);
+    generic_state->frame_height_4x = ALIGN(generic_state->frame_height_in_pixel/4,16);
+    generic_state->downscaled_width_4x_in_mb  = generic_state->frame_width_4x/16 ;
+    generic_state->downscaled_height_4x_in_mb = generic_state->frame_height_4x/16;
+
+    generic_state->frame_width_16x  =  ALIGN(generic_state->frame_width_in_pixel/16,16);
+    generic_state->frame_height_16x =  ALIGN(generic_state->frame_height_in_pixel/16,16);
+    generic_state->downscaled_width_16x_in_mb  = generic_state->frame_width_16x/16 ;
+    generic_state->downscaled_height_16x_in_mb = generic_state->frame_height_16x/16;
+
+    generic_state->frame_width_32x  = ALIGN(generic_state->frame_width_in_pixel/32,16);
+    generic_state->frame_height_32x = ALIGN(generic_state->frame_height_in_pixel/32,16);
+    generic_state->downscaled_width_32x_in_mb  = generic_state->frame_width_32x/16 ;
+    generic_state->downscaled_height_32x_in_mb = generic_state->frame_height_32x/16;
+
+    if (generic_state->hme_supported) {
+        generic_state->hme_enabled = 1;
+    } else {
+        generic_state->hme_enabled = 0;
+    }
+
+    if (generic_state->b16xme_supported) {
+        generic_state->b16xme_enabled = 1;
+    } else {
+        generic_state->b16xme_enabled = 0;
+    }
+
+    if (generic_state->b32xme_supported) {
+        generic_state->b32xme_enabled = 1;
+    } else {
+        generic_state->b32xme_enabled = 0;
+    }
+    /* disable HME/16xME if the size is too small */
+    if (generic_state->frame_width_4x <= INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT) {
+        generic_state->b32xme_supported = 0;
+        generic_state->b32xme_enabled = 0;
+        generic_state->b16xme_supported = 0;
+        generic_state->b16xme_enabled = 0;
+        generic_state->frame_width_4x = INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT;
+        generic_state->downscaled_width_4x_in_mb = WIDTH_IN_MACROBLOCKS(INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT);
+    }
+    if (generic_state->frame_height_4x <= INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT) {
+        generic_state->b32xme_supported = 0;
+        generic_state->b32xme_enabled = 0;
+        generic_state->b16xme_supported = 0;
+        generic_state->b16xme_enabled = 0;
+        generic_state->frame_height_4x = INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT;
+        generic_state->downscaled_height_4x_in_mb = WIDTH_IN_MACROBLOCKS(INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT);
+    }
+
+    if (generic_state->frame_width_16x < INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT)
+    {
+        generic_state->b32xme_supported = 0;
+        generic_state->b32xme_enabled = 0;
+        generic_state->frame_width_16x = INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT;
+        generic_state->downscaled_width_16x_in_mb = WIDTH_IN_MACROBLOCKS(INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT);
+    }
+    if (generic_state->frame_height_16x < INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT) {
+        generic_state->b32xme_supported = 0;
+        generic_state->b32xme_enabled = 0;
+        generic_state->frame_height_16x = INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT;
+        generic_state->downscaled_height_16x_in_mb = WIDTH_IN_MACROBLOCKS(INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT);
+    }
+
+    if (generic_state->frame_width_32x < INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT)
+    {
+        generic_state->frame_width_32x = INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT;
+        generic_state->downscaled_width_32x_in_mb = WIDTH_IN_MACROBLOCKS(INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT);
+    }
+    if (generic_state->frame_height_32x < INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT) {
+        generic_state->frame_height_32x = INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT;
+        generic_state->downscaled_height_32x_in_mb = WIDTH_IN_MACROBLOCKS(INTEL_VME_MIN_ALLOWED_WIDTH_HEIGHT);
+    }
+
+}
+
+static VAStatus
+gen9_avc_encode_check_parameter(VADriverContextP ctx,
+                                struct encode_state *encode_state,
+                                struct intel_encoder_context *encoder_context)
+{
+    struct encoder_vme_mfc_context * vme_context = (struct encoder_vme_mfc_context *)encoder_context->vme_context;
+    struct generic_enc_codec_state * generic_state = (struct generic_enc_codec_state * )vme_context->generic_enc_state;
+    struct avc_enc_state * avc_state = (struct avc_enc_state * )vme_context->private_enc_state;
+    unsigned int rate_control_mode = encoder_context->rate_control_mode;
+    unsigned int preset = generic_state->preset;
+    VAEncPictureParameterBufferH264 *pic_param ;
+    int i = 0;
+
+    /*resolution change detection*/
+    pic_param = avc_state->pic_param;
+
+    /*avbr init*/
+    generic_state->avbr_curracy = 30;
+    generic_state->avbr_convergence = 150;
+
+    switch (rate_control_mode & 0x7f) {
+    case VA_RC_CBR:
+        generic_state->internal_rate_mode = INTEL_BRC_CBR;
+        break;
+
+    case VA_RC_VBR:
+        generic_state->internal_rate_mode = INTEL_BRC_VBR;
+        break;
+
+    case VA_RC_CQP:
+    default:
+        generic_state->internal_rate_mode = INTEL_BRC_CQP;
+        break;
+    }
+
+    if (rate_control_mode != VA_RC_NONE &&
+        rate_control_mode != VA_RC_CQP) {
+        generic_state->brc_enabled = 1;
+        generic_state->brc_distortion_buffer_supported = 1;
+        generic_state->brc_constant_buffer_supported = 1;
+        generic_state->num_pak_passes = MAX_AVC_PAK_PASS_NUM;
+    }
+
+    /*check brc parameter*/
+    if(generic_state->brc_enabled)
+    {
+       avc_state->mb_qp_data_enable = 0;
+    }
+
+    /*set the brc init and reset accordingly*/
+    if(generic_state->brc_need_reset &&
+        (generic_state->brc_distortion_buffer_supported == 0 ||
+        rate_control_mode == VA_RC_CQP))
+    {
+       generic_state->brc_need_reset = 0;// not support by CQP
+    }
+
+    if(generic_state->brc_need_reset && !avc_state->sfd_mb_enable)
+    {
+        avc_state->sfd_enable = 0;
+    }
+
+    if(generic_state->window_size == 0)
+    {
+        generic_state->window_size = (generic_state->frames_per_100s/100 < 60)?(generic_state->frames_per_100s/100):60;
+    }else if(generic_state->window_size > 2 * generic_state->frames_per_100s/100)
+    {
+        generic_state->window_size = (generic_state->frames_per_100s/100 < 60)?(generic_state->frames_per_100s/100):60;
+    }
+
+    if(generic_state->brc_enabled)
+    {
+        generic_state->hme_enabled = generic_state->frame_type != SLICE_TYPE_I;
+        if(avc_state->min_max_qp_enable)
+        {
+            generic_state->num_pak_passes = 1;
+        }
+        generic_state->brc_roi_enable = (rate_control_mode != VA_RC_CQP) && (generic_state->num_roi > 0);// only !CQP
+        generic_state->mb_brc_enabled = generic_state->mb_brc_enabled || generic_state->brc_roi_enable;
+    }else
+    {
+        generic_state->num_pak_passes = 2;// CQP only one pass
+    }
+
+    avc_state->mbenc_i_frame_dist_in_use = 0;
+    avc_state->mbenc_i_frame_dist_in_use = (generic_state->brc_enabled) && (generic_state->brc_distortion_buffer_supported) && (generic_state->frame_type == SLICE_TYPE_I);
+
+    /*ROI must enable mbbrc.*/
+
+    /*CAD check*/
+    if(avc_state->caf_supported)
+    {
+        switch(generic_state->frame_type)
+        {
+        case SLICE_TYPE_I:
+            break;
+        case SLICE_TYPE_P:
+            avc_state->caf_enable = gen9_avc_all_fractional[preset] & 0x01;
+            break;
+        case SLICE_TYPE_B:
+            avc_state->caf_enable = (gen9_avc_all_fractional[preset] >> 1) & 0x01;
+            break;
+        }
+
+        if(avc_state->caf_enable && avc_state->caf_disable_hd && gen9_avc_disable_all_fractional_check_for_high_res[preset])
+        {
+            if(generic_state->frame_width_in_pixel >= 1280 && generic_state->frame_height_in_pixel >= 720)
+                 avc_state->caf_enable = 0;
+        }
+    }
+
+    avc_state->adaptive_transform_decision_enable &= gen9_avc_enable_adaptive_tx_decision[preset&0x7];
+
+    /* Flatness check is enabled only if scaling will be performed and CAF is enabled. here only frame */
+    if(avc_state->flatness_check_supported )
+    {
+        avc_state->flatness_check_enable = ((avc_state->caf_enable) && (generic_state->brc_enabled || generic_state->hme_supported)) ;
+    }else
+    {
+        avc_state->flatness_check_enable = 0;
+    }
+
+    /* check mb_status_supported/enbale*/
+    if(avc_state->adaptive_transform_decision_enable)
+    {
+       avc_state->mb_status_enable = 1;
+    }else
+    {
+       avc_state->mb_status_enable = 0;
+    }
+    /*slice check,all the slices use the same slice height except the last slice*/
+    avc_state->arbitrary_num_mbs_in_slice = 0;
+    for(i = 0; i < avc_state->slice_num;i++)
+    {
+        assert(avc_state->slice_param[i]->num_macroblocks % generic_state->frame_width_in_mbs == 0);
+        avc_state->slice_height = avc_state->slice_param[i]->num_macroblocks / generic_state->frame_width_in_mbs;
+        /*add it later for muli slices map*/
+    }
+
+    if(generic_state->frame_type == SLICE_TYPE_I)
+    {
+       generic_state->hme_enabled = 0;
+       generic_state->b16xme_enabled = 0;
+       generic_state->b32xme_enabled = 0;
+    }
+
+    if(generic_state->frame_type == SLICE_TYPE_B)
+    {
+        gen9_avc_get_dist_scale_factor(ctx,encode_state,encoder_context);
+        avc_state->bi_weight = gen9_avc_get_biweight(avc_state->dist_scale_factor_list0[0],pic_param->pic_fields.bits.weighted_bipred_idc);
+    }
+
+    /* Determine if SkipBiasAdjustment should be enabled for P picture 1. No B frame 2. Qp >= 22 3. CQP mode */
+    avc_state->skip_bias_adjustment_enable = avc_state->skip_bias_adjustment_supported && (generic_state->frame_type == SLICE_TYPE_P)
+        && (generic_state->gop_ref_distance == 1) && (avc_state->pic_param->pic_init_qp + avc_state->slice_param[0]->slice_qp_delta >= 22) && !generic_state->brc_enabled;
+
+    if(generic_state->kernel_mode == INTEL_ENC_KERNEL_QUALITY)
+    {
+        avc_state->tq_enable = 1;
+        avc_state->tq_rounding = 6;
+        if(generic_state->brc_enabled)
+        {
+            generic_state->mb_brc_enabled = 1;
+        }
+    }
+
+    return VA_STATUS_SUCCESS;
+}
-- 
2.11.0



More information about the Libva mailing list