rknn_model_zoo 中的 librga:基于 RGA 2D 硬件加速器的图像处理编程指南

原创2026-10-03 15:24:151,439 阅读
文章标签:示例工程人工智能嵌入式边缘计算计算机视觉模型优化

rknn_model_zoo 中的 librga:基于 RGA 2D 硬件加速器的图像处理编程指南

导读

RGA(Raster Graphic Acceleration Unit)是 Rockchip 平台上一颗独立的 2D 硬件加速器,可承担点/线绘制、图像缩放、旋转、bitBlt、alpha 混合等常见 2D 图形操作,将 CPU 从高频的图像搬运与变换中解放出来。本仓库在 3rdparty/librga 目录下内置了 librga —— RGA 的用户空间驱动库及其 2D 图形操作 API(当前版本 v1.10.0),并针对 Android 与 Linux 提供了多种 CPU 架构的预编译产物。阅读本文后,你将掌握 librga 的目录结构、im2d API 分层、核心数据结构与状态码语义,能够在自己的 C/C++ 应用中完成缩放、裁剪、格式转换、旋转、混合、填充等硬件加速操作,并了解它在本仓库 utils/image_utils.c 中的真实调用方式。

librga 在仓库中的定位

根据 3rdparty/librga/README.md 的说明,librga 实现了 RGA 的用户空间驱动,并提供一系列 2D 图形操作 API,其上游来源是 airockchip 维护的 librga 开源项目,当前仓库内置版本为 v1.10.0。该版本号与头文件 im2d_version.h 中的版本定义完全一致:RGA_API_MAJOR_VERSION = 1、RGA_API_MINOR_VERSION = 10、RGA_API_REVISION_VERSION = 0,并可通过 RGA_API_FULL_VERSION 宏在运行时打印完整版本字符串。

在 rknn_model_zoo 的整体架构中,librga 属于 3rdparty 第三方依赖库,与 fftw、jpeg_turbo、opencv、rknpu2 等并列,为上层图像预处理链路(如模型输入图像的缩放、格式转换)提供 2D 硬件加速选项。

目录结构与预编译产物

librga 目录的核心布局如下:

  • include/:全部公共头文件,包括 im2d 系列 API 头文件与底层 rga.h;
  • Linux/:Linux 平台预编译库,按 aarch64、armhf、armhf_uclibc 架构划分,每种架构同时提供 librga.a(静态库)与 librga.so(动态库);
  • Android/:Android 平台预编译库,提供 arm64-v8a 与 armeabi-v7a 两套 ABI 的 librga.a / librga.so;
  • README.md:来源与版本说明。

实际开发中可直接链接对应架构的库文件,也可以自行从上游源码构建后替换,使用方式与 OpenCV 等第三方库一致。

头文件体系:im2d API 的分层结构

include 目录下最核心的入口是 im2d.h,它通过简单的 include 组合将整套 API 暴露给使用者:

#include "im2d_version.h"
#include "im2d_type.h"
#include "im2d_common.h"
#include "im2d_buffer.h"
#include "im2d_single.h"
#include "im2d_task.h"
#include "im2d_mpi.h"

各头文件分工明确,可以按功能边界将其划分为五层:

头文件 职责
im2d_version.h API 版本宏,用于运行时校验头文件与库的版本匹配
im2d_type.h 核心类型:缓冲区描述 rga_buffer_t、矩形 im_rect、选项 im_opt_t、枚举 IM_USAGE/IM_STATUS 等
im2d_buffer.h 缓冲区导入(importbuffer 系列)与包装(wrapbuffer 系列)
im2d_single.h 单任务模式 API:copy/resize/crop/rotate/flip/blend/fill 等
im2d_task.h 多任务队列模式 API:imbeginJob / imendJob 与各类 xxxTask
im2d_common.h 通用工具:querystring、imStrError、imcheck、imsync、imconfig
im2d_mpi.h 面向 rockit-ko 的上下文(ctx)接口,如 improcess_ctx
im2d_expand.h Android 扩展:GraphicBuffer / AHardwareBuffer 的导入与包装

另外 rga.h 属于底层头文件,定义了 RK_FORMAT_* 像素格式枚举,im2d_type.h 会依赖它;RockchipRga.h 则提供较早期的面向对象封装(Rga 类),适合旧代码兼容场景。

核心数据结构与枚举

1. 像素格式:RK_FORMAT_*

