mirror of
https://github.com/nyanmisaka/mpp.git
synced 2025-10-05 17:16:50 +08:00
feat[rc_v2]: Support flex fps rate control
Change-Id: I45a8544c15ab4baede232e1a3b16c517f965092e Signed-off-by: sayon.chen <sayon.chen@rock-chips.com>
This commit is contained in:
@@ -185,6 +185,7 @@ typedef struct RcCfg_s {
|
|||||||
RcHierQPCfg hier_qp_cfg;
|
RcHierQPCfg hier_qp_cfg;
|
||||||
RK_U32 refresh_len;
|
RK_U32 refresh_len;
|
||||||
RK_S32 scene_mode;
|
RK_S32 scene_mode;
|
||||||
|
RK_U32 fps_chg_prop;
|
||||||
} RcCfg;
|
} RcCfg;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -98,6 +98,11 @@ typedef struct RcModelV2Ctx_t {
|
|||||||
RK_S32 qp_layer_id;
|
RK_S32 qp_layer_id;
|
||||||
RK_S32 hier_frm_cnt[4];
|
RK_S32 hier_frm_cnt[4];
|
||||||
|
|
||||||
|
RK_S64 time_base;
|
||||||
|
RK_S64 time_end;
|
||||||
|
RK_S32 frm_cnt;
|
||||||
|
RK_S32 last_fps;
|
||||||
|
|
||||||
MPP_RET (*calc_ratio)(void* ctx, EncRcTaskInfo *cfg);
|
MPP_RET (*calc_ratio)(void* ctx, EncRcTaskInfo *cfg);
|
||||||
MPP_RET (*re_calc_ratio)(void* ctx, EncRcTaskInfo *cfg);
|
MPP_RET (*re_calc_ratio)(void* ctx, EncRcTaskInfo *cfg);
|
||||||
} RcModelV2Ctx;
|
} RcModelV2Ctx;
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
#include "mpp_env.h"
|
#include "mpp_env.h"
|
||||||
#include "mpp_mem.h"
|
#include "mpp_mem.h"
|
||||||
#include "mpp_common.h"
|
#include "mpp_common.h"
|
||||||
|
#include "mpp_time.h"
|
||||||
#include "rc_debug.h"
|
#include "rc_debug.h"
|
||||||
#include "rc_ctx.h"
|
#include "rc_ctx.h"
|
||||||
#include "rc_model_v2.h"
|
#include "rc_model_v2.h"
|
||||||
@@ -1065,7 +1065,7 @@ MPP_RET bits_model_init(RcModelV2Ctx *ctx)
|
|||||||
RK_S32 gop_len = ctx->usr_cfg.igop;
|
RK_S32 gop_len = ctx->usr_cfg.igop;
|
||||||
RcFpsCfg *fps = &ctx->usr_cfg.fps;
|
RcFpsCfg *fps = &ctx->usr_cfg.fps;
|
||||||
RK_S64 gop_bits = 0;
|
RK_S64 gop_bits = 0;
|
||||||
RK_U32 target_bps;
|
RK_U32 target_bps = 0;
|
||||||
|
|
||||||
rc_dbg_func("enter %p\n", ctx);
|
rc_dbg_func("enter %p\n", ctx);
|
||||||
|
|
||||||
@@ -1099,6 +1099,10 @@ MPP_RET bits_model_init(RcModelV2Ctx *ctx)
|
|||||||
ctx->gop_frm_cnt = 0;
|
ctx->gop_frm_cnt = 0;
|
||||||
ctx->gop_qp_sum = 0;
|
ctx->gop_qp_sum = 0;
|
||||||
|
|
||||||
|
if (!usr_cfg->fps_chg_prop) {
|
||||||
|
usr_cfg->fps_chg_prop = 25;
|
||||||
|
}
|
||||||
|
|
||||||
target_bps = ctx->usr_cfg.bps_max;
|
target_bps = ctx->usr_cfg.bps_max;
|
||||||
ctx->re_calc_ratio = reenc_calc_vbr_ratio;
|
ctx->re_calc_ratio = reenc_calc_vbr_ratio;
|
||||||
switch (ctx->usr_cfg.mode) {
|
switch (ctx->usr_cfg.mode) {
|
||||||
@@ -1139,6 +1143,7 @@ MPP_RET bits_model_init(RcModelV2Ctx *ctx)
|
|||||||
ctx->watl_thrd = 3 * target_bps;
|
ctx->watl_thrd = 3 * target_bps;
|
||||||
ctx->stat_watl = ctx->watl_thrd >> 3;
|
ctx->stat_watl = ctx->watl_thrd >> 3;
|
||||||
ctx->watl_base = ctx->stat_watl;
|
ctx->watl_base = ctx->stat_watl;
|
||||||
|
ctx->last_fps = fps->fps_out_num / fps->fps_out_denorm;
|
||||||
|
|
||||||
rc_dbg_rc("gop %d total bit %lld per_frame %d statistics time %d second\n",
|
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.igop, ctx->gop_total_bits, ctx->bit_per_frame,
|
||||||
@@ -1147,12 +1152,70 @@ MPP_RET bits_model_init(RcModelV2Ctx *ctx)
|
|||||||
if (bits_model_param_init(ctx)) {
|
if (bits_model_param_init(ctx)) {
|
||||||
return MPP_NOK;
|
return MPP_NOK;
|
||||||
}
|
}
|
||||||
|
ctx->time_base = mpp_time();
|
||||||
bits_frm_init(ctx);
|
bits_frm_init(ctx);
|
||||||
rc_dbg_func("leave %p\n", ctx);
|
rc_dbg_func("leave %p\n", ctx);
|
||||||
return MPP_OK;
|
return MPP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static MPP_RET update_mode_param(RcModelV2Ctx *ctx, RK_U32 fps)
|
||||||
|
{
|
||||||
|
RcCfg *usr_cfg = &ctx->usr_cfg;
|
||||||
|
RK_S32 gop_len = ctx->usr_cfg.igop;
|
||||||
|
RK_S64 gop_bits = 0;
|
||||||
|
RK_U32 target_bps;
|
||||||
|
RK_U32 stat_len = fps * usr_cfg->stats_time;
|
||||||
|
|
||||||
|
target_bps = ctx->usr_cfg.bps_max;
|
||||||
|
if (ctx->usr_cfg.mode == RC_CBR) {
|
||||||
|
target_bps = ctx->usr_cfg.bps_target;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gop_len >= 1)
|
||||||
|
gop_bits = (RK_S64)gop_len * target_bps;
|
||||||
|
else
|
||||||
|
gop_bits = (RK_S64)target_bps;
|
||||||
|
|
||||||
|
ctx->gop_total_bits = gop_bits / fps;
|
||||||
|
|
||||||
|
ctx->bit_per_frame = target_bps / fps;
|
||||||
|
|
||||||
|
if (ctx->stat_bits != NULL) {
|
||||||
|
mpp_data_deinit_v2(ctx->stat_bits);
|
||||||
|
ctx->stat_bits = NULL;
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return MPP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MPP_RET fps_chg_update_mode(RcModelV2Ctx *ctx)
|
||||||
|
{
|
||||||
|
ctx->time_end = mpp_time();
|
||||||
|
ctx->frm_cnt++;
|
||||||
|
|
||||||
|
if (ctx->time_base && ctx->time_end &&
|
||||||
|
((ctx->time_end - ctx->time_base) >= (RK_S64)(250 * 1000))) {
|
||||||
|
|
||||||
|
RK_S32 time_diff = ((RK_S32)(ctx->time_end - ctx->time_base) / 1000);
|
||||||
|
RK_U32 fps = ctx->frm_cnt * 1000 / time_diff;
|
||||||
|
|
||||||
|
if (ctx->last_fps > 0 && fps &&
|
||||||
|
abs(ctx->last_fps - (RK_S32)fps) * 100 / ctx->last_fps > (RK_S32)ctx->usr_cfg.fps_chg_prop) {
|
||||||
|
update_mode_param(ctx, fps);
|
||||||
|
mpp_log("fps chg from %d -> %d", ctx->last_fps, fps);
|
||||||
|
ctx->last_fps = fps;
|
||||||
|
}
|
||||||
|
ctx->time_base = ctx->time_end;
|
||||||
|
ctx->frm_cnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MPP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
MPP_RET bits_mode_reset(RcModelV2Ctx *ctx)
|
MPP_RET bits_mode_reset(RcModelV2Ctx *ctx)
|
||||||
{
|
{
|
||||||
rc_dbg_func("enter %p\n", ctx);
|
rc_dbg_func("enter %p\n", ctx);
|
||||||
@@ -1320,6 +1383,10 @@ MPP_RET rc_model_v2_start(void *ctx, EncRcTask *task)
|
|||||||
return MPP_OK;
|
return MPP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (usr_cfg->fps.fps_out_flex) {
|
||||||
|
fps_chg_update_mode(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
info->frame_type = (frm->is_intra) ? (INTRA_FRAME) : (INTER_P_FRAME);
|
info->frame_type = (frm->is_intra) ? (INTRA_FRAME) : (INTER_P_FRAME);
|
||||||
|
|
||||||
if (frm->ref_mode == REF_TO_PREV_INTRA)
|
if (frm->ref_mode == REF_TO_PREV_INTRA)
|
||||||
|
Reference in New Issue
Block a user