012、安防NVR/DVR多路编码架构:海思Hi3516与瑞芯微RK3588的ISP与编码协同 012、安防NVR/DVR多路编码架构海思Hi3516与瑞芯微RK3588的ISP与编码协同去年年底接了个项目客户要把老旧的DVR方案从海思Hi3516DV300整体切到瑞芯微RK3588理由是算力不够要上AI。结果板子回来第一天8路1080P预览就卡成PPTCPU占用飙到85%编码器利用率才60%。查了半天问题出在ISP输出格式和编码器输入格式的匹配上——海思的VI通道默认输出NV12RK3588的ISP默认输出NV12但带了个奇怪的stride对齐而编码器那边又要求按16字节对齐。就这么个看似不起眼的差异导致编码器每次都要做一次内存拷贝8路下来带宽直接打满。先聊海思的架构。Hi3516DV300这颗芯片ISP和编码器是紧耦合设计的VIVideo Input通道直接挂VGSVideo Graphics Subsystem做缩放和格式转换然后进VENCVideo Encoder。它的数据通路是ISP - VI - VGS - VENC中间有个关键点VI通道的buffer是硬件管理的支持按帧自动轮转而且VGS可以做到零拷贝的格式转换——只要你的目标格式和源格式在同一个内存池里VGS直接改描述符就行不搬数据。这个设计在安防场景非常实用因为NVR/DVR的典型需求是8路1080P输入同时要出4路CIF子码流和1路主码流海思的VGS可以一条命令链搞定一路画面的多路缩放而且带宽开销极小。瑞芯微这边就完全是另一套思路。RK3588的ISP实际是RKISP3.x输出走的是RGARaster Graphic Acceleration或者直接进VPUVideo Processing Unit的编码器。RGA是个2D图形加速器能做缩放、旋转、格式转换但它的设计初衷是给UI合成用的不是给视频管线用的。问题在于RGA的输入输出格式要求非常严格比如NV12输入要求宽度按16对齐高度按2对齐而且它的stride行字节数计算方式跟海思的VGS不一样——海思是按实际宽度算strideRK3588是按对齐后的宽度算。这就导致你从ISP拿到的buffer如果直接丢给编码器编码器会按自己的对齐规则去读读出来的画面就是斜的或者花屏。我在RK3588上调第一版的时候就是直接ISP输出NV12丢给MPPMedia Process Platform的编码器结果8路里有3路画面是歪的查了半天发现是stride不匹配。海思的VI通道会自动帮你把stride对齐到编码器要求的值RK3588的ISP不会你得自己在RGA或者CPU里做一次拷贝。后来我改成ISP输出NV12_MST多平面格式然后通过RGA做一次格式转换到NV12同时指定输出stride为编码器要求的对齐值问题就解决了。但代价是每路多了一次RGA操作8路下来RGA的负载到了40%左右好在RK3588的RGA有3个核可以并行。再说编码器本身的差异。海思的VENC是硬编码器支持H.264/H.265但它的码控策略比较保守尤其是CBR模式在场景切换剧烈的时候会突然掉帧。RK3588的VPU编码器码控更激进但有个坑它的GOPGroup of Pictures结构默认是IDR帧间隔等于GOP大小不像海思那样支持自适应IDR插入。在安防场景这意味着如果网络丢包导致关键帧丢失海思的方案会在下一个IDR自动恢复RK3588可能要等很久。解决办法是在应用层做强制IDR请求但MPP的接口里这个功能藏得比较深得用MPP_ENC_SET_CFG配合MppEncRcCfg里的gop_mode参数设成GOP_MODE_NORMAL然后手动触发MPP_ENC_SET_IDR_FRAME。还有个容易踩的坑是内存分配。海思的mpp注意海思的mpp是Media Process Platform跟瑞芯微的MPP同名但完全不同的东西内存池是统一管理的你申请buffer的时候指定MMB_VI、MMB_VGS、MMB_VENC这些属性系统会自动做cache一致性管理。RK3588的MPP用的是dma_buf你得自己保证cache同步否则会出现编码出来的画面有随机噪点——尤其是ISP写入buffer后CPU或者RGA读的时候如果没做dma_buf_sync那画面就是花的。我一开始没注意这个调试了三天最后用dma_buf_begin_cpu_access和dma_buf_end_cpu_access包住RGA操作才解决。多路编码的调度策略也完全不同。海思的VENC是硬件多路并行每路独立编码你只需要配置好通道参数硬件自己调度。RK3588的VPU虽然也是多路并行但它的编码器核是共享的如果一路的码率控制参数设置不当比如码率上限设太高会挤占其他路的带宽导致其他路画面质量下降。我做过一个测试8路1080P同时编码如果一路设成4Mbps其他路设成2Mbps结果那路4Mbps的实际码率能跑到5Mbps其他路掉到1.5Mbps。后来我把所有路的rc_mode设成MPP_RC_MODE_CBR并且把max_i_bit_rate和max_p_bit_rate都设成跟目标码率一致才把这个问题压住。再说说ISP和编码器协同的延迟问题。安防场景对延迟敏感尤其是PTZ控制的时候从云台转动到画面更新延迟超过200ms就感觉卡顿。海思的ISP到VENC的延迟大约在40ms左右因为VI通道是零拷贝直通的。RK3588这边ISP输出到RGA再进VPU每级都有buffer排队延迟轻松到80ms以上。我试过用RK3588的ISP直接输出到VPU的mpp_buffer绕过RGA但ISP的输出格式是NV12_MSTVPU编码器不支持必须转。后来发现RK3588的ISP有个rkisp_vir节点可以配置输出NV12非MST但这样会牺牲一些ISP的3A统计功能。权衡之下我选择了保留RGA转换但把RGA的buffer池缩小减少排队延迟最终做到60ms左右勉强能接受。最后说产线调试的经验。海思的方案产线上主要用himm工具直接改寄存器调试方便但风险高改错了直接死机。RK3588的调试工具是rk_mpi_aiq和rkisp_demo可以在线调3A参数但它的日志系统比较啰嗦建议用export RK_LOG_LEVEL2只打错误信息。另外瑞芯微的MPP有个mpp_info命令可以查看编码器状态包括每路的帧率、码率、编码耗时这个对产线测试非常有用海思那边没有直接对应的工具得自己写脚本解析/proc下的统计信息。总结一下我的经验如果项目是纯安防NVR/DVR没有AI需求海思Hi3516系列依然是更稳的选择它的ISP和编码器协同是经过十几年量产验证的坑少。如果一定要上RK3588做AI那就要接受它的架构差异重点做好三件事一是统一stride对齐策略二是管好dma_buf的cache同步三是用MPP的码控参数把多路编码的带宽隔离做好。别指望RK3588能像海思那样开箱即用它的优势在算力不在影像管线你得花时间把管线调顺。