From 09e626dc0581595faea9638669ac75daf6dafd05 Mon Sep 17 00:00:00 2001 From: "timkingh.huang" Date: Tue, 25 Apr 2017 17:28:54 +0800 Subject: [PATCH] [h264e]: fix mosaic bug If target bit is zero, it will exist mosaic in the encoded picture. In this case, half of the average bit rate of previous P frames is assigned to target bit. Change-Id: I990e80ae04affb0a6bed2e6f456c77657f31a221 Signed-off-by: timkingh.huang --- mpp/codec/inc/mpp_rc.h | 2 ++ mpp/codec/mpp_rc.cpp | 52 +++++++++++++++++++---------- mpp/hal/common/h264/hal_h264e_com.c | 6 ++-- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/mpp/codec/inc/mpp_rc.h b/mpp/codec/inc/mpp_rc.h index cd0cf6cd..4b5aa268 100644 --- a/mpp/codec/inc/mpp_rc.h +++ b/mpp/codec/inc/mpp_rc.h @@ -150,11 +150,13 @@ typedef struct MppRateControl_s { /* * intra - intra frame bits record + * inter - inter frame bits record * pid_intra - intra frame bits record * pid_inter - inter frame bits record * pid_gop - serial frame bits record */ MppData *intra; + MppData *inter; MppData *gop_bits; MppData *intra_percent; MppPIDCtx pid_intra; diff --git a/mpp/codec/mpp_rc.cpp b/mpp/codec/mpp_rc.cpp index b4c99e98..4dfdd67a 100644 --- a/mpp/codec/mpp_rc.cpp +++ b/mpp/codec/mpp_rc.cpp @@ -106,6 +106,7 @@ RK_S32 mpp_data_avg(MppData *p, RK_S32 len, RK_S32 num, RK_S32 denorm) sum += p->val[pos]; } } else { + /* This case is not used so far, but may be useful in the future */ mpp_assert(num > denorm); RK_S32 acc_num = num; RK_S32 acc_denorm = denorm; @@ -119,8 +120,8 @@ RK_S32 mpp_data_avg(MppData *p, RK_S32 len, RK_S32 num, RK_S32 denorm) pos = p->len - 1; sum += p->val[pos] * acc_num / acc_denorm; - acc_num += num; - acc_denorm += denorm; + acc_num *= num; + acc_denorm *= denorm; } } return DIV(sum, len); @@ -212,6 +213,11 @@ MPP_RET mpp_rc_deinit(MppRateControl *ctx) ctx->intra = NULL; } + if (ctx->inter) { + mpp_data_deinit(ctx->inter); + ctx->inter = NULL; + } + if (ctx->gop_bits) { mpp_data_deinit(ctx->gop_bits); ctx->gop_bits = NULL; @@ -276,6 +282,10 @@ MPP_RET mpp_rc_update_user_cfg(MppRateControl *ctx, MppEncRcCfg *cfg, RK_S32 for mpp_data_deinit(ctx->intra); mpp_data_init(&ctx->intra, gop); + if (ctx->inter) + mpp_data_deinit(ctx->inter); + mpp_data_init(&ctx->inter, ctx->fps_out); /* need test */ + if (ctx->gop_bits) mpp_data_deinit(ctx->gop_bits); mpp_data_init(&ctx->gop_bits, gop); @@ -408,12 +418,13 @@ MPP_RET mpp_rc_bits_allocation(MppRateControl *ctx, RcSyntax *rc_syn) if (ctx->acc_intra_count) { intra_percent = mpp_data_avg(ctx->intra_percent, 1, 1, 1) / 100.0; ctx->last_intra_percent = intra_percent; - } - if (ctx->acc_intra_count) { - ctx->bits_target = (ctx->fps_out * ctx->bits_per_pic + diff_bit) * intra_percent; - } else - ctx->bits_target = ctx->bits_per_intra - mpp_pid_calc(&ctx->pid_intra); + ctx->bits_target = (ctx->fps_out * ctx->bits_per_pic + diff_bit) + * intra_percent; + } else { + ctx->bits_target = ctx->bits_per_intra + - mpp_pid_calc(&ctx->pid_intra); + } } else { if (ctx->pre_frmtype == INTRA_FRAME) { RK_S32 diff_bit = mpp_pid_calc(&ctx->pid_fps); @@ -447,7 +458,22 @@ MPP_RET mpp_rc_bits_allocation(MppRateControl *ctx, RcSyntax *rc_syn) } break; } - ctx->bits_target = ctx->bits_target > 0 ? ctx->bits_target : 0; + /* If target bit is zero, it will exist mosaic in the encoded picture. + * In this case, half of the average bit rate of previous P frames is + * assigned to target bit. + */ + if (ctx->bits_target <= 0) { + if (ctx->cur_frmtype == INTRA_FRAME) { + mpp_rc_dbg_rc("unbelievable case: intra frame target bits is zero!\n"); + } else { + mpp_rc_dbg_rc("inter frame target bits is zero!" + "intra frame %d, inter frame %d, total_cnt %d\n", + ctx->acc_intra_count, ctx->acc_inter_count, + ctx->acc_total_count); + ctx->bits_target = mpp_data_avg(ctx->inter, -1, 1, 1) / 2; + mpp_rc_dbg_rc("after adjustment, target bits %d\n", ctx->bits_target); + } + } rc_syn->bit_target = ctx->bits_target; @@ -485,6 +511,7 @@ MPP_RET mpp_rc_update_hw_result(MppRateControl *ctx, RcHalResult *result) ctx, bits, ctx->bits_per_inter); ctx->acc_inter_count++; ctx->acc_inter_bits_in_fps += bits; + mpp_data_update(ctx->inter, bits); mpp_data_update(ctx->gop_bits, bits); mpp_pid_update(&ctx->pid_inter, bits - ctx->bits_target); } @@ -503,15 +530,6 @@ MPP_RET mpp_rc_update_hw_result(MppRateControl *ctx, RcHalResult *result) ctx->last_fps_bits = 0; } - switch (ctx->gop_mode) { - case MPP_GOP_ALL_INTER : { - } break; - case MPP_GOP_ALL_INTRA : { - } break; - default : { - } break; - } - ctx->pre_frmtype = ctx->cur_frmtype; return MPP_OK; diff --git a/mpp/hal/common/h264/hal_h264e_com.c b/mpp/hal/common/h264/hal_h264e_com.c index c4792842..a8783106 100644 --- a/mpp/hal/common/h264/hal_h264e_com.c +++ b/mpp/hal/common/h264/hal_h264e_com.c @@ -782,9 +782,6 @@ void h264e_sei_pack2str(char *str, H264eHalContext *ctx, RcSyntax *rc_syn) /* rc cfg */ if (rc_change) { H264E_HAL_SPRINT(str, len, "[rc] "); - H264E_HAL_SPRINT(str, len, "rc_mode=%d ", rc->rc_mode); - H264E_HAL_SPRINT(str, len, "quality=%d ", rc->quality); - H264E_HAL_SPRINT(str, len, "bps=%d:%d:%d ", rc->bps_target, rc->bps_min, rc->bps_max); H264E_HAL_SPRINT(str, len, "fps_in=%d:%d:%d ", rc->fps_in_num, rc->fps_in_denorm, rc->fps_in_flex); H264E_HAL_SPRINT(str, len, "fps_out=%d:%d:%d ", rc->fps_out_num, rc->fps_out_denorm, rc->fps_out_flex); H264E_HAL_SPRINT(str, len, "gop=%d ", rc->gop); @@ -792,6 +789,9 @@ void h264e_sei_pack2str(char *str, H264eHalContext *ctx, RcSyntax *rc_syn) if (rc_syn) { H264E_HAL_SPRINT(str, len, "[frm %d] ", ctx->frame_cnt); + H264E_HAL_SPRINT(str, len, "rc_mode=%d ", rc->rc_mode); + H264E_HAL_SPRINT(str, len, "quality=%d ", rc->quality); + H264E_HAL_SPRINT(str, len, "bps=%d:%d:%d ", rc->bps_target, rc->bps_min, rc->bps_max); H264E_HAL_SPRINT(str, len, "tgt_bit=%d:%d:%d ", rc_syn->bit_target, rc_syn->bit_min, rc_syn->bit_max); H264E_HAL_SPRINT(str, len, "qp=%d:%d:%d ", hw_cfg->qp, hw_cfg->qp_min, hw_cfg->qp_max); }