RGA 支持 RGB 与 YUV 两大类格式,定义在 rga.h 中(格式值统一左移 8 位以与 Android 的 HAL_PIXEL_FORMAT_* 区分)。常用格式包括:

  • RGB 类:RK_FORMAT_RGBA_8888、RK_FORMAT_RGBX_8888、RK_FORMAT_RGB_888、RK_FORMAT_BGRA_8888、RK_FORMAT_RGB_565、RK_FORMAT_BGR_888;
  • YUV 半平面/平面类:RK_FORMAT_YCbCr_420_SP(NV12 风格)、RK_FORMAT_YCrCb_420_SP(NV21 风格)、RK_FORMAT_YCbCr_420_P、RK_FORMAT_YCbCr_422_SP 等;
  • 10 bit 类:RK_FORMAT_YCbCr_420_SP_10B、RK_FORMAT_YCrCb_420_SP_10B、RK_FORMAT_YCbCr_422_SP_10B 等;
  • 打包格式:RK_FORMAT_YUYV_422、RK_FORMAT_UYVY_422 等。

2. 缓冲区描述:rga_buffer_t

所有 im2d 函数都通过 rga_buffer_t 描述一块图像缓冲区,其定义位于 im2d_type.h:

typedef struct {
    void* vir_addr;          /* 虚拟地址 */
    void* phy_addr;          /* 物理地址 */
    int fd;                  /* dma-buf 共享 fd */

    int width;               /* 图像宽度 */
    int height;              /* 图像高度 */
    int wstride;             /* 宽度方向的像素 stride */
    int hstride;             /* 高度方向的像素 stride */
    int format;              /* 像素格式,取自 RK_FORMAT_* */

    int color_space_mode;    /* 色彩空间模式 */
    int global_alpha;        /* 全局 alpha 值 */
    int rd_mode;             /* 读取模式(raster/fbc/tile) */

    int color;               /* 颜色填充时使用的颜色 */
    im_colorkey_range colorkey_range;
    im_nn_t nn;
    int rop_code;

    rga_buffer_handle_t handle;  /* RGA 驱动中的缓冲区句柄 */
} rga_buffer_t;

注意 wstride/hstride 与 width/height 的区别:前者是缓冲区在内存中实际的对齐 stride,后者是参与运算的可视区域尺寸。对齐不满足硬件要求时,通常需要设置 stride 大于 width。

3. 矩形与选项

  • im_rect:描述图像上的操作区域,含 x、y、width、height 四个字段;
  • im_opt_t:单次任务的完整配置项,包含颜色填充值 color、colorkey 范围、NN 量化参数 nn、ROP 码、调度优先级 priority、核心选择 core、马赛克模式 mosaic_mode、OSD 配置 osd_config、中断配置 intr_config 以及预留字段 reserve[128],结构体第一个成员 version 默认取 RGA_CURRENT_API_HEADER_VERSION,用于版本校验。

4. 状态码:IM_STATUS

任何 blit 类函数的返回值都取自 IM_STATUS,其语义定义清晰:

状态码 值 含义
IM_STATUS_NOERROR 2 无错误
IM_STATUS_SUCCESS 1 执行成功
IM_STATUS_FAILED 0 执行失败
IM_STATUS_NOT_SUPPORTED -1 不支持该操作/格式组合
IM_STATUS_OUT_OF_MEMORY -2 内存不足
IM_STATUS_INVALID_PARAM -3 参数无效
IM_STATUS_ILLEGAL_PARAM -4 参数非法
IM_STATUS_ERROR_VERSION -5 头文件与库版本不匹配

配合 imStrError(status) 宏(定义于 im2d_common.h)可将状态码转换为可读的错误描述字符串,便于调试。

5. 操作位图:IM_USAGE

IM_USAGE 以位图方式描述一次任务要启用的硬件能力(im2d_type.h):

  • 几何变换:IM_HAL_TRANSFORM_ROT_90/180/270、IM_HAL_TRANSFORM_FLIP_H/V;
  • 混合模式:IM_ALPHA_BLEND_SRC_OVER(默认 Porter-Duff "SRC over DST")、IM_ALPHA_BLEND_SRC、IM_ALPHA_BLEND_DST、IM_ALPHA_BLEND_SRC_IN、IM_ALPHA_BLEND_DST_IN、IM_ALPHA_BLEND_XOR 等;
  • 高级特性:IM_ALPHA_COLORKEY_NORMAL/INVERTED(颜色键控)、IM_SYNC/IM_ASYNC(同步/异步)、IM_COLOR_FILL、IM_COLOR_PALETTE、IM_NN_QUANTIZE、IM_ROP、IM_ALPHA_BLEND_PRE_MUL、IM_MOSAIC、IM_OSD 等。

此外还有调度核心枚举 IM_SCHEDULER_CORE(可指定 RGA3 Core0/Core1 或 RGA2 Core0)与缩放插值枚举 IM_SCALE_MODE(INTER_NEAREST / INTER_LINEAR / INTER_CUBIC)。

