/* * Copyright 2016 Rockchip Electronics Co. LTD * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define MODULE_TAG "vp8e_rc" #include #include #include "mpp_env.h" #include "mpp_mem.h" #include "mpp_common.h" #include "rc_debug.h" #include "rc_ctx.h" #include "rc_model_v2.h" #define UPSCALE 8000 static RK_S32 vp8_initial_qp(RK_S32 bits, RK_S32 pels) { RK_S32 i = -1; static const RK_S32 qp_tbl[2][12] = { {47, 57, 73, 93, 122, 155, 214, 294, 373, 506, 781, 0x7FFFFFFF}, {120, 110, 100, 90, 80, 70, 60, 50, 40, 30, 20, 10} }; if (bits > 1000000) return 10; pels >>= 8; bits >>= 5; bits *= pels + 250; bits /= 350 + (3 * pels) / 4; bits = axb_div_c(bits, UPSCALE, pels << 6); while (qp_tbl[0][++i] < bits); return qp_tbl[1][i]; } MPP_RET rc_model_v2_vp8_hal_start(void *ctx, EncRcTask *task) { RcModelV2Ctx *p = (RcModelV2Ctx *)ctx; EncFrmStatus *frm = &task->frm; EncRcTaskInfo *info = &task->info; EncRcForceCfg *force = &task->force; RcCfg *usr_cfg = &p->usr_cfg; RK_S32 mb_w = MPP_ALIGN(usr_cfg->width, 16) / 16; RK_S32 mb_h = MPP_ALIGN(usr_cfg->height, 16) / 16; RK_S32 bit_min = info->bit_min; RK_S32 bit_max = info->bit_max; RK_S32 bit_target = info->bit_target; RK_S32 quality_min = info->quality_min; RK_S32 quality_max = info->quality_max; RK_S32 quality_target = info->quality_target; rc_dbg_func("enter p %p task %p\n", p, task); rc_dbg_rc("seq_idx %d intra %d\n", frm->seq_idx, frm->is_intra); if (force->force_flag & ENC_RC_FORCE_QP) { RK_S32 qp = force->force_qp; info->quality_target = qp; info->quality_max = qp; info->quality_min = qp; return MPP_OK; } if (usr_cfg->mode == RC_FIXQP) return MPP_OK; /* setup quality parameters */ if (p->first_frm_flg && frm->is_intra) { if (info->quality_target < 0) { if (info->bit_target) { p->start_qp = vp8_initial_qp(info->bit_target, mb_w * mb_h * 16 * 16); p->cur_scale_qp = (p->start_qp) << 6; } else { mpp_log("fix qp case but init qp no set"); info->quality_target = 40; p->start_qp = 40; p->cur_scale_qp = (p->start_qp) << 6; } } else { p->start_qp = info->quality_target; p->cur_scale_qp = (p->start_qp) << 6; } if (p->reenc_cnt > 0) { p->cur_scale_qp += p->next_ratio; p->start_qp = p->cur_scale_qp >> 6; rc_dbg_rc("p->start_qp = %d, p->cur_scale_qp %d,p->next_ratio %d ", p->start_qp, p->cur_scale_qp, p->next_ratio); } else { p->start_qp -= usr_cfg->i_quality_delta; } p->cur_scale_qp = mpp_clip(p->cur_scale_qp, (info->quality_min << 6), (info->quality_max << 6)); p->pre_i_qp = p->cur_scale_qp >> 6; p->pre_p_qp = p->cur_scale_qp >> 6; } else { RK_S32 qp_scale = p->cur_scale_qp + p->next_ratio; RK_S32 start_qp = 0; RK_S32 dealt_qp = 0; if (frm->is_intra) { qp_scale = mpp_clip(qp_scale, (info->quality_min << 6), (info->quality_max << 6)); start_qp = ((p->pre_i_qp + ((qp_scale + p->next_i_ratio) >> 6)) >> 1); start_qp = mpp_clip(start_qp, info->quality_min, info->quality_max); p->pre_i_qp = start_qp; p->start_qp = start_qp; p->cur_scale_qp = qp_scale; if (usr_cfg->i_quality_delta && !p->reenc_cnt) p->start_qp -= dealt_qp; } else { qp_scale = mpp_clip(qp_scale, (info->quality_min << 6), (info->quality_max << 6)); p->cur_scale_qp = qp_scale; p->start_qp = qp_scale >> 6; if (frm->ref_mode == REF_TO_PREV_INTRA && usr_cfg->vi_quality_delta) { p->start_qp -= usr_cfg->vi_quality_delta; } } rc_dbg_rc("i_quality_delta %d, vi_quality_delta %d", dealt_qp, usr_cfg->vi_quality_delta); } p->start_qp = mpp_clip(p->start_qp, info->quality_min, info->quality_max); info->quality_target = p->start_qp; rc_dbg_rc("bitrate [%d : %d : %d] -> [%d : %d : %d]\n", bit_min, bit_target, bit_max, info->bit_min, info->bit_target, info->bit_max); rc_dbg_rc("quality [%d : %d : %d] -> [%d : %d : %d]\n", quality_min, quality_target, quality_max, info->quality_min, info->quality_target, info->quality_max); rc_dbg_func("leave %p\n", p); return MPP_OK; } const RcImplApi default_vp8e = { "default", MPP_VIDEO_CodingVP8, sizeof(RcModelV2Ctx), rc_model_v2_init, rc_model_v2_deinit, NULL, rc_model_v2_check_reenc, rc_model_v2_start, rc_model_v2_end, rc_model_v2_vp8_hal_start, rc_model_v2_hal_end, };