背景
在 RK3588 平台上做多路 RTSP 解码、处理、再编码的项目中,我们最初沿用了旧 SDK 中常见的 VGS 处理方案,用于对解码后的帧进行裁剪 / 拷贝。
在旧版本 SDK 上,这套方案长期“看起来是正常的”。
但在升级到新版本 SDK(Rockit / 新驱动)后,问题集中爆发:
- VGS 处理后画面绿屏
- 偶尔不绿,但像素错位 / 花屏
- cache / stride 已反复确认,问题仍不稳定
最终,我们用 RGA 替换 VGS,问题全部消失,性能还明显提升。
本文完整记录这次问题的成因分析、踩坑过程和最终结论。
一、问题现象回顾
1️⃣ VGS 处理前帧是正常的
通过RK_MPI_MB_Handle2VirAddr+ OpenCV 保存VGS 处理前的帧:
- NV12 数据正确
- 图像内容完整
- stride / virHeight 与 SDK 返回一致
👉说明解码器输出是“可读且正确的”
2️⃣ VGS 处理后出现异常
使用RK_MPI_VGS_AddCropTask/AddScaleTask后:
- 要么整帧绿屏
- 要么局部绿 + 像素错位
- 偶现“正常”,但不可复现
即便已经处理了:
- NV12 对齐
- cache flush / invalidate
- virWidth / virHeight 不乱改
- pVirAddr 补齐
问题仍然存在。
二、误区:为什么“保存出来是正常的”,VGS 却不行?
这是很多 RK 工程师都会掉进去的坑。
关键误区是:
“CPU 能读 ≠ 硬件 DMA 能正确处理”
1️⃣ VDEC / VI 输出帧的真实身份
VDEC / VI 输出的VIDEO_FRAME_INFO_S:
不是标准线性 YUV 帧
可能是:
- NV21
- 私有 stride
- 内部重排布局
- 仅对 CPU 映射友好
CPU 通过Handle2VirAddr读取,是 SDK 帮你做了兼容映射。
2️⃣ VGS 在新 SDK 中的行为变化(关键)
旧 SDK:
- VGS 内部可能走CPU + DMA 混合路径
- 容忍非标准布局
- 甚至有隐式 memcpy / 兜底逻辑
新 SDK:
VGS 完全走硬件 DMA
严格要求:
- 线性 NV12
- COMPRESS_MODE_NONE
- 可 DMA 直接访问的布局
👉DMA 不理解 VDEC 的私有帧布局
结果就是:
- UV plane 解析错误 → 绿屏
- stride 偏移错误 → 像素错位
三、为什么旧 SDK 正常,新 SDK 出问题?
结论很明确:
旧 SDK 的“正常”,建立在隐式容错之上
新 SDK 把这层容错移除了
这是一次SDK 行为的“纠偏”,不是 Bug。
四、RGA 为什么能一换就好?
RGA 的定位,和 VGS 完全不同
| 模块 | 设计初衷 |
|---|---|
| VGS | ISP / IPC 流水线内部使用 |
| RGA | SoC 通用图像处理(解码 / App / 算法) |
RGA 天然支持的能力
直接吃VDEC / VI 原始帧
支持:
- NV12 / NV21
- 私有 stride
- dmabuf fd
内部完成:
- layout 解析
- cache 协调
- 数据线性化
👉RGA 是“合法中转站”
五、最终方案:用 RGA 替换 VGS
原 pipeline(问题来源)
VDEC / VI ↓ VGS (不稳定,绿屏) ↓ 后处理 / 编码新 pipeline(稳定方案)
VDEC / VI ↓ RGA(copy / crop / resize / NV21→NV12) ↓ 后处理 / 编码实际效果对比
| 指标 | VGS | RGA |
|---|---|---|
| 稳定性 | ❌ | ✅ |
| 绿屏 | 常见 | 无 |
| 像素错位 | 偶发 | 无 |
| 单帧处理耗时 | 不稳定 | ~1.1 ms |
| CPU 占用 | 中 | 极低 |
| SDK 兼容性 | 差 | 好 |
六、性能数据(RK3588 实测)
- 单帧处理耗时:≈ 1.1 ms
- 端到端延迟:6 ~ 15 ms
- FPS:稳定 25~26 fps
- VDEC timeout:偶发(正常现象,处理能力 > 输入)
这是一个非常健康的实时视频 pipeline。
七、工程结论(强烈建议收藏)
✅ 结论 1
VGS 不应直接处理 VDEC / VI 原始输出帧
✅ 结论 2
旧 SDK 的“可用”不代表架构正确
✅ 结论 3
RGA 是 RK 平台长期推荐的解码后图像处理模块
八、经验总结(给后来者)
凡是“解码 / 摄像头”出来的帧:
👉 先 RGA
👉 再进入后续 pipeline
这条经验可以帮你避开:
- 绿屏
- stride 错位
- cache 地狱
- SDK 升级灾难
结语
这次问题的解决,本质不是“修一个 Bug”,
而是完成了一次视频处理架构的升级。
从“能跑”,走向“正确、稳定、可长期维护”。