RKMEDIA实战入门:从零搭建瑞芯微RV1126/RV1109媒体处理流水线

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=NV12

2.2 视频处理(RGA模块)妙用

RGA模块是瑞芯微的独门武器,这个2D加速器能零拷贝处理图像。我最常用的三个功能:

  1. 格式转换:把VI输出的NV12转成RGB888给AI模型输入
  2. 缩放处理:1080p降采样到640x360节省编码带宽
  3. 旋转镜像:应对倒装摄像头场景

配置示例:

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_capable

4. 模块绑定与性能调优

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/media0

4.2 性能优化三板斧

  1. 内存优化:启用ION内存池减少拷贝

    MPP_CHN_S chn_attr = { .enModId = RK_ID_VI, .s32ChnId = 0 }; RK_MPI_SYS_SetChnDebugLevel(&chn_attr, RK_LOG_LEVEL_DEBUG);
  2. 线程优化:为每个模块分配独立线程

    echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
  3. 带宽监控:用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的模块化设计,像搭积木一样组合出最优方案。