RGA(三)——实宽高、虚宽高与对齐约束

一、为什么单独讲这一篇?

前两篇讲了 RGA 是什么、RK3588 上有几颗核。从这一篇开始,要讲真正会"让你踩坑"的东西了。

在 RGA 的日常使用中,超过八成的"花屏""失败""图像不对"问题,都源于对"实宽高/虚宽高"和"对齐约束"的理解不到位 。官方 FAQ 里单独列了一节讲对齐,内核调试节点里有一个 check 模式专门检查对齐------说明这个问题官方自己也知道容易出错。

这一篇就把这两件事讲透。


二、实宽高(aw/ah)与虚宽高(vw/vh)

2.1 先看一个真实的报错

如果你在调用 RGA 时看到这样的报错:

css 复制代码
err ws[100,1280,1280]
Error srcRect

这是什么意思?官方 FAQ 给出了明确解释:

该报错为明显的参数报错,"err ws"即虚宽(width stride)参数异常,其后"\[\]"内的参数分别为 x_offset, width, width_stride,这里由于 X 方向的偏移与实际操作区域的宽的和大于了虚宽,所以 librga 认为虚宽存在问题而返回的报错。

翻译一下:err ws[100,1280,1280] 表示 X 方向偏移是 100,实际操作区域宽度是 1280,虚宽是 1280。因为 100 + 1280 = 1380 > 1280,超出了虚宽范围,所以报错。

解决方案:把虚宽改为 1380,或者把实宽改为 1180。

2.2 四个概念,一次说清

缩写 官方名称 含义 对应字段
aw / ah active width / active height 实宽实高,本次实际操作区域 im_rect.width / im_rect.height
vw / vh virtual width / virtual height 虚宽虚高,图像 buffer 本身大小(即 stride) rga_buffer_t.width / rga_buffer_t.height
xoff / yoff x offset / y offset 操作区域相对 buffer 原点的偏移 im_rect.x / im_rect.y

画个图就清楚了:

ini 复制代码
vw(虚宽 = width stride)
├────────────────────────────────────────┤
│                                        │
│         xoff = 100                     │
│      ┌──────────────┐                  │
│      │              │                  │  vh(虚高)
│      │  实际操作区域  │ ah = 300         │
│      │              │                  │
│      └──────────────┘                  │
│           aw = 300                     │
└────────────────────────────────────────┘

官方对 im_rect 的约束说得很清楚:

实际操作区域不能超出图像大小,即 (x + width) <= wstride ,(y + height) <= hstride。

违反这条约束,就是"err ws"报错的直接原因。

2.3 为什么会有虚宽这个概念?

因为 RGA 硬件是按 字(word,32bit) 方式取数的。

  • RGBA8888:单像素 32bit = 1 word → 无对齐要求(RGA2 下)
  • RGB565:单像素 16bit → 需 2 对齐(凑满一个 word)
  • RGB888:单像素 24bit → 需 4 对齐(4 个像素 = 3 个 word)
  • YUV:Y 通道单像素 8bit → Y 通道需 4 对齐 ;同时 4:2:0/4:2:2 下采样特性要求 x_offset、y_offset、width、height 都 2 对齐。

官方还给了对齐的计算公式:

width stride 对齐 = lcm(bpp, byte_stride × 8) / pixel_stride

符号 含义 举例
bpp bit per pixel,单像素占多少 bit RGBA8888 = 32,RGB565 = 16,RGB888 = 24,YUV 的 Y 通道 = 8
byte_stride 硬件取数的字节颗粒度 RGA2 = 4 ,RGA3 = 16
byte_stride × 8 把字节颗粒度换算成 bit RGA2 = 32 bit,RGA3 = 128 bit
pixel_stride 单像素占多少 bit(注意:和 bpp 数值一样,但语义不同) 和 bpp 同值
lcm(x, y) x 和 y 的最小公倍数 lcm(32, 32) = 32,lcm(24, 32) = 96
公式结果 width stride 需要对齐到多少个像素 结果 = 4 表示必须按 4 个像素的倍数对齐

简单说,虚宽不是随便写的,必须满足硬件按 word 取数的要求。


三、各平台各格式的对齐要求(核心表格)

官方对齐表分 RGA2 和 RGA3 两套,这里分别列出。

3.1 RGA2 的对齐要求

格式 对齐要求
RGBA/BGRA/ARGB/ABGR/RGBX/BGRX/XRGB/XBGR 8888 width stride 无对齐要求
RGBA_4444 / ARGB_5551 / RGB_565 等 16bit width stride 须 2 对齐
YUYV / YVYU / UYVY / VYUY 420/422 width stride 须 2 对齐,x_offset、y_offset、width、height、height stride 均须 2 对齐
RGB_888 / BGR_888 / A8 width stride 须 4 对齐
YCbCr 420/422/444 SP/P、Y400、Y4、Y8 width stride 须 4 对齐,x_offset、y_offset、width、height、height stride 均须 2 对齐
YCbCr 420/422 SP 10B width stride 须 16 对齐,x_offset、y_offset、width、height、height stride 均须 2 对齐

3.2 RGA3 的对齐要求