单任务 API:一次调用完成一项操作

单任务模式是最常用的编程方式,每个 API 的典型签名为「输入缓冲 + 输出缓冲 + 操作参数 + 同步标志(默认同步执行)」,全部声明在 im2d_single.h 中。C++ 下使用默认参数即可,C 环境下则通过宏自动展开为 _t 后缀函数并填充默认值。

常用 API 一览:

API 功能 关键参数
imcopy 图像拷贝 src、dst、sync
imresize 缩放 src、dst、fx/fy 缩放因子、interpolation
imcrop 裁剪 src、dst、im_rect(源图像上的裁剪区域)
imtranslate 平移 src、dst、目标起始坐标 x/y
imcvtcolor 色彩空间/格式转换 src、dst、sfmt、dfmt、mode(BT601/BT709 等)
imrotate 旋转 src、dst、IM_HAL_TRANSFORM_ROT_90/180/270
imflip 镜像翻转 src、dst、IM_HAL_TRANSFORM_FLIP_H/V
imblend 双通道混合(前景+背景→背景) fg、bg、Porter-Duff mode
imcomposite 三通道混合(SRCA+SRCB→DST) srcA、srcB、dst、mode
imcolorkey 颜色键控 src、dst、im_colorkey_range、mode
imquantize NN 量化 src、dst、im_nn_t(各通道 scale/offset)
imfill / imfillArray 颜色填充 dst、im_rect、color
imrectangle 画矩形框 dst、rect、color、thickness(负值=实心)
immosaic 马赛克 image、rect、IM_MOSAIC_8/16/32/64/128
impalette 调色板/LUT 映射 src、dst、lut
improcess 通用单任务处理 src/dst/pat 三通道 + 三个矩形 + im_opt_t + usage
immakeBorder 扩边 src、dst、top/bottom/left/right、border_type、value

以缩放入口为例,C++ 接口签名为:

IM_API IM_STATUS imresize(const rga_buffer_t src, rga_buffer_t dst,
                          double fx = 0, double fy = 0,
                          int interpolation = 0, int sync = 1,
                          int *release_fence_fd = NULL);

当 sync == 1 时函数阻塞等待任务完成并直接返回状态码;当 sync == 0 时异步提交,通过 release_fence_fd 输出用于查询任务状态的 fence fd,之后可配合 imsync(release_fence_fd) 等待完成,适合流水线并行场景。

任务队列 API:一次提交多个操作

当需要对同一批图像连续执行多个操作(如先裁剪再缩放再格式转换)时,可以使用任务模式(im2d_task.h)将多个 task 打包成一个 RGA job 一次性提交,减少用户态与内核态的往返开销。基本流程为:

im_job_handle_t job = imbeginJob();              // 创建 job
imcropTask(job, src, tmp, rect);                 // 加入裁剪任务
imresizeTask(job, tmp, dst, 0, 0, INTER_LINEAR); // 加入缩放任务
imcvtcolorTask(job, tmp, dst, sfmt, dfmt);       // 加入格式转换任务
IM_STATUS ret = imendJob(job);                   // 提交并执行(默认 IM_SYNC)

核心接口包括:

  • imbeginJob(uint64_t flags = 0):创建 job,返回 im_job_handle_t 句柄;
  • imendJob(job, sync_mode = IM_SYNC, acquire_fence_fd = 0, int *release_fence_fd = NULL):提交 job,支持同步/异步两种运行模式;
  • imcancelJob(job):取消并销毁 job;
  • 各类 imxxxTask(job, ...):向 job 追加任务,包括 imcopyTask、imresizeTask、imcropTask、imrotateTask、imflipTask、imblendTask、imcompositeTask、imfillTask、immosaicTask、impaletteTask、improcessTask 等,与单任务 API 一一对应。

任务模式的任务全部在硬件端串行/流水执行,可避免中间结果的多次内存搬运,适合对性能敏感的预处理链路。

缓冲区管理:importbuffer 与 wrapbuffer

RGA 硬件不能直接访问普通 malloc 内存,因此 im2d 提供了两套缓冲区接口(im2d_buffer.h):

导入(importbuffer)——把外部分配的缓冲区注册到 RGA 驱动,返回 rga_buffer_handle_t 句柄:

  • importbuffer_fd(int fd, ...):传入 dma-buf 的 fd(推荐方式,drm 分配);
  • importbuffer_virtualaddr(void *va, ...):传入虚拟地址(需映射为连续物理内存场景);
  • importbuffer_physicaladdr(uint64_t pa, ...):传入物理地址;
  • releasebuffer_handle(handle):任务结束后释放句柄。

导入接口存在三组重载:仅传 size、传 width/height/format、或传 im_handle_param_t 结构体(内含 width、height、format 三字段)。

