diff options
author | Pengfei Qu <Pengfei.Qu@intel.com> | 2016-12-28 13:42:28 +0800 |
---|---|---|
committer | Sean V Kelley <seanvk@posteo.de> | 2017-01-10 15:22:17 -0800 |
commit | f2c0e543fd0a195ab505eb6becffe7b2076faf39 (patch) | |
tree | 175730a5a1b6a47befb2a01fd6af8d0263d49440 | |
parent | aa3ebbb345874da6e438c4ccc86026817c746fa0 (diff) |
ENC: kernel related parameter check function for AVC encoder
Signed-off-by: Pengfei Qu <Pengfei.Qu@intel.com>
Reviewed-by: Sean V Kelley <seanvk@posteo.de>
-rwxr-xr-x | src/gen9_avc_encoder.c | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/src/gen9_avc_encoder.c b/src/gen9_avc_encoder.c index f8dc45c..04cf30f 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; +} |