格式 对齐要求
RGBA 系 8888 width stride 须 4 对齐
RGB_565 / BGR_565 width stride 须 8 对齐
YUYV / UYVY 等 422 width stride 须 8 对齐,x_offset、y_offset、width、height、height stride 均须 2 对齐
RGB_888 / BGR_888 width stride 须 16 对齐
YCbCr 420/422 SP width stride 须 16 对齐,x_offset、y_offset、width、height、height stride 均须 2 对齐
YCbCr 420/422 SP 10B width stride 须 64 对齐,x_offset、y_offset、width、height、height stride 均须 2 对齐
FBC mode 除上述格式对齐要求外,width stride、height stride 须 16 对齐
TILE 8×8 mode 除上述格式对齐要求外,width、height 须 8 对齐 ,输入通道 width stride、height stride 须 16 对齐

四、RK3588 的特殊规则:取最严约束

RK3588 同时搭载 RGA2 和 RGA3,而两者的对齐要求不同。官方对此有明确说明:

当芯片平台搭载多版本硬件时,为了保证硬件利用率,librga 会按最严格的对齐要求进行约束。

具体来说:

  • RGA2 的 byte_stride_align 是 4
  • RGA3 的 byte_stride_align 是 16

所以 librga 在 RK3588 上会统一按 16 对齐校验。

这意味着:你在准备 NV12 的 stride 时,不能按 RGA2 时代的 4 来算,要按 16 来算。

举个具体的例子:你要处理一帧 1280×720 的 NV12 图像。

  • 如果按 RGA2 的标准,stride 写 1280(刚好 4 对齐)
  • 但 RK3588 会按 RGA3 的标准校验,要求 16 对齐
  • 所以 stride 必须写 ALIGN(1280, 16) = 1280(刚好也是 16 的倍数,没问题)
  • 但如果分辨率是 1281 或 1282,stride 就必须往上取到 16 的倍数

同样,10bit NV12 的 stride 要按 64 对齐准备,而不是 RGA2 时代的 16。


五、实战中的对齐检查

5.1 用 imcheck 在调试阶段校验

librga 提供了 imcheck() 接口用于校验参数合法性:

imcheck() 接口作为调用 librga 的校验接口,它将判断即将传递到 librga 内部的数据结构的参数是否正确、功能是否支持、是否触发硬件限制等。

如果校验失败,返回的错误信息会明确指出原因。比如:

ini 复制代码
Invalid parameters: dst, Error yuv not align to 2, 
rect[x,y,w,h] = [0,0,1281,720], wstride = 1281, hstride = 720, format = 0xa00(nv12)

这说明 YUV 格式的宽度 1281 不是 2 对齐,所以校验失败。

5.2 常见对齐问题的诊断

报错/现象 原因 对策
err ws[100,1280,1280] x_offset + width > width_stride 改虚宽为 1380,或改实宽为 1180
Error yuv not align to 2 YUV 宽度不是 2 对齐 宽度改为偶数
RGB888 缩放后有黑线/斜的 RGB888 的 width stride 未 4(或 16)对齐 检查 stride 对齐
图像出现黑色或绿色小条纹 buffer 使能了 cache 但未同步 同步 cache,或分配非 cache buffer

六、本篇小结

第一,实宽高(aw/ah)是本次实际操作区域,虚宽高(vw/vh)是图像 buffer 本身大小。 约束是 x + width <= wstride,y + height <= hstride,违反就会报 "err ws"。

第二,对齐要求来自硬件按 word(32bit)取数的特性。 RGBA8888 无对齐(RGA2)/ 4 对齐(RGA3),RGB565 2 / 8,RGB888 4 / 16,YUV 4 / 16,10bit YUV 16 / 64。

第三,YUV 族的 x_offset、y_offset、width、height、height stride 均须 2 对齐。 10bit YUV 的 64 对齐是加在 width stride 上的,不要和 2 对齐混。

第四,RK3588 上按最严约束执行,也就是 RGA3 的 16 对齐标准。 NV12 的 stride 要按 16 准备,10bit NV12 要按 64 准备。

第五,调试阶段用 imcheck() 校验参数。 它会在调用驱动之前就把参数问题找出来,报错信息会直接告诉你是哪个格式、哪个参数不符合要求。

相关推荐
fastjson_1 小时前
帆软看板 - 问题收集
linux·前端·javascript
jianpeng的工程笔记1 小时前
EL8 / EL9 安装 Slurm 26.05.4:主备控制器、MariaDB 记账与作业验收
linux·数据库·mariadb·高性能计算·slurm
程序员-Benothing1 小时前
Linux系统时间管理:date、timedatectl、NTP、Chrony配置
linux·运维·服务器
燕卫博1 小时前
SSD201 BSP 开发教程
嵌入式·bsp·ssd201
the3clipse2 小时前
MacOS、Linux 与 Windows 视频编解码对比:AV1、HEVC、ProRes 与硬件加速优劣势
linux·windows·macos·hevc·av1·视频解码·硬件解码
s6516654962 小时前
bootsect.s,setup.s,head.s的主要功能和对系统状态的影响、作用
linux
夜雪一千2 小时前
Python URL解码详解:单层、双重URL解码实战与踩坑指南
linux·服务器·python
一直C2 小时前
【嵌入式 ARM 驱动开发】PWM 脉宽调制原理与 GT9147 电容触控屏驱动开发详解
嵌入式硬件·lcd·嵌入式·arm汇编·imx6ull·cortex-a7
咯哦哦哦哦2 小时前
配置VNC sever 6.11.0版本 linux(激活码)
linux·运维·服务器