/*
|
* 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 "rc_model_v2"
|
|
#include <math.h>
|
#include <string.h>
|
|
#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 I_WINDOW_LEN 2
|
#define P_WINDOW1_LEN 5
|
#define P_WINDOW2_LEN 8
|
|
static const RK_S32 max_i_delta_qp[51] = {
|
640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640, 640,
|
576, 576, 512, 512, 448, 448, 384, 384, 320, 320, 320, 256, 256, 256,
|
192, 192, 192, 192, 192, 128, 128, 128, 128, 128, 128, 64, 64, 64,
|
64, 64, 64, 0, 0, 0, 0, 0, 0,
|
};
|
|
RK_S32 tab_lnx[64] = {
|
-1216, -972, -830, -729, -651, -587, -533, -486,
|
-445, -408, -374, -344, -316, -290, -265, -243,
|
-221, -201, -182, -164, -147, -131, -115, -100,
|
-86, -72, -59, -46, -34, -22, -11, 0,
|
10, 21, 31, 41, 50, 60, 69, 78,
|
86, 95, 87, 103, 111, 119, 127, 134,
|
142, 149, 156, 163, 170, 177, 183, 190,
|
196, 202, 208, 214, 220, 226, 232, 237,
|
};
|
|
RK_S32 mean_qp2scale[16] = {
|
14, 15, 16, 18, 20, 22, 25, 28,
|
32, 36, 40, 44, 50, 56, 64, 72
|
};
|
const RK_S8 max_ip_qp_dealt[8] = {
|
7, 7, 6, 6, 5, 5, 4, 4
|
};
|
RK_U32 bit2percent[100] = {
|
99, 99, 99, 99, 99, 99, 99, 99, 99, 99,
|
99, 95, 90, 85, 80, 75, 72, 69, 66, 64,
|
62, 59, 58, 57, 56, 55, 54, 53, 52, 51,
|
50, 49, 48, 47, 47, 46, 46, 45, 45, 44,
|
44, 43, 43, 43, 42, 42, 42, 41, 41, 41,
|
40, 40, 40, 39, 39, 39, 38, 38, 38, 37,
|
37, 37, 37, 37, 37, 37, 36, 36, 36, 36,
|
36, 36, 36, 35, 35, 35, 34, 34, 34, 34,
|
34, 33, 33, 33, 33, 33, 33, 33, 33, 33,
|
32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
|
};
|
|
RK_S8 intra_qp_map[8] = {
|
0, 0, 1, 1, 2, 2, 2, 2,
|
};
|
|
MPP_RET bits_model_param_deinit(RcModelV2Ctx *ctx)
|
{
|
rc_dbg_func("enter %p\n", ctx);
|
|
if (ctx->i_bit != NULL) {
|
mpp_data_deinit_v2(ctx->i_bit);
|
ctx->i_bit = NULL;
|
}
|
|
if (ctx->p_bit != NULL) {
|
mpp_data_deinit_v2(ctx->p_bit);
|
ctx->p_bit = NULL;
|
}
|
|
if (ctx->vi_bit != NULL) {
|
mpp_data_deinit_v2(ctx->vi_bit);
|
ctx->vi_bit = NULL;
|
}
|
|
if (ctx->pre_p_bit != NULL) {
|
mpp_data_deinit_v2(ctx->pre_p_bit);
|
ctx->pre_p_bit = NULL;
|
}
|
|
if (ctx->pre_i_bit != NULL) {
|
mpp_data_deinit_v2(ctx->pre_i_bit);
|
ctx->pre_i_bit = NULL;
|
}
|
|
if (ctx->pre_i_mean_qp != NULL) {
|
mpp_data_deinit_v2(ctx->pre_i_mean_qp);
|
ctx->pre_i_mean_qp = NULL;
|
}
|
|
if (ctx->madi != NULL) {
|
mpp_data_deinit_v2(ctx->madi);
|
ctx->madi = NULL;
|
}
|
if (ctx->madp != NULL) {
|
mpp_data_deinit_v2(ctx->madp);
|
ctx->madp = NULL;
|
}
|
|
if (ctx->stat_rate != NULL) {
|
mpp_data_deinit_v2(ctx->stat_rate);
|
ctx->stat_rate = NULL;
|
}
|
|
if (ctx->stat_bits != NULL) {
|
mpp_data_deinit_v2(ctx->stat_bits);
|
ctx->stat_bits = NULL;
|
}
|
if (ctx->gop_bits != NULL) {
|
mpp_data_deinit_v2(ctx->gop_bits);
|
ctx->gop_bits = NULL;
|
}
|
rc_dbg_func("leave %p\n", ctx);
|
return MPP_OK;
|
}
|
|
MPP_RET bits_model_param_init(RcModelV2Ctx *ctx)
|
{
|
RK_S32 gop_len = ctx->usr_cfg.igop;
|
RcFpsCfg *fps = &ctx->usr_cfg.fps;
|
RK_U32 stat_len = fps->fps_out_num * ctx->usr_cfg.stats_time / fps->fps_out_denorm;
|
stat_len = stat_len ? stat_len : 1;
|
|
bits_model_param_deinit(ctx);
|
mpp_data_init_v2(&ctx->i_bit, I_WINDOW_LEN, 0);
|
if (ctx->i_bit == NULL) {
|
mpp_err("i_bit init fail");
|
return MPP_ERR_MALLOC;
|
}
|
|
mpp_data_init_v2(&ctx->vi_bit, I_WINDOW_LEN, 0);
|
if (ctx->vi_bit == NULL) {
|
mpp_err("vi_bit init fail");
|
return MPP_ERR_MALLOC;
|
}
|
mpp_data_init_v2(&ctx->p_bit, P_WINDOW1_LEN, 0);
|
if (ctx->p_bit == NULL) {
|
mpp_err("p_bit init fail");
|
return MPP_ERR_MALLOC;
|
}
|
|
mpp_data_init_v2(&ctx->pre_p_bit, P_WINDOW2_LEN, 0);
|
if (ctx->pre_p_bit == NULL) {
|
mpp_err("pre_p_bit init fail");
|
return MPP_ERR_MALLOC;
|
}
|
|
mpp_data_init_v2(&ctx->pre_i_bit, I_WINDOW_LEN, 0);
|
if (ctx->pre_i_bit == NULL) {
|
mpp_err("pre_i_bit init fail");
|
return MPP_ERR_MALLOC;
|
}
|
|
mpp_data_init_v2(&ctx->pre_i_mean_qp, I_WINDOW_LEN, -1);
|
if (ctx->pre_i_mean_qp == NULL) {
|
mpp_err("pre_i_mean_qp init fail");
|
return MPP_ERR_MALLOC;
|
}
|
mpp_data_init_v2(&ctx->madi, P_WINDOW2_LEN, 0);
|
if (ctx->madi == NULL) {
|
mpp_err("madi init fail");
|
return MPP_ERR_MALLOC;
|
}
|
mpp_data_init_v2(&ctx->madp, P_WINDOW2_LEN, 0);
|
if (ctx->madp == NULL) {
|
mpp_err("madp init fail");
|
return MPP_ERR_MALLOC;
|
}
|
mpp_data_init_v2(&ctx->stat_rate, fps->fps_out_num, 0);
|
if (ctx->stat_rate == NULL) {
|
mpp_err("stat_rate init fail fps_out_num %d", fps->fps_out_num);
|
return MPP_ERR_MALLOC;
|
}
|
|
mpp_data_init_v2(&ctx->stat_bits, stat_len, ctx->bit_per_frame);
|
if (ctx->stat_bits == NULL) {
|
mpp_err("stat_bits init fail stat_len %d", stat_len);
|
return MPP_ERR_MALLOC;
|
}
|
|
mpp_data_init_v2(&ctx->gop_bits, gop_len, 0);
|
if (ctx->gop_bits == NULL) {
|
mpp_err("gop_bits init fail gop_len %d", gop_len);
|
return MPP_ERR_MALLOC;
|
}
|
return MPP_OK;
|
}
|
|
void bits_frm_init(RcModelV2Ctx *ctx)
|
{
|
RcCfg *usr_cfg = &ctx->usr_cfg;
|
RK_U32 gop_len = usr_cfg->igop;
|
RK_U32 p_bit = 0;
|
|
rc_dbg_func("enter %p\n", ctx);
|
|
switch (usr_cfg->gop_mode) {
|
case NORMAL_P: {
|
ctx->i_scale = ctx->usr_cfg.init_ip_ratio;
|
ctx->p_scale = 16;
|
if (gop_len <= 1)
|
p_bit = ctx->gop_total_bits * 16;
|
else
|
p_bit = ctx->gop_total_bits * 16 / (ctx->i_scale + ctx->p_scale * (gop_len - 1));
|
mpp_data_reset_v2(ctx->p_bit, p_bit);
|
ctx->p_sumbits = 5 * p_bit;
|
mpp_data_reset_v2(ctx->i_bit, p_bit * ctx->i_scale / 16);
|
ctx->i_sumbits = 2 * p_bit * ctx->i_scale / 16;
|
} break;
|
case SMART_P: {
|
RK_U32 vi_num = 0;
|
mpp_assert(usr_cfg->vgop > 1);
|
ctx->i_scale = 320;
|
ctx->p_scale = 16;
|
ctx->vi_scale = 32;
|
vi_num = gop_len / usr_cfg->vgop;
|
if (vi_num > 0) {
|
vi_num = vi_num - 1;
|
}
|
p_bit = ctx->gop_total_bits * 16 / (ctx->i_scale + ctx->vi_scale * vi_num + ctx->p_scale * (gop_len - vi_num));
|
mpp_data_reset_v2(ctx->p_bit, p_bit);
|
ctx->p_sumbits = 5 * p_bit;
|
|
mpp_data_reset_v2(ctx->i_bit, p_bit * ctx->i_scale / 16);
|
ctx->i_sumbits = 2 * p_bit * ctx->i_scale / 16;
|
|
mpp_data_reset_v2(ctx->vi_bit, p_bit * ctx->vi_scale / 16);
|
ctx->vi_sumbits = 2 * p_bit * ctx->vi_scale / 16;
|
} break;
|
default:
|
break;
|
}
|
rc_dbg_rc("p_sumbits %d i_sumbits %d vi_sumbits %d\n", ctx->p_sumbits, ctx->i_sumbits, ctx->vi_sumbits);
|
rc_dbg_func("leave %p\n", ctx);
|
}
|
|
RK_S32 moving_judge_update(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg)
|
{
|
switch (cfg->frame_type) {
|
case INTRA_FRAME: {
|
mpp_data_update_v2(ctx->pre_i_bit, cfg->bit_real);
|
mpp_data_update_v2(ctx->pre_i_mean_qp, cfg->quality_real);
|
} break;
|
|
case INTER_P_FRAME: {
|
mpp_data_update_v2(ctx->pre_p_bit, cfg->bit_real);
|
mpp_data_update_v2(ctx->madp, cfg->madp);
|
} break;
|
|
default:
|
break;
|
}
|
return 0;
|
}
|
|
void bit_statics_update(RcModelV2Ctx *ctx, RK_U32 real_bit)
|
{
|
RK_S32 mean_pbits, mean_ibits;
|
RcCfg *usr_cfg = &ctx->usr_cfg;
|
RK_U32 gop_len = usr_cfg->igop;
|
|
mpp_data_update_v2(ctx->gop_bits, real_bit);
|
mean_pbits = mpp_data_mean_v2(ctx->pre_p_bit);
|
mean_ibits = mpp_data_mean_v2(ctx->pre_i_bit);
|
ctx->real_gbits = mpp_data_sum_v2(ctx->gop_bits);
|
ctx->avg_gbits = (gop_len - 1) * (RK_S64)mean_pbits + mean_ibits;
|
}
|
|
MPP_RET bits_model_preset(RcModelV2Ctx *ctx, EncRcTaskInfo *info)
|
{
|
RcCfg *usr_cfg = &ctx->usr_cfg;
|
RK_S32 preset_bit = info->bit_target;
|
RK_S32 water_level = 0;
|
|
mpp_data_preset_v2(ctx->stat_rate, preset_bit != 0);
|
mpp_data_preset_v2(ctx->stat_bits, preset_bit);
|
|
ctx->ins_bps = mpp_data_sum_v2(ctx->stat_bits) / usr_cfg->stats_time;
|
if (preset_bit + ctx->stat_watl > ctx->watl_thrd)
|
water_level = ctx->watl_thrd - ctx->bit_per_frame;
|
else
|
water_level = preset_bit + ctx->stat_watl - ctx->bit_per_frame;
|
|
if (water_level < 0) {
|
water_level = 0;
|
}
|
ctx->stat_watl = water_level;
|
switch (info->frame_type) {
|
case INTRA_FRAME : {
|
mpp_data_preset_v2(ctx->i_bit, preset_bit);
|
ctx->i_sumbits = mpp_data_sum_v2(ctx->i_bit);
|
ctx->i_scale = 80 * ctx->i_sumbits / (2 * ctx->p_sumbits);
|
rc_dbg_rc("i_sumbits %d p_sumbits %d i_scale %d\n",
|
ctx->i_sumbits, ctx->p_sumbits, ctx->i_scale);
|
} break;
|
case INTER_P_FRAME : {
|
mpp_data_preset_v2(ctx->p_bit, preset_bit);
|
ctx->p_sumbits = mpp_data_sum_v2(ctx->p_bit);
|
|
/* Avoid div zero when P frame successive drop */
|
if (!ctx->p_sumbits)
|
ctx->p_sumbits = 1;
|
|
ctx->p_scale = 16;
|
} break;
|
case INTER_VI_FRAME : {
|
mpp_data_preset_v2(ctx->vi_bit, preset_bit);
|
ctx->vi_sumbits = mpp_data_sum_v2(ctx->vi_bit);
|
ctx->vi_scale = 80 * ctx->vi_sumbits / (2 * ctx->p_sumbits);
|
/* NOTE: vi_scale may be set to zero. So we should limit the range */
|
ctx->vi_scale = mpp_clip(ctx->vi_scale, 16, 320);
|
} break;
|
default : {
|
} break;
|
}
|
return MPP_OK;
|
}
|
|
MPP_RET bits_model_update(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg)
|
{
|
RcCfg *usr_cfg = &ctx->usr_cfg;
|
RK_S32 real_bit = cfg->bit_real;
|
RK_U32 madi = cfg->madi;
|
RK_S32 water_level = 0;
|
|
rc_dbg_func("enter %p\n", ctx);
|
|
mpp_data_update_v2(ctx->stat_rate, real_bit != 0);
|
mpp_data_update_v2(ctx->stat_bits, real_bit);
|
|
ctx->ins_bps = mpp_data_sum_v2(ctx->stat_bits) / usr_cfg->stats_time;
|
if (real_bit + ctx->stat_watl > ctx->watl_thrd)
|
water_level = ctx->watl_thrd - ctx->bit_per_frame;
|
else
|
water_level = real_bit + ctx->stat_watl - ctx->bit_per_frame;
|
|
if (water_level < 0)
|
water_level = 0;
|
|
ctx->stat_watl = water_level;
|
|
switch (cfg->frame_type) {
|
case INTRA_FRAME : {
|
mpp_data_update_v2(ctx->i_bit, real_bit);
|
ctx->i_sumbits = mpp_data_sum_v2(ctx->i_bit);
|
ctx->i_scale = 80 * ctx->i_sumbits / (2 * ctx->p_sumbits);
|
rc_dbg_rc("i_sumbits %d p_sumbits %d i_scale %d\n",
|
ctx->i_sumbits, ctx->p_sumbits, ctx->i_scale);
|
} break;
|
case INTER_P_FRAME : {
|
mpp_data_update_v2(ctx->p_bit, real_bit);
|
mpp_data_update_v2(ctx->madi, madi);
|
ctx->p_sumbits = mpp_data_sum_v2(ctx->p_bit);
|
|
/* Avoid div zero when P frame successive drop */
|
if (!ctx->p_sumbits)
|
ctx->p_sumbits = 1;
|
|
ctx->p_scale = 16;
|
} break;
|
case INTER_VI_FRAME: {
|
mpp_data_update_v2(ctx->vi_bit, real_bit);
|
ctx->vi_sumbits = mpp_data_sum_v2(ctx->vi_bit);
|
ctx->vi_scale = 80 * ctx->vi_sumbits / (2 * ctx->p_sumbits);
|
/* NOTE: vi_scale may be set to zero. So we should limit the range */
|
ctx->vi_scale = mpp_clip(ctx->vi_scale, 16, 320);
|
} break;
|
default : {
|
} break;
|
}
|
|
rc_dbg_func("leave %p\n", ctx);
|
return MPP_OK;
|
}
|
|
MPP_RET bits_model_alloc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg, RK_S64 total_bits)
|
{
|
RcCfg *usr_cfg = &ctx->usr_cfg;
|
RK_U32 max_i_prop = usr_cfg->max_i_bit_prop * 16;
|
RK_S32 gop_len = usr_cfg->igop;
|
RK_S32 i_scale = ctx->i_scale;
|
RK_S32 vi_scale = ctx->vi_scale;
|
RK_S32 alloc_bits = 0;
|
RK_S32 super_bit_thr = 0x7fffffff;
|
|
ctx->i_scale = 80 * ctx->i_sumbits / (2 * ctx->p_sumbits);
|
i_scale = ctx->i_scale;
|
|
rc_dbg_func("enter %p\n", ctx);
|
rc_dbg_rc("frame_type %d max_i_prop %d i_scale %d total_bits %lld\n",
|
cfg->frame_type, max_i_prop, i_scale, total_bits);
|
if (usr_cfg->super_cfg.super_mode) {
|
super_bit_thr = usr_cfg->super_cfg.super_p_thd;
|
}
|
if (usr_cfg->gop_mode == SMART_P) {
|
RK_U32 vi_num = 0;
|
mpp_assert(usr_cfg->vgop > 1);
|
vi_num = gop_len / usr_cfg->vgop;
|
if (vi_num > 0) {
|
vi_num = vi_num - 1;
|
}
|
switch (cfg->frame_type) {
|
case INTRA_FRAME: {
|
i_scale = mpp_clip(i_scale, 16, 16000);
|
total_bits = total_bits * i_scale;
|
if (usr_cfg->super_cfg.super_mode) {
|
super_bit_thr = usr_cfg->super_cfg.super_i_thd;
|
}
|
} break;
|
|
case INTER_P_FRAME: {
|
i_scale = mpp_clip(i_scale, 16, max_i_prop);
|
total_bits = total_bits * 16;
|
} break;
|
case INTER_VI_FRAME: {
|
i_scale = mpp_clip(i_scale, 16, max_i_prop);
|
total_bits = total_bits * vi_scale;
|
} break;
|
default:
|
break;
|
}
|
|
alloc_bits = total_bits / (i_scale + 16 * (gop_len - vi_num) + vi_num * vi_scale);
|
|
if (!alloc_bits) {
|
mpp_log_f("found zero alloc bits\n");
|
mpp_log_f("total_bits %lld, i_scale %d, gop_len %d, vi_num %d, vi_scale %d",
|
total_bits, i_scale, gop_len, vi_num, vi_scale);
|
mpp_log_f("gop_total_bits %lld, i_sumbits %d, p_sumbits %d, vgop %d igop %d",
|
ctx->gop_total_bits, ctx->i_sumbits, ctx->p_sumbits, usr_cfg->vgop, usr_cfg->igop);
|
}
|
} else {
|
switch (cfg->frame_type) {
|
case INTRA_FRAME: {
|
i_scale = mpp_clip(i_scale, 16, 16000);
|
total_bits = total_bits * i_scale;
|
if (usr_cfg->super_cfg.super_mode) {
|
super_bit_thr = usr_cfg->super_cfg.super_i_thd;
|
}
|
} break;
|
|
case INTER_P_FRAME: {
|
i_scale = mpp_clip(i_scale, 16, max_i_prop);
|
total_bits = total_bits * 16;
|
} break;
|
default:
|
break;
|
}
|
if (gop_len > 1) {
|
alloc_bits = total_bits / (i_scale + 16 * (gop_len - 1));
|
} else {
|
alloc_bits = total_bits / i_scale;
|
}
|
}
|
rc_dbg_rc("i_scale %d, total_bits %lld", i_scale, total_bits);
|
if (alloc_bits > super_bit_thr &&
|
(usr_cfg->super_cfg.rc_priority == MPP_ENC_RC_BY_FRM_SIZE_FIRST)) {
|
alloc_bits = super_bit_thr - (super_bit_thr >> 4);
|
rc_dbg_rc("alloc bits max then super_bit_thr %d", super_bit_thr);
|
}
|
|
ctx->cur_super_thd = super_bit_thr;
|
cfg->bit_target = alloc_bits;
|
|
mpp_assert(alloc_bits);
|
|
rc_dbg_func("leave %p\n", ctx);
|
return MPP_OK;
|
}
|
|
MPP_RET calc_next_i_ratio(RcModelV2Ctx *ctx)
|
{
|
RcCfg *usr_cfg = &ctx->usr_cfg;
|
RK_S32 max_i_prop = usr_cfg->max_i_bit_prop * 16;
|
RK_S32 gop_len = usr_cfg->igop;
|
RK_S32 pre_qp = ctx->pre_i_qp;
|
RK_S32 bits_alloc;
|
|
rc_dbg_func("enter %p\n", ctx);
|
if (gop_len > 1) {
|
bits_alloc = ctx->gop_total_bits * max_i_prop / (max_i_prop + 16 * (gop_len - 1));
|
} else {
|
bits_alloc = ctx->gop_total_bits * max_i_prop / max_i_prop;
|
}
|
|
if (ctx->pre_real_bits > bits_alloc || ctx->next_i_ratio) {
|
RK_S32 ratio = ((ctx->pre_real_bits - bits_alloc) << 8) / bits_alloc;
|
|
ratio = mpp_clip(ratio, -256, 256);
|
ratio = ctx->next_i_ratio + ratio;
|
if (ratio >= 0) {
|
if (ratio > max_i_delta_qp[pre_qp])
|
ratio = max_i_delta_qp[pre_qp];
|
} else {
|
ratio = 0;
|
}
|
ctx->next_i_ratio = ratio;
|
rc_dbg_rc("ctx->next_i_ratio %d", ctx->next_i_ratio);
|
}
|
|
rc_dbg_func("leave %p\n", ctx);
|
return MPP_OK;
|
|
}
|
|
MPP_RET calc_debreath_qp(RcModelV2Ctx *ctx)
|
{
|
rc_dbg_func("enter %p\n", ctx);
|
RcDebreathCfg *debreath_cfg = &ctx->usr_cfg.debreath_cfg;
|
RK_S32 qp_start_sum = 0;
|
RK_S32 new_start_qp = 0;
|
RK_U8 idx2 = MPP_MIN(ctx->pre_iblk4_prop >> 5, (RK_S32)sizeof(intra_qp_map) - 1);
|
|
static RK_S8 strength_map[36] = {
|
0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4,
|
5, 5, 5, 6, 6, 6, 7, 7, 7, 8, 8, 8,
|
9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12
|
};
|
|
qp_start_sum = MPP_MIN(ctx->gop_qp_sum / ctx->gop_frm_cnt, (RK_S32)sizeof(strength_map) - 1);
|
|
rc_dbg_qp("i start_qp %d, qp_start_sum = %d, intra_lv4_prop %d",
|
ctx->start_qp, qp_start_sum, ctx->pre_iblk4_prop);
|
|
RK_S32 dealt_qp = strength_map[debreath_cfg->strength] - intra_qp_map[idx2];
|
if (qp_start_sum > dealt_qp)
|
new_start_qp = qp_start_sum - dealt_qp;
|
else
|
new_start_qp = qp_start_sum;
|
|
ctx->start_qp = mpp_clip(new_start_qp, ctx->usr_cfg.min_i_quality, ctx->usr_cfg.max_i_quality);
|
|
rc_dbg_func("leave %p\n", ctx);
|
return MPP_OK;
|
}
|
|
MPP_RET calc_cbr_ratio(void *ctx, EncRcTaskInfo *cfg)
|
{
|
RcModelV2Ctx *p = (RcModelV2Ctx *)ctx;
|
RK_S32 target_bps = p->target_bps;
|
RK_S32 ins_bps = p->ins_bps;
|
RK_S32 pre_target_bits = p->pre_target_bits;
|
RK_S32 pre_real_bits = p->pre_real_bits;
|
RK_S32 pre_ins_bps = p->last_inst_bps;
|
RK_S32 idx1, idx2;
|
RK_S32 bit_diff_ratio, ins_ratio, bps_ratio, wl_ratio;
|
RK_S32 fluc_l = 3;
|
|
rc_dbg_func("enter %p\n", p);
|
|
rc_dbg_bps("%10s|%10s|%10s|%10s|%10s|%8s", "r_bits", "t_bits", "ins_bps", "p_ins_bps", "target_bps", "watl");
|
rc_dbg_bps("%10d %10d %10d %10d %10d %8d", pre_real_bits, pre_target_bits, ins_bps, pre_ins_bps, target_bps, p->stat_watl >> 10);
|
|
bits_model_alloc(p, cfg, p->gop_total_bits);
|
|
mpp_assert(target_bps > 0);
|
|
if (pre_target_bits > pre_real_bits)
|
bit_diff_ratio = 52 * (pre_real_bits - pre_target_bits) / pre_target_bits;
|
else
|
bit_diff_ratio = 64 * (pre_real_bits - pre_target_bits) / pre_target_bits;
|
|
idx1 = (ins_bps << 5) / target_bps;
|
idx2 = (pre_ins_bps << 5) / target_bps;
|
|
idx1 = mpp_clip(idx1, 0, 63);
|
idx2 = mpp_clip(idx2, 0, 63);
|
ins_ratio = tab_lnx[idx1] - tab_lnx[idx2]; // %3
|
|
/*ins_bps is increase and pre_ins > target_bps*15/16 will raise up ins_ratio to decrease bit
|
*ins_bps is decresase and pre_ins < target_bps*17/16 will decrease ins_ratio to increase bit
|
*/
|
|
if (ins_bps > pre_ins_bps && target_bps - pre_ins_bps < (target_bps >> 4)) { // %6
|
ins_ratio = 6 * ins_ratio;
|
} else if ( ins_bps < pre_ins_bps && pre_ins_bps - target_bps < (target_bps >> 4)) {
|
ins_ratio = 4 * ins_ratio;
|
} else {
|
ins_ratio = 0;
|
}
|
|
bit_diff_ratio = mpp_clip(bit_diff_ratio, -128, 256);
|
|
ins_ratio = mpp_clip(ins_ratio, -128, 256);
|
|
bps_ratio = (ins_bps - target_bps) * fluc_l / (target_bps >> 4);
|
wl_ratio = 4 * (p->stat_watl - p->watl_base) * fluc_l / p->watl_base;
|
bps_ratio = mpp_clip(bps_ratio, -32, 32);
|
wl_ratio = mpp_clip(wl_ratio, -16, 32);
|
p->next_ratio = bit_diff_ratio + ins_ratio + bps_ratio + wl_ratio;
|
|
rc_dbg_qp("%10s|%10s|%10s|%10s|%10s|%10s", "diff_ratio", "ins_ratio", "bps_ratio",
|
"wl_ratio", "next_ratio", "cur_qp_s");
|
rc_dbg_qp("%10d %10d %10d %10d %10d|%10d", bit_diff_ratio, ins_ratio - bit_diff_ratio,
|
bps_ratio, wl_ratio, p->next_ratio, p->cur_scale_qp);
|
|
rc_dbg_func("leave %p\n", p);
|
return MPP_OK;
|
}
|
|
MPP_RET reenc_calc_super_frm_ratio(void *ctx, EncRcTaskInfo *cfg)
|
{
|
RcModelV2Ctx *p = (RcModelV2Ctx *)ctx;
|
|
rc_dbg_func("enter %p\n", p);
|
p->next_ratio = 160 * (4 * (cfg->bit_real - p->cur_super_thd) / cfg->bit_target);
|
p->next_ratio = mpp_clip(p->next_ratio, 128, 640);
|
rc_dbg_func("leave %p\n", p);
|
return MPP_OK;
|
}
|
|
MPP_RET reenc_calc_cbr_ratio(void *ctx, EncRcTaskInfo *cfg)
|
{
|
RcModelV2Ctx *p = (RcModelV2Ctx *)ctx;
|
RcCfg *usr_cfg = &p->usr_cfg;
|
RK_S32 stat_time = usr_cfg->stats_time;
|
RK_S32 pre_ins_bps = mpp_data_sum_v2(p->stat_bits) / stat_time;
|
RK_S32 ins_bps = (pre_ins_bps * stat_time - mpp_data_get_pre_val_v2(p->stat_bits, -1) + cfg->bit_real) / stat_time;
|
RK_S32 real_bit = cfg->bit_real;
|
RK_S32 target_bit = cfg->bit_target;
|
RK_S32 target_bps = p->target_bps;
|
RK_S32 water_level = 0;
|
RK_S32 idx1, idx2;
|
RK_S32 bit_diff_ratio, ins_ratio, bps_ratio, wl_ratio;
|
RK_S32 mb_w = MPP_ALIGN(usr_cfg->width, 16) / 16;
|
RK_S32 mb_h = MPP_ALIGN(usr_cfg->height, 16) / 16;
|
|
rc_dbg_func("enter %p\n", p);
|
|
if (p->cur_super_thd <= cfg->bit_real &&
|
usr_cfg->super_cfg.rc_priority == MPP_ENC_RC_BY_FRM_SIZE_FIRST) {
|
return reenc_calc_super_frm_ratio(ctx, cfg);
|
}
|
|
if (real_bit + p->stat_watl > p->watl_thrd)
|
water_level = p->watl_thrd - p->bit_per_frame;
|
else
|
water_level = real_bit + p->stat_watl - p->bit_per_frame;
|
|
if (water_level < 0) {
|
water_level = 0;
|
}
|
|
if (target_bit > real_bit)
|
bit_diff_ratio = 32 * (real_bit - target_bit) / real_bit;
|
else
|
bit_diff_ratio = 32 * (real_bit - target_bit) / target_bit;
|
|
idx1 = ins_bps / (target_bps >> 5);
|
idx2 = pre_ins_bps / (target_bps >> 5);
|
|
idx1 = mpp_clip(idx1, 0, 63);
|
idx2 = mpp_clip(idx2, 0, 63);
|
ins_ratio = tab_lnx[idx1] - tab_lnx[idx2];
|
|
bps_ratio = 96 * (ins_bps - target_bps) / target_bps;
|
wl_ratio = 32 * (water_level - p->watl_base) / p->watl_base;
|
if (pre_ins_bps < ins_bps && target_bps != pre_ins_bps) {
|
ins_ratio = 6 * ins_ratio;
|
ins_ratio = mpp_clip(ins_ratio, -192, 256);
|
} else {
|
if (cfg->frame_type == INTRA_FRAME) {
|
ins_ratio = 3 * ins_ratio;
|
ins_ratio = mpp_clip(ins_ratio, -192, 256);
|
} else {
|
ins_ratio = 0;
|
}
|
}
|
|
bit_diff_ratio = mpp_clip(bit_diff_ratio, -128, 256);
|
bps_ratio = mpp_clip(bps_ratio, -32, 32);
|
wl_ratio = mpp_clip(wl_ratio, -32, 32);
|
p->next_ratio = bit_diff_ratio + ins_ratio + bps_ratio + wl_ratio;
|
if (cfg->frame_type == INTRA_FRAME && (cfg->madi > 0)) {
|
RK_U32 tar_bpp = target_bit / (mb_w * mb_h);
|
float lnb_t = log(tar_bpp);
|
float c = 6.7204, a = -0.1435, b = 0.0438;
|
float start_qp = (p->cur_scale_qp >> 6);
|
int qp_c = ((lnb_t - cfg->madi * b - c) / a + 14);
|
if (qp_c > start_qp)
|
p->next_ratio = (qp_c << 6) - p->cur_scale_qp;
|
}
|
rc_dbg_rc("cbr target_bit %d real_bit %d reenc next ratio %d", target_bit, real_bit, p->next_ratio);
|
rc_dbg_func("leave %p\n", p);
|
return MPP_OK;
|
}
|
|
void rc_hier_calc_dealt_qp(RcModelV2Ctx *p, EncRcTaskInfo *info)
|
{
|
RcHierQPCfg *hier_qp_cfg = &p->usr_cfg.hier_qp_cfg;
|
|
if (!hier_qp_cfg->hier_qp_en)
|
return;
|
|
if (info->frame_type == INTRA_FRAME || info->frame_type == INTER_VI_FRAME) {
|
p->hier_frm_cnt[3] = 0;
|
p->hier_frm_cnt[2] = 0;
|
p->hier_frm_cnt[1] = 0;
|
p->hier_frm_cnt[0] = 0;
|
p->qp_layer_id = 0;
|
} else {
|
if (p->hier_frm_cnt[3] < hier_qp_cfg->hier_frame_num[3]) {
|
p->hier_frm_cnt[3]++;
|
p->qp_layer_id = 4;
|
} else if (p->hier_frm_cnt[2] < hier_qp_cfg->hier_frame_num[2]) {
|
p->hier_frm_cnt[2]++;
|
p->hier_frm_cnt[3] = 0;
|
p->qp_layer_id = 3;
|
} else if (p->hier_frm_cnt[1] < hier_qp_cfg->hier_frame_num[1]) {
|
p->hier_frm_cnt[1]++;
|
p->hier_frm_cnt[3] = 0;
|
p->hier_frm_cnt[2] = 0;
|
p->qp_layer_id = 2;
|
} else if (p->hier_frm_cnt[0] < hier_qp_cfg->hier_frame_num[0]) {
|
p->hier_frm_cnt[0]++;
|
p->hier_frm_cnt[3] = 0;
|
p->hier_frm_cnt[2] = 0;
|
p->hier_frm_cnt[1] = 0;
|
p->qp_layer_id = 1;
|
} else {
|
p->hier_frm_cnt[3] = 0;
|
p->hier_frm_cnt[2] = 0;
|
p->hier_frm_cnt[1] = 0;
|
p->hier_frm_cnt[0] = 0;
|
p->qp_layer_id = 0;
|
}
|
}
|
|
return;
|
}
|
|
MPP_RET calc_vbr_ratio(void *ctx, EncRcTaskInfo *cfg)
|
{
|
RcModelV2Ctx *p = (RcModelV2Ctx *)ctx;
|
RcCfg *usr_cfg = &p->usr_cfg;
|
RK_S32 bps_change = p->target_bps;
|
RK_S32 max_bps_target = usr_cfg->bps_max;
|
RK_S32 ins_bps = p->ins_bps;
|
RK_S32 pre_target_bits = p->pre_target_bits;
|
RK_S32 pre_real_bits = p->pre_real_bits;
|
RK_S32 pre_ins_bps = p->last_inst_bps;
|
|
RK_S32 idx1, idx2;
|
RK_S32 bit_diff_ratio, ins_ratio, bps_ratio;
|
|
rc_dbg_func("enter %p\n", p);
|
|
bits_model_alloc(p, cfg, p->gop_total_bits);
|
if (pre_target_bits > pre_real_bits)
|
bit_diff_ratio = 32 * (pre_real_bits - pre_target_bits) / pre_target_bits;
|
else
|
bit_diff_ratio = 64 * (pre_real_bits - pre_target_bits) / pre_target_bits;
|
|
idx1 = ins_bps / (max_bps_target >> 5);
|
idx2 = pre_ins_bps / (max_bps_target >> 5);
|
|
idx1 = mpp_clip(idx1, 0, 63);
|
idx2 = mpp_clip(idx2, 0, 63);
|
ins_ratio = tab_lnx[idx1] - tab_lnx[idx2];
|
|
rc_dbg_bps("%10s|%10s|%10s|%10s|%10s|%10s", "r_bits", "t_bits", "ins_bps", "p_ins_bps",
|
"bps_ch", "max_bps");
|
rc_dbg_bps("%10d %10d %10d %10d %10d %10d", pre_real_bits, pre_target_bits, ins_bps,
|
pre_ins_bps, bps_change, max_bps_target);
|
|
|
if (ins_bps > bps_change && ins_bps > pre_ins_bps) {
|
ins_ratio = 6 * ins_ratio;
|
} else if (ins_bps <= pre_ins_bps && bps_change > pre_ins_bps) {
|
ins_ratio = 3 * ins_ratio;
|
} else {
|
ins_ratio = 0;
|
}
|
|
bit_diff_ratio = mpp_clip(bit_diff_ratio, -128, 256);
|
ins_ratio = mpp_clip(ins_ratio, -128, 256);
|
bps_ratio = 3 * (ins_bps - bps_change) / (max_bps_target >> 4);
|
bps_ratio = mpp_clip(bps_ratio, -16, 32);
|
if (p->i_scale > 640) {
|
bit_diff_ratio = mpp_clip(bit_diff_ratio, -16, 32);
|
ins_ratio = mpp_clip(ins_ratio, -16, 32);
|
}
|
|
p->next_ratio = bit_diff_ratio + ins_ratio + bps_ratio;
|
|
rc_dbg_qp("%10s|%10s|%10s|%10s|%10s", "diff_ratio", "ins_ratio", "bps_ratio", "next_ratio", "cur_qp_s");
|
rc_dbg_qp("%10d %10d %10d %10d|%10d", bit_diff_ratio, ins_ratio, bps_ratio, p->next_ratio, p->cur_scale_qp);
|
rc_dbg_func("leave %p\n", p);
|
return MPP_OK;
|
}
|
|
MPP_RET reenc_calc_vbr_ratio(void *ctx, EncRcTaskInfo *cfg)
|
{
|
|
RcModelV2Ctx *p = (RcModelV2Ctx *)ctx;
|
RcCfg *usr_cfg = &p->usr_cfg;
|
RK_S32 stat_time = usr_cfg->stats_time;
|
RK_S32 pre_ins_bps = mpp_data_sum_v2(p->stat_bits) / stat_time;
|
RK_S32 ins_bps = (pre_ins_bps * stat_time - mpp_data_get_pre_val_v2(p->stat_bits, -1) + cfg->bit_real) / stat_time;
|
RK_S32 bps_change = p->target_bps;
|
RK_S32 max_bps_target = usr_cfg->bps_max;
|
|
RK_S32 real_bit = cfg->bit_real;
|
RK_S32 target_bit = cfg->bit_target;
|
RK_S32 idx1, idx2;
|
RK_S32 bit_diff_ratio, ins_ratio, bps_ratio;
|
|
rc_dbg_func("enter %p\n", p);
|
|
if (p->cur_super_thd <= cfg->bit_real &&
|
usr_cfg->super_cfg.rc_priority == MPP_ENC_RC_BY_FRM_SIZE_FIRST) {
|
return reenc_calc_super_frm_ratio(ctx, cfg);
|
}
|
|
if (target_bit <= real_bit)
|
bit_diff_ratio = 32 * (real_bit - target_bit) / target_bit;
|
else
|
bit_diff_ratio = 32 * (real_bit - target_bit) / real_bit;
|
|
idx1 = ins_bps / (max_bps_target >> 5);
|
idx2 = pre_ins_bps / (max_bps_target >> 5);
|
idx1 = mpp_clip(idx1, 0, 63);
|
idx2 = mpp_clip(idx2, 0, 63);
|
if (pre_ins_bps < ins_bps && bps_change < ins_bps) {
|
ins_ratio = 6 * (tab_lnx[idx1] - tab_lnx[idx2]);
|
ins_ratio = mpp_clip(ins_ratio, -192, 256);
|
} else {
|
ins_ratio = 0;
|
}
|
|
bps_ratio = 96 * (ins_bps - bps_change) / bps_change;
|
bit_diff_ratio = mpp_clip(bit_diff_ratio, -128, 256);
|
bps_ratio = mpp_clip(bps_ratio, -32, 32);
|
|
p->next_ratio = bit_diff_ratio + ins_ratio + bps_ratio;
|
rc_dbg_rc("vbr reenc next ratio %d", p->next_ratio);
|
rc_dbg_func("leave %p\n", p);
|
return MPP_OK;
|
}
|
|
RK_S32 moving_ratio_calc(RcModelV2Ctx *ctx)
|
{
|
RK_S32 motion_sensitivity = ctx->motion_sensitivity;
|
RK_S32 scale = 0, i;
|
RK_S32 total_bit = 0, pbit_sum = 0;
|
RK_S32 madi_sum = 0, madp_sum = 0;
|
RK_S32 percent = 0;
|
|
for (i = 0; i < 2; i++) {
|
RK_S32 pre_I_bit = mpp_data_get_pre_val_v2(ctx->pre_i_bit, i);
|
RK_S32 pre_mean_qp = mpp_data_get_pre_val_v2(ctx->pre_i_mean_qp, i);
|
if (pre_mean_qp == -1) {
|
scale = 32;
|
} else {
|
RK_S32 index = pre_mean_qp + 8 - ctx->pre_mean_qp;
|
if (index >= 0) {
|
index = mpp_clip(index, 0 , 15);
|
scale = mean_qp2scale[index];
|
} else {
|
scale = 14;
|
}
|
}
|
total_bit += (scale * pre_I_bit >> 5);
|
rc_dbg_rc("pre_mean_qp = %d, ctx->pre_mean_qp %d", pre_mean_qp, ctx->pre_mean_qp);
|
rc_dbg_rc("scale = %d, pre_I_bit %d", scale, pre_I_bit);
|
}
|
|
pbit_sum = mpp_data_sum_v2(ctx->pre_p_bit);
|
madi_sum = mpp_data_sum_v2(ctx->madi);
|
madp_sum = mpp_data_sum_v2(ctx->madp);
|
rc_dbg_rc("pbit_sum %d,madi_sum = %d, madp_sum = %d", pbit_sum, madi_sum, madp_sum);
|
if ( pbit_sum == 0 || total_bit == 0) {
|
percent = 255;
|
} else {
|
RK_S32 index = (total_bit << 6) / pbit_sum;
|
index = mpp_clip(index >> 4, 1, 99);
|
percent = (bit2percent[index] << 8) / 100;
|
}
|
rc_dbg_rc("means qp percent %d min_still_percent %d", percent, ctx->min_still_percent);
|
RK_S32 percent_a = (ctx->min_still_percent - 30) << 8;
|
RK_S32 percent_b = 100 - ctx->min_still_percent;
|
|
percent = (percent_a + percent * percent_b) / 70;
|
rc_dbg_rc("percent_a = %d percent_b %d", percent_a, percent_b);
|
RK_S32 mv_percnt = (ctx->prev_md_prop * 100) >> 8;
|
RK_S32 mv_ratio = (percent_a + 7680 + mv_percnt * percent_b) / 100;
|
rc_dbg_rc("mv_ratio = %d", mv_ratio);
|
RK_S32 mad_ratio = 256;
|
if (madi_sum) {
|
mad_ratio = 20 * madp_sum / madi_sum;
|
mad_ratio = mpp_clip(mad_ratio, 5, 100);
|
rc_dbg_rc("mad_ratio = %d", mad_ratio);
|
mad_ratio = (mad_ratio << 8) / 100;
|
}
|
mad_ratio = (percent_a + 7680 + percent_b * mad_ratio) / 100;
|
|
RK_S32 moving_ratio = (percent + 1 + (mv_ratio * motion_sensitivity + (100 - motion_sensitivity) * mad_ratio) / 100) >> 1;
|
rc_dbg_rc("moving_ratio = %d, motion_sensitivity = %d", moving_ratio, motion_sensitivity);
|
rc_dbg_rc("percent %d mad_ratio %d hr_ratio %d, moving_ratio %d", percent, mad_ratio, mv_ratio, moving_ratio);
|
return moving_ratio;
|
}
|
|
MPP_RET calc_avbr_ratio(void *ctx, EncRcTaskInfo *cfg)
|
{
|
RcModelV2Ctx *p = (RcModelV2Ctx *)ctx;
|
RcCfg *usr_cfg = &p->usr_cfg;
|
RK_S32 bps_change = p->target_bps;
|
RK_S32 max_bps_target = usr_cfg->bps_max;
|
RK_S32 ins_bps = p->ins_bps;
|
RK_S32 pre_target_bits = p->pre_target_bits;
|
RK_S32 pre_real_bits = p->pre_real_bits;
|
RK_S32 pre_ins_bps = p->last_inst_bps;
|
RK_S32 idx1, idx2;
|
RK_S32 bit_diff_ratio, ins_ratio, agop_dratio, rgop_dratio;
|
RK_S32 moving_ratio = 0, moving_percent;
|
RK_S32 gop_bits = 0, gop_kbits = 0;
|
RK_S32 i_ratio, max_bps;
|
RK_S32 qratio, final_qratio;
|
|
rc_dbg_func("enter %p\n", p);
|
|
moving_ratio = moving_ratio_calc(p);
|
if (p->moving_ratio - 2 >= moving_ratio)
|
moving_ratio = p->moving_ratio - 2;
|
|
if (p->moving_ratio > moving_ratio && (p->max_still_qp << 6) <= p->scale_qp) {
|
p->moving_ratio = mpp_clip(p->moving_ratio + 1, 1, 255);
|
} else {
|
p->moving_ratio = moving_ratio;
|
}
|
rc_dbg_rc("final moving_ratio = %d", moving_ratio);
|
|
if (moving_ratio <= 0)
|
moving_ratio = 1;
|
|
gop_bits = moving_ratio * p->gop_total_bits >> 8;
|
gop_kbits = gop_bits >> 10;
|
if (gop_kbits < 1)
|
gop_kbits = 1;
|
|
bits_model_alloc(p, cfg, gop_bits);
|
bps_change = moving_ratio * bps_change >> 8;
|
if (moving_ratio < 0) {
|
moving_ratio += 255;
|
}
|
moving_percent = 100 * moving_ratio >> 8;
|
|
rc_dbg_bps("%10s|%10s|%10s|%10s|%10s", "m_ratio", "r_bits", "t_bits", "ins_bps", "p_ins_bps");
|
rc_dbg_bps("%10d %10d %10d %10d %10d", p->moving_ratio, pre_real_bits, pre_target_bits, ins_bps, pre_ins_bps);
|
|
if (pre_target_bits > pre_real_bits)
|
bit_diff_ratio = 32 * (pre_real_bits - pre_target_bits) / pre_target_bits;
|
else
|
bit_diff_ratio = 64 * (pre_real_bits - pre_target_bits) / pre_target_bits * moving_percent;
|
|
i_ratio = mpp_clip(p->pre_i_scale >> 4, 10, 200);
|
idx1 = ins_bps / (max_bps_target >> 5);
|
idx2 = pre_ins_bps / (max_bps_target >> 5);
|
idx1 = mpp_clip(idx1, 0, 63);
|
idx2 = mpp_clip(idx2, 0, 63);
|
ins_ratio = tab_lnx[idx2] - tab_lnx[idx1];
|
max_bps = bps_change;
|
|
if (max_bps < pre_ins_bps) {
|
max_bps = pre_ins_bps;
|
}
|
|
if (ins_bps > max_bps) {
|
ins_ratio = 6 * ins_ratio;
|
} else if (ins_bps < pre_ins_bps && bps_change > pre_ins_bps) {
|
ins_ratio = 3 * ins_ratio;
|
} else {
|
ins_ratio = 0;
|
}
|
|
ins_ratio = mpp_clip(ins_ratio >> 2, -128, 256);
|
bit_diff_ratio = mpp_clip(10 * bit_diff_ratio / i_ratio, -128, 256);
|
rgop_dratio = mpp_clip(24 * ((p->real_gbits - gop_bits) >> 10) / gop_kbits, -1, 1);
|
agop_dratio = mpp_clip(48 * ((p->avg_gbits - gop_bits) >> 10) / gop_kbits , -1, 1);
|
if (p->pre_i_scale > 640) {
|
bit_diff_ratio = mpp_clip(bit_diff_ratio, -16, 32);
|
ins_ratio = mpp_clip(ins_ratio, -16, 32);
|
}
|
qratio = 0;
|
final_qratio = ins_ratio + bit_diff_ratio + agop_dratio + rgop_dratio;
|
if (max_bps_target >= ins_bps) {
|
if (final_qratio > 0) {
|
if (p->scale_qp >= (p->max_still_qp << 6)) {
|
final_qratio = ins_ratio + agop_dratio + rgop_dratio;
|
qratio = -6;
|
}
|
}
|
}
|
p->next_ratio = qratio + final_qratio;
|
|
rc_dbg_qp("%10s|%10s|%10s|%10s|%10s|%10s|%10s", "diff_ratio", "ins_ratio", "rg_ratio",
|
"ag_ratio", "qratio", "next_ratio", "cur_qp_s");
|
rc_dbg_qp("%10d %10d %10d %10d %10d %10d %10d", bit_diff_ratio, ins_ratio, rgop_dratio,
|
agop_dratio, qratio, p->next_ratio, p->cur_scale_qp);
|
rc_dbg_func("leave %p\n", p);
|
return MPP_OK;
|
}
|
|
MPP_RET bits_model_init(RcModelV2Ctx *ctx)
|
{
|
RcCfg *usr_cfg = &ctx->usr_cfg;
|
RK_S32 gop_len = ctx->usr_cfg.igop;
|
RcFpsCfg *fps = &ctx->usr_cfg.fps;
|
RK_S64 gop_bits = 0;
|
RK_U32 target_bps;
|
|
rc_dbg_func("enter %p\n", ctx);
|
|
usr_cfg->min_i_bit_prop = mpp_clip(usr_cfg->min_i_bit_prop, 10, 100);
|
usr_cfg->max_i_bit_prop = mpp_clip(usr_cfg->max_i_bit_prop,
|
usr_cfg->min_i_bit_prop, 100);
|
usr_cfg->init_ip_ratio = mpp_clip(usr_cfg->init_ip_ratio, 160, 640);
|
|
rc_dbg_rc("min_i_bit_prop %d max_i_bit_prop %d, init_ip_ratio %d",
|
usr_cfg->min_i_bit_prop, usr_cfg->max_i_bit_prop, usr_cfg->init_ip_ratio);
|
|
if (!gop_len) {
|
rc_dbg_rc("infinte gop, set default for rc bit calc\n");
|
usr_cfg->igop = gop_len = 500;
|
} else if (gop_len == 1) {
|
rc_dbg_rc("all intra gop \n");
|
usr_cfg->init_ip_ratio = 16;
|
|
/* disable debreath on all intra case */
|
if (usr_cfg->debreath_cfg.enable)
|
usr_cfg->debreath_cfg.enable = 0;
|
|
usr_cfg->igop = gop_len = 500;
|
} else {
|
usr_cfg->igop = gop_len = mpp_clip(usr_cfg->igop, usr_cfg->igop, 500);
|
}
|
|
if (!ctx->min_still_percent) {
|
if (usr_cfg->bps_min && usr_cfg->bps_max) {
|
ctx->min_still_percent = usr_cfg->bps_min * 100 / usr_cfg->bps_max;
|
} else {
|
ctx->min_still_percent = 25;
|
}
|
rc_dbg_rc("min_still_percent %d", ctx->min_still_percent);
|
}
|
ctx->max_still_qp = 35;
|
ctx->motion_sensitivity = 90;
|
|
ctx->first_frm_flg = 1;
|
ctx->gop_frm_cnt = 0;
|
ctx->gop_qp_sum = 0;
|
|
target_bps = ctx->usr_cfg.bps_max;
|
ctx->re_calc_ratio = reenc_calc_vbr_ratio;
|
switch (ctx->usr_cfg.mode) {
|
case RC_CBR: {
|
ctx->calc_ratio = calc_cbr_ratio;
|
ctx->re_calc_ratio = reenc_calc_cbr_ratio;
|
target_bps = ctx->usr_cfg.bps_target;
|
} break;
|
case RC_VBR: {
|
ctx->calc_ratio = calc_vbr_ratio;
|
} break;
|
case RC_FIXQP: {
|
return MPP_OK;
|
}
|
case RC_AVBR: {
|
ctx->calc_ratio = calc_avbr_ratio;
|
} break;
|
default:
|
mpp_log("rc mode set error");
|
break;
|
}
|
|
ctx->target_bps = ctx->usr_cfg.bps_target;
|
|
if (gop_len >= 1)
|
gop_bits = (RK_S64)gop_len * target_bps * fps->fps_out_denorm;
|
else
|
gop_bits = (RK_S64)fps->fps_out_num * target_bps * fps->fps_out_denorm;
|
|
ctx->gop_total_bits = gop_bits / fps->fps_out_num;
|
ctx->bit_per_frame = target_bps * fps->fps_out_denorm / fps->fps_out_num;
|
ctx->watl_thrd = 3 * target_bps;
|
ctx->stat_watl = ctx->watl_thrd >> 3;
|
ctx->watl_base = ctx->stat_watl;
|
|
rc_dbg_rc("gop %d total bit %lld per_frame %d statistics time %d second\n",
|
ctx->usr_cfg.igop, ctx->gop_total_bits, ctx->bit_per_frame,
|
ctx->usr_cfg.stats_time);
|
|
if (bits_model_param_init(ctx)) {
|
return MPP_NOK;
|
}
|
|
bits_frm_init(ctx);
|
rc_dbg_func("leave %p\n", ctx);
|
return MPP_OK;
|
}
|
|
MPP_RET bits_mode_reset(RcModelV2Ctx *ctx)
|
{
|
rc_dbg_func("enter %p\n", ctx);
|
(void) ctx;
|
rc_dbg_func("leave %p\n", ctx);
|
return MPP_OK;
|
}
|
|
MPP_RET check_super_frame(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg)
|
{
|
MPP_RET ret = MPP_OK;
|
RK_S32 frame_type = cfg->frame_type;
|
RK_U32 bits_thr = 0;
|
RcCfg *usr_cfg = &ctx->usr_cfg;
|
|
rc_dbg_func("enter %p\n", ctx);
|
if (usr_cfg->super_cfg.super_mode) {
|
bits_thr = usr_cfg->super_cfg.super_p_thd;
|
if (frame_type == INTRA_FRAME) {
|
bits_thr = usr_cfg->super_cfg.super_i_thd;
|
}
|
|
if ((RK_U32)cfg->bit_real >= bits_thr) {
|
if (usr_cfg->super_cfg.super_mode == MPP_ENC_RC_SUPER_FRM_DROP) {
|
rc_dbg_rc("super frame drop current frame");
|
usr_cfg->drop_mode = MPP_ENC_RC_DROP_FRM_NORMAL;
|
usr_cfg->drop_gap = 0;
|
}
|
ret = MPP_NOK;
|
}
|
}
|
rc_dbg_func("leave %p\n", ctx);
|
return ret;
|
}
|
|
MPP_RET check_re_enc(RcModelV2Ctx *ctx, EncRcTaskInfo *cfg)
|
{
|
RcCfg *usr_cfg = &ctx->usr_cfg;
|
RK_S32 frame_type = cfg->frame_type;
|
RK_S32 bit_thr = 0;
|
RK_S32 stat_time = usr_cfg->stats_time;
|
RK_S32 last_ins_bps = mpp_data_sum_v2(ctx->stat_bits) / stat_time;
|
RK_S32 ins_bps = (last_ins_bps * stat_time - mpp_data_get_pre_val_v2(ctx->stat_bits, -1)
|
+ cfg->bit_real) / stat_time;
|
RK_S32 target_bps;
|
RK_S32 ret = MPP_OK;
|
|
rc_dbg_func("enter %p\n", ctx);
|
rc_dbg_rc("reenc check target_bps %d last_ins_bps %d ins_bps %d",
|
usr_cfg->bps_target, last_ins_bps, ins_bps);
|
|
if (ctx->reenc_cnt >= usr_cfg->max_reencode_times)
|
return MPP_OK;
|
|
if (check_super_frame(ctx, cfg))
|
return MPP_NOK;
|
|
if (usr_cfg->debreath_cfg.enable && !ctx->first_frm_flg)
|
return MPP_OK;
|
|
rc_dbg_drop("drop mode %d frame_type %d\n", usr_cfg->drop_mode, frame_type);
|
if (usr_cfg->drop_mode && frame_type == INTER_P_FRAME) {
|
bit_thr = (RK_S32)(usr_cfg->bps_max * (100 + usr_cfg->drop_thd) / (float)100);
|
rc_dbg_drop("drop mode %d check max_bps %d bit_thr %d ins_bps %d",
|
usr_cfg->drop_mode, usr_cfg->bps_target, bit_thr, ins_bps);
|
return (ins_bps > bit_thr) ? MPP_NOK : MPP_OK;
|
}
|
|
switch (frame_type) {
|
case INTRA_FRAME:
|
bit_thr = 3 * cfg->bit_target / 2;
|
break;
|
case INTER_P_FRAME:
|
bit_thr = 3 * cfg->bit_target;
|
break;
|
default:
|
break;
|
}
|
|
if (cfg->bit_real > bit_thr) {
|
if (usr_cfg->mode == RC_CBR) {
|
target_bps = usr_cfg->bps_target;
|
if (target_bps / 20 < ins_bps - last_ins_bps &&
|
(target_bps + target_bps / 10 < ins_bps
|
|| target_bps - target_bps / 10 > ins_bps)) {
|
ret = MPP_NOK;
|
}
|
} else {
|
target_bps = usr_cfg->bps_max;
|
if ((target_bps - (target_bps >> 3) < ins_bps) &&
|
(target_bps / 20 < ins_bps - last_ins_bps)) {
|
ret = MPP_NOK;
|
}
|
}
|
}
|
|
rc_dbg_func("leave %p ret %d\n", ctx, ret);
|
return ret;
|
}
|
|
|
MPP_RET rc_model_v2_init(void *ctx, RcCfg *cfg)
|
{
|
RcModelV2Ctx *p = (RcModelV2Ctx*)ctx;
|
|
rc_dbg_func("enter %p\n", ctx);
|
|
memcpy(&p->usr_cfg, cfg, sizeof(RcCfg));
|
bits_model_init(p);
|
|
rc_dbg_func("leave %p\n", ctx);
|
return MPP_OK;
|
}
|
|
MPP_RET rc_model_v2_deinit(void *ctx)
|
{
|
RcModelV2Ctx *p = (RcModelV2Ctx *)ctx;
|
|
rc_dbg_func("enter %p\n", ctx);
|
bits_model_param_deinit(p);
|
|
rc_dbg_func("leave %p\n", ctx);
|
return MPP_OK;
|
}
|
|
MPP_RET rc_model_v2_start(void *ctx, EncRcTask *task)
|
{
|
RcModelV2Ctx *p = (RcModelV2Ctx*)ctx;
|
EncFrmStatus *frm = &task->frm;
|
EncRcTaskInfo *info = &task->info;
|
RcCfg *usr_cfg = &p->usr_cfg;
|
|
rc_dbg_func("enter %p\n", ctx);
|
|
if (usr_cfg->mode == RC_FIXQP) {
|
if (usr_cfg->init_quality <= 0) {
|
mpp_log("invalid fix %d qp found set default qp 26\n",
|
usr_cfg->init_quality);
|
usr_cfg->init_quality = 26;
|
}
|
|
if (usr_cfg->max_quality <= 0)
|
usr_cfg->max_quality = usr_cfg->init_quality;
|
if (usr_cfg->min_quality <= 0)
|
usr_cfg->min_quality = usr_cfg->init_quality;
|
if (usr_cfg->max_i_quality <= 0)
|
usr_cfg->max_i_quality = usr_cfg->max_quality;
|
if (usr_cfg->min_i_quality <= 0)
|
usr_cfg->min_i_quality = usr_cfg->min_quality;
|
|
if (frm->is_intra) {
|
info->quality_max = usr_cfg->max_i_quality;
|
info->quality_min = usr_cfg->min_i_quality;
|
info->quality_target = usr_cfg->init_quality;
|
} else {
|
info->quality_max = usr_cfg->max_quality;
|
info->quality_min = usr_cfg->min_quality;
|
info->quality_target = usr_cfg->init_quality;
|
}
|
|
rc_dbg_rc("seq_idx %d intra %d\n", frm->seq_idx, frm->is_intra);
|
rc_dbg_rc("bitrate [%d : %d : %d]\n", info->bit_min, info->bit_target, info->bit_max);
|
rc_dbg_rc("quality [%d : %d : %d]\n", info->quality_min, info->quality_target, info->quality_max);
|
|
return MPP_OK;
|
}
|
|
info->frame_type = (frm->is_intra) ? (INTRA_FRAME) : (INTER_P_FRAME);
|
|
if (frm->ref_mode == REF_TO_PREV_INTRA)
|
info->frame_type = INTER_VI_FRAME;
|
|
p->next_ratio = 0;
|
if (p->last_frame_type == INTRA_FRAME) {
|
calc_next_i_ratio(p);
|
}
|
|
if (!p->first_frm_flg) {
|
if (p->calc_ratio)
|
p->calc_ratio(p, info);
|
} else {
|
bits_model_alloc(p, info, p->gop_total_bits);
|
/* quality determination */
|
info->quality_target = (usr_cfg->init_quality <= 0) ? -1 : usr_cfg->init_quality;
|
}
|
|
if (frm->is_intra) {
|
info->quality_max = usr_cfg->max_i_quality;
|
info->quality_min = usr_cfg->min_i_quality;
|
} else {
|
info->quality_max = usr_cfg->max_quality;
|
info->quality_min = usr_cfg->min_quality;
|
}
|
|
bits_model_preset(p, info);
|
|
rc_dbg_rc("seq_idx %d intra %d\n", frm->seq_idx, frm->is_intra);
|
rc_dbg_rc("bitrate [%d : %d : %d]\n", info->bit_min, info->bit_target, info->bit_max);
|
rc_dbg_rc("quality [%d : %d : %d]\n", info->quality_min, info->quality_target, info->quality_max);
|
|
p->reenc_cnt = 0;
|
p->last_frame_type = info->frame_type;
|
|
rc_dbg_func("leave %p\n", ctx);
|
|
return MPP_OK;
|
}
|
|
static RK_S32 cal_first_i_start_qp(RK_S32 target_bit, RK_U32 total_mb)
|
{
|
static RK_U32 mb_num[9] = {
|
0, 200, 700, 1200,
|
2000, 4000, 8000, 16000,
|
20000
|
};
|
|
static RK_U32 tab_bit[9] = {
|
3780, 3570, 3150, 2940,
|
2730, 3780, 2100, 1680,
|
2100
|
};
|
|
static RK_U8 qscale2qp[96] = {
|
15, 15, 15, 15, 15, 16, 18, 20, 21, 22, 23, 24,
|
25, 25, 26, 27, 28, 28, 29, 29, 30, 30, 30, 31,
|
31, 32, 32, 33, 33, 33, 34, 34, 34, 34, 35, 35,
|
35, 36, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38,
|
38, 38, 38, 39, 39, 39, 39, 39, 39, 40, 40, 40,
|
40, 41, 41, 41, 41, 41, 41, 41, 42, 42, 42, 42,
|
42, 42, 42, 42, 43, 43, 43, 43, 43, 43, 43, 43,
|
44, 44, 44, 44, 44, 44, 44, 44, 45, 45, 45, 45,
|
};
|
|
RK_S32 cnt = 0;
|
RK_S32 index;
|
RK_S32 i;
|
|
for (i = 0; i < 8; i++) {
|
if (mb_num[i] > total_mb)
|
break;
|
cnt++;
|
}
|
|
index = (total_mb * tab_bit[cnt] - 350) / target_bit; // qscale
|
index = mpp_clip(index, 4, 95);
|
|
return qscale2qp[index];
|
}
|
|
MPP_RET rc_model_v2_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) {
|
RK_S32 i_quality_delta = usr_cfg->i_quality_delta;
|
|
if (info->quality_target < 0) {
|
if (info->bit_target) {
|
info->quality_target = cal_first_i_start_qp(info->bit_target, mb_w * mb_h);
|
} else {
|
mpp_log("init qp not set on fix qp mode, use default qp\n");
|
info->quality_target = 26;
|
}
|
}
|
|
if (p->reenc_cnt) {
|
p->cur_scale_qp += p->next_ratio;
|
p->start_qp = (p->cur_scale_qp >> 6) - i_quality_delta;
|
} else {
|
p->start_qp = info->quality_target;
|
p->cur_scale_qp = (info->quality_target + i_quality_delta) << 6;
|
}
|
|
rc_dbg_rc("qp: start %2d cur_scale %d next_ratio %d reenc %d\n",
|
p->start_qp, p->cur_scale_qp, p->next_ratio, p->reenc_cnt);
|
|
p->cur_scale_qp = mpp_clip(p->cur_scale_qp, (info->quality_min << 6), (info->quality_max << 6));
|
} else {
|
RK_S32 qp_scale = p->cur_scale_qp + p->next_ratio;
|
RK_S32 start_qp = 0;
|
|
if (frm->is_intra) {
|
RK_S32 i_quality_delta = usr_cfg->i_quality_delta;
|
|
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);
|
|
if (i_quality_delta) {
|
RK_U32 index = mpp_clip(mpp_data_mean_v2(p->madi) / 4, 0, 7);
|
RK_S32 max_ip_delta = max_ip_qp_dealt[index];
|
|
if (i_quality_delta > max_ip_delta)
|
i_quality_delta = max_ip_delta;
|
|
rc_dbg_rc("qp prev %d:%d curr %d - %d (max %d) -> %d reenc %d\n",
|
p->pre_i_qp, qp_scale >> 6, start_qp,
|
usr_cfg->i_quality_delta, max_ip_delta,
|
start_qp - i_quality_delta, p->reenc_cnt);
|
|
if (!p->reenc_cnt) {
|
start_qp -= i_quality_delta;
|
}
|
}
|
|
start_qp = mpp_clip(start_qp, info->quality_min, info->quality_max);
|
p->start_qp = start_qp;
|
|
if (!p->reenc_cnt) {
|
p->cur_scale_qp = qp_scale;
|
if (p->usr_cfg.debreath_cfg.enable) {
|
calc_debreath_qp(ctx);
|
}
|
} else {
|
p->cur_scale_qp = qp_scale;
|
}
|
|
p->gop_frm_cnt = 0;
|
p->gop_qp_sum = 0;
|
} else {
|
qp_scale = mpp_clip(qp_scale, (info->quality_min << 6), (info->quality_max << 6));
|
p->cur_scale_qp = qp_scale;
|
rc_dbg_rc("qp %d -> %d\n", p->start_qp, qp_scale >> 6);
|
p->start_qp = qp_scale >> 6;
|
if (frm->ref_mode == REF_TO_PREV_INTRA && usr_cfg->vi_quality_delta) {
|
rc_dbg_rc("qp %d -> %d (vi)\n", p->start_qp, p->start_qp - usr_cfg->vi_quality_delta);
|
p->start_qp -= usr_cfg->vi_quality_delta;
|
}
|
}
|
}
|
|
if (usr_cfg->hier_qp_cfg.hier_qp_en && !p->reenc_cnt) {
|
rc_hier_calc_dealt_qp(p, info);
|
if (p->qp_layer_id) {
|
RK_S32 hier_qp_delta = usr_cfg->hier_qp_cfg.hier_qp_delta[p->qp_layer_id - 1];
|
|
p->start_qp -= hier_qp_delta;
|
rc_dbg_qp("hier_qp: layer %d delta %d", p->qp_layer_id, hier_qp_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;
|
}
|
|
MPP_RET rc_model_v2_hal_end(void *ctx, EncRcTask *task)
|
{
|
RcModelV2Ctx *p = (RcModelV2Ctx *)ctx;
|
EncFrmStatus *frm = &task->frm;
|
|
rc_dbg_func("enter ctx %p task %p\n", ctx, task);
|
|
if (frm->is_intra)
|
p->pre_i_qp = p->cur_scale_qp >> 6;
|
else
|
p->pre_p_qp = p->cur_scale_qp >> 6;
|
|
rc_dbg_func("leave %p\n", ctx);
|
return MPP_OK;
|
}
|
|
MPP_RET rc_model_v2_check_reenc(void *ctx, EncRcTask *task)
|
{
|
RcModelV2Ctx *p = (RcModelV2Ctx *)ctx;
|
EncRcTaskInfo *cfg = (EncRcTaskInfo *)&task->info;
|
EncFrmStatus *frm = &task->frm;
|
RcCfg *usr_cfg = &p->usr_cfg;
|
|
rc_dbg_func("enter ctx %p cfg %p\n", ctx, cfg);
|
|
frm->reencode = 0;
|
|
if ((usr_cfg->mode == RC_FIXQP) ||
|
(task->force.force_flag & ENC_RC_FORCE_QP) ||
|
p->on_drop || p->on_pskip)
|
return MPP_OK;
|
|
if (check_re_enc(p, cfg)) {
|
MppEncRcDropFrmMode drop_mode = usr_cfg->drop_mode;
|
|
if (frm->is_intra)
|
drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED;
|
|
if (usr_cfg->drop_gap && p->drop_cnt >= usr_cfg->drop_gap)
|
drop_mode = MPP_ENC_RC_DROP_FRM_DISABLED;
|
|
rc_dbg_drop("reenc drop_mode %d drop_cnt %d\n", drop_mode, p->drop_cnt);
|
|
switch (drop_mode) {
|
case MPP_ENC_RC_DROP_FRM_NORMAL : {
|
frm->drop = 1;
|
frm->reencode = 1;
|
p->on_drop = 1;
|
p->drop_cnt++;
|
rc_dbg_drop("drop\n");
|
} break;
|
case MPP_ENC_RC_DROP_FRM_PSKIP : {
|
frm->force_pskip = 1;
|
frm->reencode = 1;
|
p->on_pskip = 1;
|
p->drop_cnt++;
|
rc_dbg_drop("force_pskip\n");
|
} break;
|
case MPP_ENC_RC_DROP_FRM_DISABLED :
|
default : {
|
if (p->re_calc_ratio)
|
p->re_calc_ratio(p, cfg);
|
|
if (p->next_ratio != 0 && cfg->quality_target < cfg->quality_max) {
|
p->reenc_cnt++;
|
frm->reencode = 1;
|
}
|
p->drop_cnt = 0;
|
} break;
|
}
|
}
|
|
return MPP_OK;
|
}
|
|
MPP_RET rc_model_v2_end(void *ctx, EncRcTask *task)
|
{
|
RcModelV2Ctx *p = (RcModelV2Ctx *)ctx;
|
EncRcTaskInfo *cfg = (EncRcTaskInfo *)&task->info;
|
RcCfg *usr_cfg = &p->usr_cfg;
|
|
rc_dbg_func("enter ctx %p cfg %p\n", ctx, cfg);
|
|
rc_dbg_rc("bits_mode_update real_bit %d", cfg->bit_real);
|
|
if (usr_cfg->mode == RC_FIXQP)
|
goto DONE;
|
|
p->last_inst_bps = p->ins_bps;
|
p->first_frm_flg = 0;
|
|
bits_model_update(p, cfg);
|
if (usr_cfg->mode == RC_AVBR) {
|
moving_judge_update(p, cfg);
|
bit_statics_update(p, cfg->bit_real);
|
}
|
|
p->gop_frm_cnt++;
|
p->gop_qp_sum += p->start_qp;
|
|
p->pre_mean_qp = cfg->quality_real;
|
p->pre_iblk4_prop = cfg->iblk4_prop;
|
p->scale_qp = p->cur_scale_qp;
|
p->prev_md_prop = 0;
|
p->pre_target_bits = cfg->bit_target;
|
p->pre_real_bits = cfg->bit_real;
|
|
p->on_drop = 0;
|
p->on_pskip = 0;
|
|
DONE:
|
rc_dbg_func("leave %p\n", ctx);
|
return MPP_OK;
|
}
|