背景说明
最近,有开发者反馈在基于RK3588的编码项目中,启用了MPP的ROI(感兴趣区域)功能后,遇到了一个两难问题:要么码率暴涨失控,要么视觉效果提升不明显。他的具体需求是:参考开源项目演示,期望在未启用ROI时,画面整体画质均匀;启用ROI后,能够实现人物区域清晰、背景模糊以节省带宽。
他当时使用的编码参数如下:
enc_params.rc_mode = MPP_ENC_RC_MODE_CBR;
enc_params.bps = 2000 * 1024; // 目标码率
ROI相关的参数配置为:
force_intra = 0;
qp_mode = 1; // 绝对QP模式
qp_val = 20;
对应的ROI处理逻辑代码如下:
if (enc_params.roi_enable) {
bool has_valid_roi = false;
const int MAX_ROI = 8;
int count = 0;
for (const auto& rect : roi_boxes) {
if (count >= MAX_ROI) break;
RK_S32 x = MPP_ALIGN(static_cast<RK_S32>(rect.x), 16);
RK_S32 y = MPP_ALIGN(static_cast<RK_S32>(rect.y), 16);
RK_S32 w = MPP_ALIGN(static_cast<RK_S32>(rect.width), 16);
RK_S32 h = MPP_ALIGN(static_cast<RK_S32>(rect.height), 16);
// 边界裁剪
if (w <= 0 || h <= 0 || x >= enc_params.width || y >= enc_params.height) continue;
if (x + w > enc_params.width) w = enc_params.width - x;
if (y + h > enc_params.height) h = enc_params.height - y;
if (w <= 0 || h <= 0) continue;
RoiRegionCfg region;
region.x = x;
region.y = y;
region.w = w;
region.h = h;
region.force_intra = 0;
region.qp_mode = 1;
region.qp_val = 20;
if (mpp_enc_roi_add_region(enc_params.roi_mpp_ctx, ®ion) == MPP_OK) {
has_valid_roi = true;
count++;
}
}
if (has_valid_roi) {
mpp_enc_roi_setup_meta(enc_params.roi_mpp_ctx, meta);
}
}
其中,RoiRegionCfg 结构体定义如下:

启用ROI编码后,虽然前景(吊车)清晰,背景产生了马赛克效果,但码率出现了剧烈突增,且不再受CBR(恒定码率)模式的约束。
后续,他将参数调整为相对QP模式:
region.force_intra = 0;
region.qp_mode = 0; // 相对QP模式
region.qp_val = -8;