包装(wrapbuffer)——把已导入的句柄或内存描述包装成 rga_buffer_t:

  • wrapbuffer_handle(handle, width, height, format, ...):基于句柄包装;
  • wrapbuffer_virtualaddr / wrapbuffer_physicaladdr / wrapbuffer_fd:基于地址/fd 直接包装(此时无需先 importbuffer);
  • 可选的第 4、5 个参数为 wstride、hstride,省略时默认 wstride = width、hstride = height。

典型使用模式:

rga_buffer_handle_t hnd = importbuffer_fd(dma_fd, width, height, fmt);
rga_buffer_t src = wrapbuffer_handle(hnd, width, height, fmt, wstride, hstride);
// ... 执行 im2d 操作 ...
releasebuffer_handle(hnd);

在 Android 平台上,im2d_expand.h 还提供了 importbuffer_GraphicBuffer、wrapbuffer_AHardwareBuffer 等扩展接口,可直接对接 Android 图形缓冲区。

通用工具:能力查询与参数校验

im2d_common.h 提供一组与具体操作无关的辅助接口:

  • querystring(RGA_VENDOR / RGA_VERSION / RGA_MAX_INPUT / RGA_MAX_OUTPUT / RGA_INPUT_FORMAT / RGA_OUTPUT_FORMAT / RGA_EXPECTED / RGA_ALL):查询 RGA 硬件的基本信息、支持的最大分辨率与格式集合,返回描述字符串;
  • imStrError(IM_STATUS):将状态码转为错误信息字符串;
  • imcheckHeader():校验头文件版本与库版本是否一致,避免因 API 不匹配导致未定义行为;
  • imcheck(src, dst, src_rect, dst_rect, mode_usage):在提交任务前检查输入输出缓冲、区域与 usage 是否被当前硬件支持,返回 IM_STATUS_NOERROR 表示可执行;
  • imconfig(IM_CONFIG_NAME, value):配置调度核心、优先级等全局行为;
  • imsync(int release_fence_fd):阻塞等待指定 fence fd 对应的任务完成。

建议在正式业务代码前先调用 imcheckHeader(),并在每次任务后检查返回值,这是 librga 编程中保证稳定性的基本实践。

在 rknn_model_zoo 中的真实应用

本仓库的 utils/image_utils.c 在实现图像预处理/后处理时提供了基于 librga 的加速路径:文件第 7 行直接 #include "im2d.h",随后根据缓冲区来源(物理地址 / dma fd / 虚拟地址)分别调用 importbuffer_physicaladdr、importbuffer_fd、importbuffer_virtualaddr 导入源/目标缓冲区(源码第 585-613 行),再通过 wrapbuffer_handle / wrapbuffer_physicaladdr / wrapbuffer_fd / wrapbuffer_virtualaddr 包装出 rga_buffer_t 参与后续处理(源码第 596-627 行)。这一实现是 librga 接口在真实工程中的典型范例,展示了「导入 → 包装 → 执行 → 释放」的完整调用链,可作为开发者将 RGA 加速引入自研预处理管线的参考模板。

平台适配与集成建议

根据预编译产物目录,librga 覆盖的部署环境包括:

  • Linux:aarch64、armhf、armhf_uclibc(静态库与动态库);
  • Android:arm64-v8a、armeabi-v7a。

集成时需注意三点:其一,RGA 是 Rockchip SoC 上的硬件单元,librga 只能运行于具备 RGA 硬件(如 RK356x/RK3588 等系列)的目标板上,x86 宿主机无法直接使用;其二,使用前确认内核已加载 rga 驱动节点;其三,头文件版本与库版本需保持一致,可使用 imcheckHeader() 或 RGA_API_FULL_VERSION 宏在运行时校验。对于本仓库的模型推理场景,当输入图像尺寸与模型输入不一致、或需要将相机帧(通常为 YUV)转换为模型所需的 RGB 布局时,都可以借助 imresize + imcvtcolor 的组合把预处理卸载到 RGA 上,降低 CPU 占用与整体延迟。

小结

librga 通过一套分层清晰的 im2d API,把 Rockchip RGA 2D 硬件加速器的能力以「缓冲区 + 单任务/任务队列」两种模式暴露给应用层:rga_buffer_t 描述图像,IM_USAGE 声明能力,IM_STATUS 汇报结果,importbuffer/wrapbuffer 负责内存对接。结合本仓库 3rdparty/librga 内置的 v1.10.0 头文件与多架构预编译库,以及 utils/image_utils.c 的实践范例,开发者可以快速在 Rockchip 平台上构建出高性能的图像缩放、格式转换、旋转与混合流水线。

登录后查看全文
rknn_model_zoo