在智能视觉设备开发中,多路视频编码与动态信息叠加是核心需求。瑞芯微RV1126/RV1109凭借其强大的媒体处理能力,配合RKMEDIA框架,为开发者提供了高效的解决方案。本文将深入探讨如何基于RKMEDIA实现两路1080P H.264编码,并解决OSD叠加中的色彩偏差、刷新机制等实际问题。
RV1126/RV1109的媒体处理能力建立在MPP(Media Process Platform)基础上,RKMEDIA作为上层封装,简化了开发流程。在开始编码前,需确保:
CONFIG_VIDEO_ROCKCHIP_MPP选项关键硬件参数对比:
| 参数 | RV1126 | RV1109 |
|---|---|---|
| 最大编码路数 | 4路1080P@30fps | 2路1080P@30fps |
| 编码格式支持 | H.264/H.265/MJPEG | H.264/MJPEG |
| 硬件加速单元 | 独立NPU+VPU | 共享VPU |
提示:多路编码时需计算总带宽需求,1080P@30fps单路约需100MB/s内存带宽
实现两路独立编码需要分别配置VENC通道参数。以下示例展示H.264 CBR模式初始化:
c复制// 通道0配置
VENC_CHN_ATTR_S chn0_attr = {
.stVencAttr = {
.enType = RK_CODEC_TYPE_H264,
.imageType = IMAGE_TYPE_NV12,
.u32PicWidth = 1920,
.u32PicHeight = 1080,
.u32Profile = 77 // Main Profile
},
.stRcAttr = {
.enRcMode = VENC_RC_MODE_H264CBR,
.stH264Cbr = {
.u32Gop = 30,
.u32BitRate = 1920 * 1080 * 1.5, // 经验值
.fr32DstFrameRateDen = 1,
.fr32DstFrameRateNum = 30
}
}
};
// 通道1配置(可不同参数)
VENC_CHN_ATTR_S chn1_attr = { ... };
RK_MPI_VENC_CreateChn(0, &chn0_attr);
RK_MPI_VENC_CreateChn(1, &chn1_attr);
实际项目中常遇到帧率不稳问题,需注意:
SrcFrameRateNum/DstFrameRateNum决定丢帧策略c复制VENC_RC_PARAM_S rc_param;
RK_MPI_VENC_GetRcParam(0, &rc_param);
// 优化QP参数(监控场景示例)
rc_param.stParamH264 = {
.u32MinQp = 25,
.u32MaxQp = 45,
.u32MinIQp = 20,
.u32MaxIQp = 40,
.u32StepQp = 3
};
RK_MPI_VENC_SetRcParam(0, &rc_param);
典型帧率问题排查步骤:
/proc/mpp_service/session_summary确认各通道状态cat /sys/kernel/debug/clk/clk_summary | grep enc查看编码器时钟echo 600000000 > /proc/mpp_service/rkvenc/clk_coreRKMEDIA提供区域管理接口实现OSD叠加,但需注意ARGB8888格式限制:
c复制// 创建160x160的透明背景LOGO
BITMAP_S bitmap = {
.enPixelFormat = PIXEL_FORMAT_ARGB_8888,
.u32Width = 160,
.u32Height = 160,
.pData = malloc(160 * 160 * 4)
};
// 填充位图数据(示例为左上角红色矩形)
for (int i = 0; i < 160*160; i++) {
((uint32_t*)bitmap.pData)[i] = (i%160 < 80 && i/160 < 80) ? 0xFFFF0000 : 0x00000000;
}
// 配置叠加区域
OSD_REGION_INFO_S rgn_info = {
.enRegionId = REGION_ID_0,
.u32PosX = 20,
.u32PosY = 20,
.u32Width = 160,
.u32Height = 160,
.u8Enable = 1
};
RK_MPI_VENC_RGN_SetBitMap(0, &rgn_info, &bitmap);
实时更新OSD需要特殊处理:
c复制// 时间戳更新线程
void* osd_update_thread(void* arg) {
while(running) {
time_t now = time(NULL);
struct tm *tm = localtime(&now);
// 在新的缓冲区渲染文字
char text[32];
sprintf(text, "%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec);
render_text_to_buffer(text, new_bitmap);
// 原子切换缓冲区
pthread_mutex_lock(&osd_mutex);
swap_buffers(&active_bitmap, &new_bitmap);
RK_MPI_VENC_RGN_SetBitMap(0, &rgn_info, active_bitmap);
pthread_mutex_unlock(&osd_mutex);
usleep(100000); // 100ms更新一次
}
return NULL;
}
注意:频繁调用SetBitMap可能导致编码延迟,建议控制刷新率在10Hz以内
当同时运行两路1080P编码时,需合理分配系统资源:
bash复制taskset -cp 0-3 <pid> # 绑定到前四个核心
/etc/init.d/S00mount增加echo performance > /sys/class/devfreq/dmc/governorrkbin/RKBOOT/RV1126MINIALL.ini中的DDR参数问题1:OSD色彩失真
现象:叠加的彩色LOGO出现色偏
原因:VENC只支持256色区域叠加
解决方案:
问题2:第二路编码启动失败
排查步骤:
dmesg | grep mpp是否有硬件错误bash复制cat /proc/mpp_service/bandwidth
问题3:编码延迟累积
优化方案:
c复制venc_chn_attr.stRcAttr.stH264Cbr.u32Gop = 15; // 从30调整为15
c复制rc_param.stParamH264.bEnableLowDelay = RK_TRUE;
以下代码片段展示了一个典型的多路编码带OSD应用框架:
c复制int main() {
// 1. 系统初始化
RK_MPI_SYS_Init();
// 2. 创建两路编码通道
init_venc_channel(0, 1920, 1080);
init_venc_channel(1, 1280, 720);
// 3. 初始化OSD资源
init_osd_resources();
// 4. 绑定VI到VENC
RK_MPI_SYS_Bind(&vi_dev, &venc_chn0);
RK_MPI_SYS_Bind(&vi_dev, &venc_chn1);
// 5. 启动OSD更新线程
pthread_create(&osd_thread, NULL, osd_update_thread, NULL);
// 6. 主循环处理编码数据
while(1) {
MEDIA_BUFFER mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, 0, -1);
if (mb) process_stream(mb, 0);
mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_VENC, 1, -1);
if (mb) process_stream(mb, 1);
}
// ...资源释放代码
}
实际部署中发现,当环境温度较高时,芯片降频会导致编码帧率下降。通过修改温控策略可缓解此问题:
bash复制echo user_space > /sys/class/thermal/thermal_zone0/policy
echo 85000 > /sys/class/thermal/thermal_zone0/trip_point_0_temp