ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

RK3588硬件拼接实战:8路1080P实时合成4K全景

2026/10/7 6:31:18 拓冰建站 浏览量
RK3588硬件拼接实战:8路1080P实时合成4K全景 1. 项目缘起与整体设计思路1.1 为什么要在RK3588上做8路1080P实时拼接先说说这个需求的来源。我手头有一个多摄像头环视项目8个1080P摄像头分别朝向不同角度需要把画面实时拼接成一张无缝的全景图输出给上层做目标检测和人工监看。一开始想的是把8路流全部拉到上位机用软件拼接结果一算带宽就放弃了——8路1080P30fps的原始YUV数据每帧约3MB8路就是24MB30fps下每秒720MB的吞吐光传输和内存拷贝就能把CPU吃满更别提实时性了。后来把目光转向RK3588原因很直接这颗芯片自带AVSAudio Video Stitching硬件拼接模块能在VPU和ISP之后、显示或编码之前直接把多路视频在硬件层面拼成一张大图。这意味着拼接这件事不占用CPU算力也不用来回搬数据功耗和延迟都能压下来。对于嵌入式端侧的多路视频融合场景这几乎是目前性价比最高的方案。这个项目适合谁看如果你正在做多摄像头环视、鱼眼全景、大场景监控、车载360或者任何需要“多路视频合成一张图”的嵌入式项目并且手上有RK3588的开发板那这篇内容基本可以当作一份实操参考。我会把AVS模块的配置逻辑、数据链路、参数计算、踩过的坑都摊开讲尽量让你少走弯路。1.2 AVS模块到底解决了什么问题很多人第一次听到AVS会以为是音频那个AVS编码标准其实在RK3588的语境里AVS指的是视频拼接硬件单元。它的核心能力是接收多路视频输入按照配置的布局关系把每一路缩放到目标区域然后叠加到一张输出画布上整个过程在硬件流水线里完成。它解决的核心痛点是三个算力卸载软件拼接需要CPU或GPU做缩放、色彩转换、内存拷贝8路1080P的负载非常可观。AVS把这些活接过去CPU只负责配置和调度。确定性延迟硬件流水线的延迟是固定的不会因为系统负载波动而抖动这对实时监看和后续算法处理很关键。带宽优化拼接后的输出是一张大图下游只需要处理一路数据而不是八路内存带宽和后续编码压力都大幅下降。但要注意AVS不是万能的。它做的是几何拼接也就是把多路画面按位置摆放到一张画布上并不做图像内容层面的融合、去重、光流对齐。如果你需要的是无缝的、没有重叠区域的全景融合那AVS只能完成前半程后半程的融合算法还得自己补。这一点在方案设计阶段就要想清楚否则后期会返工。1.3 整体数据链路的规划在动手之前我先把整条链路画清楚这比直接改代码重要得多。RK3588的视频输入路径大致是这样的摄像头通过MIPI CSI进入ISPISP输出到内存然后可以选择送到AVS、VOP显示控制器或者VENC编码器。我的方案是8路摄像头分别经过ISP处理输出1080P的NV12数据到DDR然后AVS从DDR读取这8路数据按照2行4列的布局拼成一张3840x2160也就是4K的大图最后把这张大图同时送给VENC编码成H.264做推流以及送给VOP做本地预览。这里有个关键决策为什么选2x4布局而不是其他排列。8路1080P如果按1x8排输出就是7680x1080横向太长很多显示器和编码器对超宽分辨率支持不好按4x2排是3840x2160正好是标准4K编码和显示都友好按2x4排是3840x2160同样标准。最终我选2行4列因为摄像头物理安装是上下两排每排4个这样拼接后的画面方向和实际场景一致监看时不会产生空间错乱。提示布局选择不只看分辨率是否标准还要考虑摄像头实际安装方位和后续算法的坐标映射。如果拼接图和物理世界方向不一致后面做目标定位时会非常痛苦。2. AVS核心细节与配置要点解析2.1 AVS的输入输出格式约束在配置AVS之前必须搞清楚它对输入输出的格式要求否则会出现“配置成功但画面花屏”的情况。根据我的实测和RK3588的文档AVS模块对输入格式有几个硬性约束输入必须是YUV格式常见的是NV12Y平面加交错UV平面。RGB数据需要先经过转换这一步通常在ISP或RGA里完成。每路输入的宽高需要是偶数1080P是1920x1080满足要求。输入路数有上限RK3588的AVS支持最多8路输入这正好卡在我们的需求上再多就不行了。输出画布的宽高也有范围限制4K3840x2160是安全的再大需要确认具体SDK版本的支持情况。输出格式同样建议用NV12这样送给VENC时不需要额外转换。如果你想让输出直接给VOP显示NV12也是VOP支持的格式链路最顺。这里有个容易忽略的点输入和输出的色彩空间要一致。如果输入是BT.601而输出配成了BT.709颜色会明显偏掉。我在第一次调试时就遇到了肤色发灰的问题查了半天才发现是色彩空间没对齐。2.2 拼接布局与坐标计算AVS的布局配置本质上就是告诉硬件第0路画面放在画布的哪个位置第1路放在哪里以此类推。每个位置用四个参数描述起始X坐标、起始Y坐标、宽度、高度。以2行4列、每路1080P、输出4K为例计算过程如下输出画布宽3840高2160。每格宽度 3840 / 4 960每格高度 2160 / 2 1080。第0路x0, y0, w960, h1080。第1路x960, y0, w960, h1080。第2路x1920, y0, w960, h1080。第3路x2880, y0, w960, h1080。第4路x0, y1080, w960, h1080。以此类推到第7路。注意这里每格宽度是960而输入是1920宽所以AVS会自动做水平方向2:1的缩放。这个缩放是硬件完成的不需要你额外配置。但缩放会带来画质损失如果你不能接受就需要调整布局让每格宽度接近1920比如改成4行2列每格1920x540但这样垂直方向又压缩了。这是一个取舍取决于你更在意水平细节还是垂直细节。注意缩放比例不要超过硬件限制。RK3588的AVS缩放能力有范围极端比例可能导致画面模糊或硬件报错。建议单方向缩放比控制在4:1以内。2.3 内存与带宽的预估8路1080P NV12输入每帧大小 1920 * 1080 * 1.5 3110400字节约3MB。8路就是24MB。30fps下输入侧每秒需要AVS读取720MB。输出4K NV12每帧 3840 * 2160 * 1.5 12441600字节约12MB30fps下输出侧每秒写入360MB。加起来AVS模块每秒要处理超过1GB的内存读写。这对DDR带宽是有压力的尤其是在同时还有ISP写入、VENC读取、CPU访问的情况下。我的经验是一定要给视频链路预留足够的DDR带宽在设备树里把相关总线的优先级调高否则会出现丢帧或画面撕裂。实测中如果DDR带宽吃紧最明显的表现是AVS输出偶尔出现一条横向撕裂线或者某一路画面突然黑一下。这时候不要怀疑代码先去查带宽和时钟配置。3. 实操过程与关键环节实现3.1 环境准备与内核配置我用的SDK是RK3588官方Linux SDK内核版本5.10。第一步是确认AVS驱动已经编进内核。在menuconfig里路径是Device Drivers - Media drivers - Rockchip Video Processing - Rockchip AVS把它选成编译进内核或模块。设备树里需要配置AVS节点关键字段包括avs: avsfdb00000 { compatible rockchip,rk3588-avs; reg 0x0 0xfdb00000 0x0 0x10000; interrupts GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH; clocks cru ACLK_AVS, cru HCLK_AVS; clock-names aclk, hclk; power-domains power RK3588_PD_AVS; status okay; };同时要确保8路ISP和CSI的节点都使能并且各自绑定到正确的摄像头。这一步如果出错后面AVS拿不到输入数据表现是输出全黑或全绿。3.2 通过V4L2配置AVSAVS在用户态通过V4L2接口操作设备节点通常是/dev/videoX。配置流程分几步打开设备查询能力确认支持VIDIOC_QUERYCAP。设置输出格式也就是拼接后的画布格式用VIDIOC_S_FMT格式NV12宽3840高2160。设置输入路数和每路的布局这部分RK3588用了私有扩展控制项需要通过VIDIOC_S_CTRL传入。申请缓冲区启动流。布局配置是核心我用的是结构体数组每路一个条目struct avs_input_rect { __u32 x; __u32 y; __u32 width; __u32 height; }; struct avs_input_rect rects[8] { {0, 0, 960, 1080}, {960, 0, 960, 1080}, {1920, 0, 960, 1080}, {2880, 0, 960, 1080}, {0, 1080, 960, 1080}, {960, 1080, 960, 1080}, {1920, 1080, 960, 1080}, {2880, 1080, 960, 1080}, };然后通过私有ioctl把这些参数下发给驱动。不同SDK版本的私有ioctl名字可能不同我用的版本里是RK_AVS_SET_INPUT_RECT。3.3 输入源的绑定与同步AVS本身不产生数据它需要从8路输入源拿数据。在RK3588上输入源可以是ISP的输出也可以是内存中的DMA缓冲区。我采用的是ISP直连AVS的方式通过media controller建立pipeline。用media-ctl工具可以看到整个拓扑media-ctl -p -d /dev/media0需要把每个ISP的输出pad链接到AVS对应的输入pad。链接建立后用v4l2-ctl启动每一路ISP的流再启动AVS的流。这里有个大坑8路输入的帧同步。如果8路摄像头不是同步曝光的拼接出来的画面在运动场景下会出现“撕裂感”比如一个人同时出现在两格画面里但位置对不上。硬件上最好用同一个时钟源给所有摄像头提供MCLK软件上尽量让8路流同时启动。我的做法是先启动所有ISP流等所有缓冲区都ready后再一次性启动AVS这样能把不同步控制在最小范围。3.4 输出到编码与显示AVS的输出缓冲区可以直接送给VENC。在V4L2里这通过export buffer再import到VENC实现避免了内存拷贝。VENC配置成H.264码率我设的是16Mbps4K30fps下这个码率能保证画质再低就会出现明显块效应。显示侧走VOP把AVS输出送到HDMI。如果本地不需要预览可以关掉VOP节省带宽。实测整条链路跑下来CPU占用率不到15%主要开销在VENC和网络推流上AVS本身几乎不占CPU。这验证了最初选硬件拼接的思路是对的。4. 常见问题与排查技巧实录4.1 画面花屏与颜色异常这是最常见的问题表现是拼接图上有绿色或紫色的条纹或者颜色整体偏色。排查顺序如下先确认输入格式是不是NV12。如果ISP输出的是其他格式AVS会按NV12解析UV平面错位就会花屏。检查色彩空间配置。输入BT.601、输出BT.709会导致偏色两者要一致。检查stride对齐。NV12的Y平面stride需要16字节对齐如果ISP输出的stride和AVS期望的不一致画面会斜切。我遇到过一次花屏最后发现是某一路ISP的输出分辨率被设成了1928x1080不是标准的1920导致AVS读取时错位。改成标准分辨率后问题消失。4.2 某一路黑屏或绿屏如果8路里有一路不正常先单独抓那一路的ISP输出确认ISP本身有没有数据。如果ISP正常但AVS里黑检查media pipeline里那一路的link有没有建立。有时候link建立了但pad没激活也会黑。绿屏通常是格式不匹配AVS把非YUV数据当YUV解析了。检查那一路的输入格式配置。4.3 帧率不达标与丢帧8路1080P拼4K理论能跑30fps但实测如果DDR带宽不够会掉到20fps左右。排查方法用cat /sys/kernel/debug/dri/0/bandwidth查看带宽占用。降低ISP的输出帧率试试如果降帧后稳定说明是带宽瓶颈。在设备树里提高AVS和DDR相关时钟频率。另外VENC的码率设太高也会反压AVS导致丢帧。先把VENC关掉只跑AVS到内存看帧率是否正常以此定位瓶颈在AVS还是VENC。4.4 常见问题速查表现象可能原因排查方法整体花屏输入格式非NV12检查ISP输出格式颜色偏色色彩空间不一致统一输入输出色彩空间单路黑屏pipeline未链接media-ctl检查link单路绿屏格式解析错误检查该路输入格式帧率不足DDR带宽瓶颈查看带宽占用降帧测试画面撕裂多路不同步检查摄像头时钟源和启动时序输出全黑AVS未启动流确认VIDIOC_STREAMON已调用4.5 几个独家避坑经验第一不要频繁启停AVS流。AVS硬件重新初始化的开销比想象中大如果业务需要动态切换布局尽量用暂停/恢复而不是关闭/重开。第二缓冲区数量要给够。我一开始每路只申请了2个buffer结果在高负载下出现丢帧加到4个后稳定。buffer多了占内存但视频链路里这点内存换稳定性是值得的。第三调试时先用静态图测试。把8路输入换成同一张测试图能快速判断是拼接逻辑问题还是摄像头采集问题。这个技巧帮我省了很多时间。第四关注温度。8路ISP加AVS加VENC全开RK3588的NPU和VPU区域温度会上升如果散热不好会触发降频帧率就掉了。加个散热片或者小风扇能明显改善长时间运行的稳定性。5. 性能调优与扩展思路5.1 带宽与功耗的平衡跑通之后下一步就是调优。我的目标是长时间稳定运行所以重点看两个指标帧率稳定性和芯片温度。帧率方面通过把VENC码率从16Mbps降到12MbpsDDR压力小了一些帧率波动从±3fps收窄到±1fps。温度方面加了一个小散热片后满载温度从85度降到72度不再触发降频。如果你对功耗敏感可以考虑降低ISP的输出帧率到25fps人眼观感差异不大但带宽和功耗都能降一截。5.2 从拼接图到智能分析拼接出4K大图之后很自然的想法是接目标检测。RK3588自带NPU6TOPS算力跑YOLOv8这类模型没问题。我的做法是把AVS输出同时送给VENC和NPUNPU做检测检测框坐标再映射回原始8路画面的坐标这样既能看到全景又能定位到具体是哪一路摄像头拍到的目标。坐标映射的关键是记录每路在拼接图中的偏移量检测框坐标减去偏移量就是该路画面内的坐标。这一步不难但要注意缩放比例因为每路在拼接时被缩放了。5.3 鱼眼矫正与AVS的配合如果摄像头是鱼眼镜头AVS本身不做畸变矫正。我的方案是先用RGA或者GPU做鱼眼矫正把画面展成透视投影再送给AVS拼接。矫正这一步比较耗算力如果8路都做GPU压力不小。可以考虑只对重叠区域做矫正或者降低矫正的分辨率。这个项目后续还可以往无缝融合方向走也就是在AVS拼接的基础上对重叠区域做羽化或光流融合让全景图看起来没有拼接缝。这需要额外的算法模块但AVS已经把最重的搬运和缩放工作做完了剩下的融合在CPU或GPU上做压力可控。我个人在实际操作中的体会是RK3588的AVS模块是一个被低估的能力很多人做多路视频时第一反应是软件拼接结果被算力和带宽卡住。先把硬件拼接用起来把CPU解放出来做更有价值的事这才是嵌入式端侧多路视频处理的正确打开方式。