这次码率恢复正常,但视觉效果的提升却不明显,前景不如之前清晰,背景也不再是明显的马赛克。
问题确认与根因分析
总结一下,问题表现为两种典型的矛盾现象:
- 绝对QP模式(qp_mode=1, qp_val=20):ROI区域画质提升效果显著,但码率完全失控。
- 相对QP模式(qp_mode=0, qp_val=-8):码率控制良好,但ROI区域的画质提升效果微乎其微。
| 场景 |
force_intra |
qp_mode |
qp_val |
效果 |
码率 |
| 未开启ROI |
- |
- |
- |
整体画质一致 |
正常~2Mbps |
| 开启ROI |
0 |
1(绝对) |
20 |
前景清晰,背景马赛克 |
突增,不受CBR约束 |
| 开启ROI |
0 |
0(相对) |
-8 |
效果不明显 |
正常~2Mbps |
问题的根源在于对MPP中ROI的QP调整模式理解不够深入。查阅Rockchip MPP源码中的注释(utils/mpp_enc_roi_utils.c)可以明确:
/*
* QP调整模式说明:
*
* qp_adj_mode = 1 (绝对QP模式):
* 16x16宏块的QP被设置为qp_adj的值,绕过RC计算的target_qp
*
* qp_adj_mode = 0 (相对QP模式):
* 16x16宏块的QP在RC计算的QP基础上调整qp_adj
* final_qp = rc_target_qp + qp_adj
*/
核心结论:在绝对QP模式下(qp_mode=1),ROI区域内每个宏块的QP值被直接固定为qp_val(例如20),完全绕过了码率控制器的计算和约束,这是导致码率失控的直接原因。而相对QP模式虽然遵从RC控制,但调整幅度qp_val = -8可能过小,不足以在有限码率预算内产生明显的画质差异。
解决方案
针对上述问题,可以从两个方向进行优化,开发者可以根据自身对码率严格性和画质提升幅度的要求进行选择。
方案一:优化相对QP模式参数(推荐)
此方案无需修改代码,仅需调整ROI参数,在保持CBR码率严格可控的前提下,追求显著的画质提升。
核心思路:继续使用相对QP模式,但增大QP的负向调整幅度。这样ROI区域的最终QP值会更低(画质更好),同时整体码率仍由RC控制器进行全局调配和约束。
参数调整建议:
调整值参考表:
| qp_val |
效果描述 |
适用场景 |
| -8 |
轻微提升,对比度不明显 |
ROI面积大(>30%) |
| -12 |
中等提升,有一定对比 |
ROI面积中等(15-30%) |
| -15 |
明显提升,对比清晰 |
ROI面积小(<15%) |
| -18 |
显著提升,对比强烈 |
ROI面积很小(≤10%) |
预期效果:
- 整体码率:稳定在2.0 ~ 2.2 Mbps(受CBR完美控制)。
- ROI区域:画质提升效果将根据
qp_val值和ROI面积变得明显。
- 兼容性:与CBR等所有RC模式完全兼容。
方案二:调整绝对QP模式及相关RC参数
此方案适用于可以接受一定码率波动,但追求ROI区域画质极致稳定(固定QP)的场景。
核心思路:仍然使用绝对QP模式,但同步提高ROI的绝对QP值(qp_val),并调整RC参数的范围以容纳ROI的固定QP,允许码率在一定范围内波动。
参数调整建议:
- 当前问题配置:
force_intra = 0;
qp_mode = 1; // 绝对QP
qp_val = 20; // 太低,导致码率翻倍
-
建议调试参数:
// ROI配置
force_intra = 0;
qp_mode = 1; // 绝对QP
qp_val = 26 ~ 28; // 提高QP值,减少码率突增
// RC配置(必须同步调整)
rc_cfg.qp_min = 20; // 必须覆盖ROI的绝对QP值
rc_cfg.qp_max = 45;
rc_cfg.qp_min_i = 18;
rc_cfg.qp_max_i = 42;
// 允许码率有一定波动
rc_cfg.bps_target = 2000 * 1024;
rc_cfg.bps_max = 2500 * 1024; // 允许25%波动
// 降低I帧比例,为ROI留出码率空间
rc_cfg.max_i_bit_prop = 30; // 默认值可能较高
rc_cfg.min_i_bit_prop = 10;
使用要点与预期结果:
- ROI面积限制:在绝对QP模式下,为避免码率波动过大,ROI区域面积建议小于画面总面积的15%。
- QP范围检查:必须确保
rc_cfg.qp_min <= roi_qp_val <= rc_cfg.qp_max,否则参数可能不生效或产生异常。
- 码率波动:预期整体码率会有±15%~25%的波动,但处于可接受的上限(
bps_max)之内。
方案验证与反馈
将上述两个方案提供给开发者进行验证。反馈结果表明,方案一(优化相对QP参数)取得了符合预期的效果,在码率受控的前提下,ROI区域的画质得到了有效提升。

总结
RK MPP的ROI功能是一个强大的工具,但要驾驭好它,关键在于理解qp_mode两种模式的本质区别及其与码率控制器的交互关系。
- 追求严格码率控制:选择相对QP模式(qp_mode=0),并尝试将
qp_val调整至-12或更低。
- 追求ROI画质绝对稳定:选择绝对QP模式(qp_mode=1),但务必同步提高
qp_val值(如26~28)并放宽RC的码率和QP上下限约束。
合理的参数调优是嵌入式多媒体系统设计中的关键一环。希望本次对RK3588平台MPP编码ROI功能的调优经验,能为遇到类似问题的开发者提供一些参考。如果你有更好的参数组合或不同的应用场景经验,欢迎在云栈社区进行分享与探讨。