资讯动态

030、安防NVR多路编码架构——瑞芯微RK3588的ISP与VPU协同处理多路码流的带宽调度

发布时间:2026/8/12 17:46:30 来源:尧图企业网站定制
030、安防NVR多路编码架构——瑞芯微RK3588的ISP与VPU协同处理多路码流的带宽调度从一次“画面冻结”的深夜告警说起凌晨两点客户现场一台16路NVR突然上报“通道3、7、11画面同时冻结”但设备没死机WEB页面还能登录回放也正常。远程抓了内核日志看到一堆vpu_service: timeout和isp_mmu: page fault交替出现。当时第一反应是VPU挂了但重启VPU服务后故障依旧。后来把码流从1080p30fps降到720p15fps问题消失——这根本不是VPU硬件故障是带宽调度被击穿了。RK3588这颗芯片ISP和VPU在硬件上各自独立但它们在DDR带宽、AXI总线仲裁、以及驱动层的buffer管理上共享着同一套资源池。多路码流同时启动编码的瞬间带宽峰值叠加谁抢到算谁的抢不到的就丢帧、超时、报错。RK3588的ISP与VPU别被“独立”两个字骗了RK3588的ISP是双路ISP实际是两套ISP核心每套支持多路sensor输入VPU是独立的编解码单元支持H.264/H.2658K30fps编码或者多路1080p同时编码。从硬件框图看ISP和VPU各自挂在不同的AXI端口上中间隔着DDR控制器。但问题恰恰出在这里——它们最终都要访问同一个DDR。RK3588的DDR带宽是有限的标称是64bit LPDDR4/4X频率最高2133MHz理论带宽大概34GB/s。听起来很大但你要算一笔账一路1080p30fps的YUV420数据从sensor进ISPISP输出到内存再被VPU读走做编码这一进一出就是两次带宽消耗。16路同时跑光YUV数据搬运就吃掉将近12GB/s。再加上ISP的3A统计、VPU的参考帧读写、系统其他模块GPU、CPU、DMA的占用实际可用带宽可能只剩一半。更关键的是RK3588的DDR控制器有QoSQuality of Service设置每个AXI端口有优先级权重。默认配置下ISP和VPU的优先级是平级的谁先发起请求谁先被响应。当多路sensor同时出帧ISP的写请求会瞬间占满DDR队列VPU的读请求被堵在后面于是VPU等不到数据报timeout。反过来如果VPU正在做高码率编码大量写码流数据ISP的3A统计可能被延迟导致曝光调节滞后画面闪烁。真正的坑驱动层的buffer分配策略硬件带宽调度只是第一层驱动层的buffer管理才是真正让人头疼的地方。RK3588的ISP驱动rkisp和VPU驱动mpp各自维护自己的buffer池。默认情况下ISP输出的YUV帧是连续物理内存通过DMA分配VPU编码时直接拿这个物理地址做输入。听起来高效但问题在于当多路sensor同时出帧ISP驱动会一次性申请大量连续物理内存。如果系统内存碎片化严重申请失败ISP驱动会退而求其次用分散内存scatter-gather但VPU驱动对输入buffer有对齐要求通常是256字节对齐分散内存的每个page可能不满足对齐条件于是VPU驱动报invalid parameter。这个错误在用户态看起来就是“编码失败”但日志里根本不会直接告诉你buffer不对齐。我们当时排查了很久最后是在mpp的调试日志里看到mpp_enc: input addr not aligned才定位到。解决办法有两个一是让ISP驱动在初始化时就预留一块足够大的连续内存池通过CMA配置二是修改VPU驱动的输入buffer校验逻辑允许非对齐地址但性能会下降约5%。我们最终选了CMA方案在dts里给ISP的cma-pool分配了256MB问题彻底消失。带宽调度的实战配置别信默认值RK3588的带宽调度核心在/sys/kernel/debug/dri/0/summary这个节点不同内核版本路径可能不同。你可以看到每个IP的实时带宽占用和优先级。默认情况下ISP和VPU的优先级都是MEDIUM这在高负载下就是灾难。我们实际调优时把ISP的优先级设为HIGHVPU设为MEDIUM同时把GPU和CPU的DMA优先级降到LOW。原因很简单ISP是实时性要求最高的模块它一旦丢帧整个链路都受影响VPU编码可以容忍一定的延迟只要buffer够多但ISP的3A统计延迟会导致画面质量下降。具体操作是在dts的qos节点里配置isp0_qos { priority { read 0x2; /* HIGH */ write 0x2; }; }; vpu_qos { priority { read 0x1; /* MEDIUM */ write 0x1; }; };这里踩过坑priority的值不是简单的0/1/2不同内核版本定义不同。在5.10内核上0x0是LOW0x1是MEDIUM0x2是HIGH。但有些vendor分支的驱动会反转这个映射所以改完一定要看summary节点里的实际生效值别只看dts。多路码流的帧率控制VPU的GOP与ISP的帧率要联动另一个容易被忽视的点是ISP和VPU的帧率匹配。NVR场景下sensor通常以固定帧率输出比如25fps但VPU编码时如果设置了动态GOP比如I帧间隔根据场景变化会导致VPU的输入buffer需求波动。当场景剧烈变化时VPU需要更多参考帧buffer占用飙升如果ISP输出帧率不变buffer池会被瞬间填满新帧无处存放ISP驱动会丢帧。我们遇到的情况是16路中某几路画面里有人走动VPU的GOP自动调整导致这几路的编码延迟增大其他路的带宽被挤占最终表现为“部分通道画面卡顿”。解决办法是关闭VPU的动态GOP固定I帧间隔比如2秒一个I帧同时把ISP的输出帧率限制在编码帧率的1.2倍以内比如编码25fpsISP输出最多30fps。这样buffer的消耗是线性的不会出现突发峰值。实测数据不同配置下的带宽占用我们在一台RK3588开发板上做了实测16路1080p25fpsH.265编码码率4Mbps。默认配置下系统总带宽占用约28GB/s已经接近DDR极限偶发VPU timeout。调整优先级后带宽占用降到24GB/s但ISP的写带宽占比从40%升到55%VPU的读带宽从35%降到25%整体稳定。再把CMA从128MB加到256MB后buffer分配失败率从0.3%降到0.01%以下。最终稳定运行72小时无故障。经验性建议非教科书如果你正在做RK3588的NVR方案我建议你从第一天就把带宽调度当做一个独立模块来设计而不是等出了问题再调。具体来说第一dts里给ISP和VPU的CMA预留足够空间别省内存256MB起步宁可让系统少点可用内存也别让buffer分配失败。第二QoS优先级一定要改默认配置就是给量产埋雷。第三VPU的GOP固定别用动态GOP除非你确认场景变化不频繁。第四调试时多用/sys/kernel/debug/dri/0/summary和/proc/mpp_service这两个节点它们能告诉你真实的带宽和buffer状态比看应用层日志有用得多。最后别迷信“RK3588支持8K编码”这种宣传多路并发时实际能力取决于你的带宽调度做得好不好而不是芯片标称值。我们后来在另一个项目里用了同样的配置只是把sensor从4路加到8路就出现了新的带宽瓶颈——这次是DDR的bank冲突不是优先级问题。所以带宽调度是个持续调优的过程没有一劳永逸的配置。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价