RKMEDIA实战入门:从零搭建瑞芯微RV1126/RV1109媒体处理流水线
1. 认识RKMEDIA与RV1126/RV1109开发环境
如果你刚拿到一块瑞芯微RV1126或RV1109开发板,想要快速搭建视频处理流水线,RKMEDIA绝对是你的首选工具。这个由瑞芯微官方提供的多媒体框架,把复杂的底层硬件操作封装成了简单的API接口。我刚开始接触时也犯怵——VI、VENC、RGA这些模块名称看起来就让人头大,但实际用起来会发现它就像乐高积木,只要掌握拼接逻辑就能组合出强大功能。
先说说硬件准备。RV1126和RV1109这对兄弟芯片虽然定位不同(前者主打AI视觉,后者侧重轻量级应用),但媒体处理架构完全一致。我手头的RV1126开发板标配MIPI摄像头接口、HDMI输出和3.5mm音频口,建议你准备:
- 支持1080p的MIPI摄像头(如OV13850)
- 至少32GB的TF卡(刷好官方SDK)
- 带散热片的Type-C电源(持续运行时芯片会发热)
开发环境搭建有个小坑要注意:官方SDK默认使用buildroot系统,建议在Ubuntu 18.04/20.04上编译。我第一次在Windows WSL里折腾了半天,最后发现DRM显示驱动根本跑不起来。正确的姿势是:
# 在SDK根目录执行 source envsetup.sh rockchip_rv1126_rv1109 make rkmedia-dirclean && make rkmedia-rebuild编译生成的库文件会出现在buildroot/output/rockchip_rv1126_rv1109/oem/usr/lib/,记得用ldd检查动态库依赖是否完整。
2. 媒体流水线搭建实战
2.1 视频采集(VI模块)初始化
VI模块相当于流水线的"水龙头",负责从摄像头获取原始数据。配置时最常遇到的就是分辨率不匹配的问题。以OV13850为例,虽然支持4224x3136分辨率,但RV1126的ISP最大只支持2688x1520,我的建议配置是:
VI_CHN_ATTR_S vi_attr = { .pcVideoNode = "rkispp_scale0", // 使用ISP缩放通道 .u32Width = 1920, .u32Height = 1080, .enPixFmt = IMAGE_TYPE_NV12, // 推荐格式 .enBufType = VI_CHN_BUF_TYPE_MMAP, .u32BufCount = 3, // 三缓冲避免卡顿 }; RK_MPI_VI_SetChnAttr(0, &vi_attr); // 通道0 RK_MPI_VI_EnableChn(0);这里有个实战技巧:通过v4l2-ctl工具先验证摄像头是否正常:
v4l2-ctl -d /dev/video0 --list-formats-ext v4l2-ctl --set-fmt-video=width=1920,height=1080,pixelformat=NV122.2 视频处理(RGA模块)妙用
RGA模块是瑞芯微的独门武器,这个2D加速器能零拷贝处理图像。我最常用的三个功能:
- 格式转换:把VI输出的NV12转成RGB888给AI模型输入
- 缩放处理:1080p降采样到640x360节省编码带宽
- 旋转镜像:应对倒装摄像头场景
配置示例:
RGA_ATTR_S rga_attr = { .bEnBufPool = RK_TRUE, .u16BufPoolCnt = 3, .u16Rotaion = 0, .stImgIn = { .u32X = 0, .u32Y = 0, .u32Width = 1920, .u32Height = 1080, .enFormat = RK_FMT_YCrCb420_SP, }, .stImgOut = { .u32X = 0, .u32Y = 0, .u32Width = 640, .u32Height = 360, .enFormat = RK_FMT_RGB888, } }; RK_MPI_RGA_CreateChn(0, &rga_attr);实测发现RGA处理一帧1080p到720p的缩放仅需2ms,比OpenCV快20倍以上。但要注意内存对齐要求:宽度必须是16的倍数,否则会出现绿边现象。
3. 编码与显示关键配置
3.1 硬件编码(VENC模块)优化
RV1126的H.264编码器支持CBR/VBR/AVBR三种模式。直播推流建议用CBR,本地存储用VBR效果更好。这是我调试出的最佳参数:
VENC_CHN_ATTR_S venv_attr = { .stVencAttr = { .enType = RK_CODEC_TYPE_H264, .u32PicWidth = 1280, .u32PicHeight = 720, .u32BufSize = 1920*1080, }, .stRcAttr = { .enRcMode = VENC_RC_MODE_H264VBR, .stH264Vbr = { .u32Gop = 30, .u32BitRate = 4000000, // 4Mbps .u32MaxBitRate = 6000000, .u32MinQp = 24, .u32MaxQp = 48, } } }; RK_MPI_VENC_CreateChn(0, &venv_attr);遇到过编码花屏的问题,最后发现是GOP设置过大导致I帧间隔太长。建议在移动场景下GOP不要超过30帧,静态场景可以设到60帧。
3.2 视频输出(VO模块)调试技巧
VO模块支持HDMI、LCD和CVBS三种输出。开发时最头疼的是显示比例失调,正确的多屏适配姿势是:
VO_CHN_ATTR_S vo_attr = { .pcDevNode = "/dev/dri/card0", // DRM设备节点 .u32DisplayType = VO_DISPLAY_TYPE_HDMI, .u32Width = 1920, .u32Height = 1080, .enPixFmt = RK_FMT_ARGB8888, }; RK_MPI_VO_SetChnAttr(0, &vo_attr);如果出现画面撕裂,可以开启垂直同步:
echo 1 > /sys/class/drm/card0-HDMI-A-1/vrr_capable4. 模块绑定与性能调优
4.1 数据流绑定实战
RKMEDIA的精髓在于模块间的绑定关系。以完整的摄像头→编码→显示流程为例:
// VI→RGA→VENC→VO绑定 MPP_CHN_S vi_chn = { .enModId = RK_ID_VI, .s32ChnId = 0 }; MPP_CHN_S rga_chn = { .enModId = RK_ID_RGA, .s32ChnId = 0 }; RK_MPI_SYS_Bind(&vi_chn, &rga_chn); MPP_CHN_S venv_chn = { .enModId = RK_ID_VENC, .s32ChnId = 0 }; RK_MPI_SYS_Bind(&rga_chn, &venv_chn); MPP_CHN_S vo_chn = { .enModId = RK_ID_VO, .s32ChnId = 0 }; RK_MPI_SYS_Bind(&venv_chn, &vo_chn);绑定顺序很重要,我曾因为先绑VO再绑VENC导致黑屏。推荐使用media-ctl工具实时查看拓扑:
media-ctl -p -d /dev/media04.2 性能优化三板斧
内存优化:启用ION内存池减少拷贝
MPP_CHN_S chn_attr = { .enModId = RK_ID_VI, .s32ChnId = 0 }; RK_MPI_SYS_SetChnDebugLevel(&chn_attr, RK_LOG_LEVEL_DEBUG);线程优化:为每个模块分配独立线程
echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor带宽监控:用
rkmedia_demo自带的统计功能export RKMEDIA_LOG_LEVEL=DBG ./rkmedia_vi_venc_vo_test -i /dev/video0 -o hdmi
最后分享个真实案例:某次客户需要同时处理4路1080p视频,直接跑发现帧率掉到8fps。通过将RGA输出降采样到720p,VENC改用H265编码,最终稳定在25fps。关键是要活用RKMEDIA的模块化设计,像搭积木一样组合出最优方案。
