From ab776598eeea312b51add08a6ccb7d8ac2793e6b Mon Sep 17 00:00:00 2001 From: Zhao Yakui Date: Tue, 24 May 2016 08:00:37 -0400 Subject: [PATCH] Add the support of CBR/VBR for Vp9 Encoding Signed-off-by: Zhao Yakui Reviewed-by: Sean V Kelley --- src/gen9_vp9_encoder.c | 176 +++++++++++++++++++++++++++++++++++++++++++++---- src/gen9_vp9_encoder.h | 2 + 2 files changed, 165 insertions(+), 13 deletions(-) diff --git a/src/gen9_vp9_encoder.c b/src/gen9_vp9_encoder.c index 0351324..e6b1543 100644 --- a/src/gen9_vp9_encoder.c +++ b/src/gen9_vp9_encoder.c @@ -3858,22 +3858,170 @@ gen9_encode_vp9_check_parameter(VADriverContextP ctx, return VA_STATUS_ERROR_UNIMPLEMENTED; if (vp9_state->brc_enabled) { - if (!vp9_state->target_bit_rate && seq_param) { - vp9_state->brc_reset = 1; - vp9_state->target_bit_rate = seq_param->bits_per_second; - vp9_state->gop_size = seq_param->intra_period; + if (vp9_state->brc_flag_check & VP9_BRC_FAILURE) { + WARN_ONCE("Rate control misc_parameter is required for BRC\n"); + return VA_STATUS_ERROR_INVALID_PARAMETER; } - if (vp9_state->target_bit_rate != seq_param->bits_per_second) { - vp9_state->brc_reset = 1; - vp9_state->target_bit_rate = seq_param->bits_per_second; - } - if (vp9_state->gop_size != seq_param->intra_period) { - vp9_state->brc_reset = 1; - vp9_state->gop_size = seq_param->intra_period; + if (vp9_state->first_frame) { + unsigned int brc_flag; + VAEncMiscParameterBuffer *misc_param; + + brc_flag = VP9_BRC_SEQ | VP9_BRC_RC; + if ((vp9_state->brc_flag_check & brc_flag) != brc_flag) { + WARN_ONCE("SPS/RC misc is required for BRC\n"); + return VA_STATUS_ERROR_INVALID_PARAMETER; + } + + /* check the corresponding BRC parameter for CBR and VBR */ + if (encoder_context->rate_control_mode == VA_RC_CBR) { + vp9_state->target_bit_rate = seq_param->bits_per_second; + vp9_state->gop_size = seq_param->intra_period; + + if (vp9_state->brc_flag_check & VP9_BRC_HRD) { + VAEncMiscParameterHRD *misc_param_hrd; + + misc_param = (VAEncMiscParameterBuffer *) + encode_state->misc_param[VAEncMiscParameterTypeHRD]->buffer; + misc_param_hrd = (VAEncMiscParameterHRD *)misc_param->data; + + vp9_state->init_vbv_buffer_fullness_in_bit = misc_param_hrd->initial_buffer_fullness; + vp9_state->vbv_buffer_size_in_bit = misc_param_hrd->buffer_size; + } + + if (vp9_state->brc_flag_check & VP9_BRC_FR) { + VAEncMiscParameterFrameRate *misc_param_fr; + + misc_param = (VAEncMiscParameterBuffer *) + encode_state->misc_param[VAEncMiscParameterTypeFrameRate]->buffer; + misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data; + + vp9_state->frame_rate = misc_param_fr->framerate; + } else { + /* Assign the default frame rate */ + vp9_state->frame_rate = 30; + } + + /* RC misc will override HRD parameter */ + if (vp9_state->brc_flag_check & VP9_BRC_RC) { + VAEncMiscParameterRateControl *misc_param_rc; + + misc_param = (VAEncMiscParameterBuffer *) + encode_state->misc_param[VAEncMiscParameterTypeRateControl]->buffer; + misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data; + + vp9_state->target_bit_rate = misc_param_rc->bits_per_second; + vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) * + misc_param_rc->window_size; + vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2; + vp9_state->window_size = misc_param_rc->window_size; + } + vp9_state->max_bit_rate = vp9_state->target_bit_rate; + vp9_state->min_bit_rate = vp9_state->target_bit_rate; + } else { + /* VBR mode */ + brc_flag = VP9_BRC_SEQ | VP9_BRC_RC; + vp9_state->target_bit_rate = seq_param->bits_per_second; + vp9_state->gop_size = seq_param->intra_period; + + if (vp9_state->brc_flag_check & VP9_BRC_FR) { + VAEncMiscParameterFrameRate *misc_param_fr; + + misc_param = (VAEncMiscParameterBuffer *) + encode_state->misc_param[VAEncMiscParameterTypeFrameRate]->buffer; + misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data; + + vp9_state->frame_rate = misc_param_fr->framerate; + } else { + /* Assign the default frame rate */ + vp9_state->frame_rate = 30; + } + + if (vp9_state->brc_flag_check & VP9_BRC_RC) { + VAEncMiscParameterRateControl *misc_param_rc; + + misc_param = (VAEncMiscParameterBuffer *) + encode_state->misc_param[VAEncMiscParameterTypeRateControl]->buffer; + misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data; + + vp9_state->max_bit_rate = misc_param_rc->bits_per_second; + vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) * + misc_param_rc->window_size; + vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2; + vp9_state->target_bit_rate = (misc_param_rc->bits_per_second / 100) * + misc_param_rc->target_percentage; + vp9_state->min_bit_rate = (misc_param_rc->bits_per_second / 100) * + (2 * misc_param_rc->target_percentage - 100); + vp9_state->target_percentage = misc_param_rc->target_percentage; + vp9_state->window_size = misc_param_rc->window_size; + } + } } + else if (vp9_state->picture_coding_type == KEY_FRAME){ + VAEncMiscParameterBuffer *misc_param; + /* update the BRC parameter only when it is key-frame */ + /* If the parameter related with RC is changed. Reset BRC */ + if (vp9_state->brc_flag_check & VP9_BRC_FR) { + VAEncMiscParameterFrameRate *misc_param_fr; + + misc_param = (VAEncMiscParameterBuffer *) + encode_state->misc_param[VAEncMiscParameterTypeFrameRate]->buffer; + misc_param_fr = (VAEncMiscParameterFrameRate *)misc_param->data; + + if (vp9_state->frame_rate != misc_param_fr->framerate) { + vp9_state->brc_reset = 1; + vp9_state->frame_rate = misc_param_fr->framerate; + } + } + + /* check the GOP size. And bit_per_second in SPS is ignored */ + if (vp9_state->brc_flag_check & VP9_BRC_SEQ) { + if (vp9_state->gop_size != seq_param->intra_period) { + vp9_state->brc_reset = 1; + vp9_state->gop_size = seq_param->intra_period; + } + } - /* check Misc Rate_Control, Frame_rate buffer */ + /* update the bit_per_second */ + if (vp9_state->brc_flag_check & VP9_BRC_RC) { + VAEncMiscParameterRateControl *misc_param_rc; + + misc_param = (VAEncMiscParameterBuffer *) + encode_state->misc_param[VAEncMiscParameterTypeRateControl]->buffer; + misc_param_rc = (VAEncMiscParameterRateControl *)misc_param->data; + + if (encoder_context->rate_control_mode == VA_RC_CBR) { + if (vp9_state->target_bit_rate != misc_param_rc->bits_per_second || + vp9_state->window_size != misc_param_rc->window_size) { + vp9_state->target_bit_rate = misc_param_rc->bits_per_second; + vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) * + misc_param_rc->window_size; + vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit * 2; + vp9_state->window_size = misc_param_rc->window_size; + vp9_state->max_bit_rate = vp9_state->target_bit_rate; + vp9_state->min_bit_rate = vp9_state->target_bit_rate; + vp9_state->brc_reset = 1; + } + } else { + /* VBR mode */ + if (vp9_state->max_bit_rate != misc_param_rc->bits_per_second || + vp9_state->target_percentage != misc_param_rc->target_percentage) { + + vp9_state->target_bit_rate = (misc_param_rc->bits_per_second / 100) * + misc_param_rc->target_percentage; + vp9_state->min_bit_rate = (misc_param_rc->bits_per_second / 100) * + (2 * misc_param_rc->target_percentage - 100); + vp9_state->max_bit_rate = misc_param_rc->bits_per_second; + vp9_state->vbv_buffer_size_in_bit = (misc_param_rc->bits_per_second / 1000) * + misc_param_rc->window_size; + vp9_state->init_vbv_buffer_fullness_in_bit = vp9_state->vbv_buffer_size_in_bit / 2; + vp9_state->target_percentage = misc_param_rc->target_percentage; + vp9_state->window_size = misc_param_rc->window_size; + vp9_state->brc_reset = 1; + } + } + } + } } vp9_state->frame_width = pic_param->frame_width_dst; @@ -3960,7 +4108,8 @@ gen9_encode_vp9_check_parameter(VADriverContextP ctx, vp9_state->b16xme_enabled = 0; } - if (vp9_state->picture_coding_type && + vp9_state->mbenc_keyframe_dist_enabled = 0; + if ((vp9_state->picture_coding_type == KEY_FRAME) && vp9_state->brc_distortion_buffer_supported) vp9_state->mbenc_keyframe_dist_enabled = 1; @@ -5706,6 +5855,7 @@ gen9_vp9_pak_pipeline(VADriverContextP ctx, vp9_state->vp9_last_frame.intra_only = pic_param->pic_flags.bits.intra_only; vp9_state->frame_number++; vp9_state->curr_mv_temporal_index ^= 1; + vp9_state->first_frame = 0; return VA_STATUS_SUCCESS; } diff --git a/src/gen9_vp9_encoder.h b/src/gen9_vp9_encoder.h index 865ada1..ccc9f80 100644 --- a/src/gen9_vp9_encoder.h +++ b/src/gen9_vp9_encoder.h @@ -1927,6 +1927,8 @@ struct gen9_vp9_state { unsigned int adaptive_transform_decision_enabled; int curr_mode_decision_index; int target_usage; + int window_size; + int target_percentage; unsigned int mb_data_offset; int curr_pak_pass; unsigned int brc_flag_check; -- 2.11.0