
目录
-
- [一、RGA 是什么?](#一、RGA 是什么?)
-
- [1.1 RGA 简介](#1.1 RGA 简介)
- [1.2 RGA vs CPU 处理对比](#1.2 RGA vs CPU 处理对比)
- [二、RK3568 RGA 硬件特性](#二、RK3568 RGA 硬件特性)
-
- [2.1 RGA 版本](#2.1 RGA 版本)
- [2.2 支持的像素格式](#2.2 支持的像素格式)
- [2.3 RGA 功能矩阵](#2.3 RGA 功能矩阵)
- [三、RGA 驱动与 API](#三、RGA 驱动与 API)
-
- [3.1 内核驱动配置](#3.1 内核驱动配置)
- [3.2 用户态 API](#3.2 用户态 API)
-
- [3.2.1 安装 librga](#3.2.1 安装 librga)
- [3.2.2 头文件包含](#3.2.2 头文件包含)
- [四、RGA 实战开发](#四、RGA 实战开发)
- [五、使用 DMA-BUF 优化性能](#五、使用 DMA-BUF 优化性能)
-
- [5.1 DMA-BUF 示例](#5.1 DMA-BUF 示例)
- [六、RGA 调试技巧](#六、RGA 调试技巧)
-
- [6.1 查看内核日志](#6.1 查看内核日志)
- [6.2 使用 rga-tools 工具](#6.2 使用 rga-tools 工具)
- [6.3 常见问题排查](#6.3 常见问题排查)
- [七、RGA 在视频处理中的实战案例](#七、RGA 在视频处理中的实战案例)
-
- [7.1 场景:摄像头采集 + RGA 缩放 + 视频编码](#7.1 场景:摄像头采集 + RGA 缩放 + 视频编码)
- [7.2 性能优化建议](#7.2 性能优化建议)
- 八、总结
- 参考资料
在嵌入式图像处理项目中,我们经常需要进行图像缩放、旋转、格式转换等操作。如果使用 CPU 处理,不仅性能低下,还会占用大量系统资源,影响其他任务的响应速度。
RK3568 芯片内置了 RGA(Raster Graphics Acceleration) 2D 加速引擎,这是一颗专门用于图像处理的硬件模块,可以大幅提升图像处理性能。本文将详细介绍 RGA 的原理、应用场景和实战开发经验。
一、RGA 是什么?
1.1 RGA 简介
RGA(Raster Graphics Acceleration)是瑞芯微(Rockchip)芯片系列中的 2D 图形加速引擎,专门用于处理像素级的图像操作。它通过硬件实现常见的图像处理算法,解放 CPU,降低功耗。
1.2 RGA vs CPU 处理对比
| 操作 | CPU 处理时间 | RGA 处理时间 | 加速比 |
|---|---|---|---|
| 1920x1080 图像缩放到 640x360 | ~45ms | ~4ms | 11.25x |
| 1920x1080 图像旋转 90° | ~120ms | ~5ms | 24x |
| RGB565 → NV12 格式转换 | ~80ms | ~3ms | 26.6x |
| 1920x1080 图像裁剪 | ~20ms | ~1ms | 20x |
从数据可以看出,RGA 在图像处理方面的性能优势非常明显,平均加速比可达 10-20 倍。
二、RK3568 RGA 硬件特性
2.1 RGA 版本
RK3568 使用的是 RGA 2.0 版本,相比早期的 RGA 1.0 有以下改进:
- 支持更大的分辨率(最高 8192x8192)
- 支持更多的输入/输出格式
- 优化了缩放算法,减少锯齿
- 支持 YUV 格式的硬件裁剪和旋转
2.2 支持的像素格式
| 类别 | 支持格式 |
|---|---|
| RGB 格式 | RGB565, RGB888, ARGB8888, XRGB8888, RGBA8888 |
| YUV 格式 | YUV420 (NV12, NV21, YUV420P), YUV422 (NV16, YUV422P), YUV444 |
| 压缩格式 | 不支持(需先解压) |
2.3 RGA 功能矩阵
| 功能 | RGA 支持 | 备注 |
|---|---|---|
| 图像缩放 | ✅ | 支持任意比例,双线性/双三次插值 |
| 图像旋转 | ✅ | 90°/180°/270°,任意角度(需固件支持) |
| 图像翻转 | ✅ | 水平/垂直翻转 |
| 格式转换 | ✅ | RGB ↔ YUV,YUV 格式间转换 |
| 图像裁剪 | ✅ | 矩形裁剪 |
| Alpha 混合 | ✅ | 支持 ARGB8888 的 Alpha 通道 |
| 颜色填充 | ✅ | 纯色填充 |
| 图像复制 | ✅ | 快速 blit 操作 |
三、RGA 驱动与 API
3.1 内核驱动配置
确保内核中 RGA 驱动已启用:
Device Drivers --->
[*] Rockchip Misc devices driver --->
<*> Rockchip Raster 2d Graphic Acceleration Unit
驱动加载后,会创建 /dev/rga 设备节点。
3.2 用户态 API
Rockchip 提供了 librga 用户态库,开发者可以通过 C API 调用 RGA 功能。
3.2.1 安装 librga
在 RK3568 SDK 中,librga 通常位于:
external/linux-rockchip/librga
编译安装:
bash
cd external/linux-rockchip/librga
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr
make -j4
sudo make install
3.2.2 头文件包含
c
#include <rga/im2d.h>
四、RGA 实战开发
4.1 基本图像缩放
场景
将 1920x1080 的图像缩放到 640x360。
代码示例
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rga/im2d.h>
int image_resize_demo() {
// 源图像配置
rga_buffer_t src = {};
src.buf = src_buffer; // 源图像数据地址
src.format = RK_FORMAT_RGBA_8888;
src.width = 1920;
src.height = 1080;
src.stride = 1920 * 4; // 每行字节数
src.fd = -1; // 使用虚拟内存
// 目标图像配置
rga_buffer_t dst = {};
dst.buf = dst_buffer; // 目标图像数据地址
dst.format = RK_FORMAT_RGBA_8888;
dst.width = 640;
dst.height = 360;
dst.stride = 640 * 4;
dst.fd = -1;
// 设置缩放参数
im_rect src_rect = {0, 0, 1920, 1080};
im_rect dst_rect = {0, 0, 640, 360};
// 执行缩放操作
int ret = imresize(src, dst, src_rect, dst_rect);
if (ret != IM_STATUS_SUCCESS) {
printf("RGA resize failed: %d\n", ret);
return -1;
}
printf("RGA resize success!\n");
return 0;
}
4.2 图像旋转
场景
将图像旋转 90°,常用于摄像头横竖屏切换。
代码示例
c
int image_rotate_demo() {
rga_buffer_t src = {
.buf = src_buffer,
.format = RK_FORMAT_RGBA_8888,
.width = 1920,
.height = 1080,
.stride = 1920 * 4,
.fd = -1
};
rga_buffer_t dst = {
.buf = dst_buffer,
.format = RK_FORMAT_RGBA_8888,
.width = 1080, // 旋转后宽高互换
.height = 1920,
.stride = 1080 * 4,
.fd = -1
};
// 设置旋转参数(90°)
im_rect src_rect = {0, 0, 1920, 1080};
im_rect dst_rect = {0, 0, 1080, 1920};
// 执行旋转
int ret = imrotate(src, dst, src_rect, dst_rect, IM_HAL_TRANSFORM_ROT_90);
if (ret != IM_STATUS_SUCCESS) {
printf("RGA rotate failed: %d\n", ret);
return -1;
}
printf("RGA rotate 90 degrees success!\n");
return 0;
}
4.3 格式转换
场景
将 RGB565 格式转换为 NV12 YUV 格式,常用于视频编码输入。
代码示例
c
int format_convert_demo() {
// 源图像(RGB565)
rga_buffer_t src = {
.buf = src_rgb565_buffer,
.format = RK_FORMAT_RGB_565,
.width = 1920,
.height = 1080,
.stride = 1920 * 2,
.fd = -1
};
// 目标图像(NV12)
rga_buffer_t dst = {
.buf = dst_nv12_buffer,
.format = RK_FORMAT_YCrCb_420_SP, // NV12
.width = 1920,
.height = 1080,
.stride = 1920, // Y 平面 stride
.fd = -1
};
im_rect src_rect = {0, 0, 1920, 1080};
im_rect dst_rect = {0, 0, 1920, 1080};
// 执行格式转换
int ret = imcrop(src, dst, src_rect, dst_rect);
if (ret != IM_STATUS_SUCCESS) {
printf("RGA format convert failed: %d\n", ret);
return -1;
}
printf("RGA RGB565 to NV12 convert success!\n");
return 0;
}
4.4 图像裁剪
场景
从大图中裁剪感兴趣区域(ROI),常用于人脸检测后的截取。
代码示例
c
int image_crop_demo() {
rga_buffer_t src = {
.buf = src_buffer,
.format = RK_FORMAT_RGBA_8888,
.width = 1920,
.height = 1080,
.stride = 1920 * 4,
.fd = -1
};
rga_buffer_t dst = {
.buf = dst_buffer,
.format = RK_FORMAT_RGBA_8888,
.width = 320, // 裁剪后的宽度
.height = 320, // 裁剪后的高度
.stride = 320 * 4,
.fd = -1
};
// 设置裁剪区域(从源图像的 (800, 300) 开始裁剪 320x320)
im_rect src_rect = {800, 300, 320, 320};
im_rect dst_rect = {0, 0, 320, 320};
// 执行裁剪
int ret = imcrop(src, dst, src_rect, dst_rect);
if (ret != IM_STATUS_SUCCESS) {
printf("RGA crop failed: %d\n", ret);
return -1;
}
printf("RGA crop success!\n");
return 0;
}
4.5 组合操作:缩放 + 旋转 + 格式转换
RGA 支持链式操作,一次调用完成多个转换,进一步减少内存拷贝。
c
int combined_operation_demo() {
rga_buffer_t src = {
.buf = src_buffer,
.format = RK_FORMAT_RGBA_8888,
.width = 1920,
.height = 1080,
.stride = 1920 * 4,
.fd = -1
};
rga_buffer_t dst = {
.buf = dst_buffer,
.format = RK_FORMAT_YCrCb_420_SP, // 最终格式 NV12
.width = 640,
.height = 360,
.stride = 640,
.fd = -1
};
// 源区域:全图
im_rect src_rect = {0, 0, 1920, 1080};
// 目标区域:缩放后的尺寸
im_rect dst_rect = {0, 0, 640, 360};
// 组合操作:缩放 + 旋转90° + 格式转换
int ret = imresize(src, dst, src_rect, dst_rect);
if (ret != IM_STATUS_SUCCESS) {
printf("RGA combined operation failed: %d\n", ret);
return -1;
}
// 再旋转(这里需要两次调用,或者使用更高级的 API)
// 实际项目中,推荐使用 im2d_t 任务链进行复杂操作
printf("RGA combined operation success!\n");
return 0;
}
五、使用 DMA-BUF 优化性能
在实际项目中,推荐使用 DMA-BUF(fd 方式) 传递图像数据,避免 CPU 内存拷贝,进一步提升性能。
5.1 DMA-BUF 示例
c
int dma_buf_demo() {
// 使用 fd 而不是虚拟地址
rga_buffer_t src = {
.fd = src_dma_fd, // DMA-BUF 文件描述符
.format = RK_FORMAT_RGBA_8888,
.width = 1920,
.height = 1080,
.stride = 1920 * 4
};
rga_buffer_t dst = {
.fd = dst_dma_fd,
.format = RK_FORMAT_YCrCb_420_SP,
.width = 640,
.height = 360,
.stride = 640
};
im_rect src_rect = {0, 0, 1920, 1080};
im_rect dst_rect = {0, 0, 640, 360};
int ret = imresize(src, dst, src_rect, dst_rect);
if (ret != IM_STATUS_SUCCESS) {
printf("RGA DMA-BUF operation failed: %d\n", ret);
return -1;
}
printf("RGA DMA-BUF operation success!\n");
return 0;
}
注意:DMA-BUF 需要配合 DRM/KMS 或 V4L2 使用,通常用于从摄像头采集直接到 RGA 处理的场景。
六、RGA 调试技巧
6.1 查看内核日志
RGA 驱动会输出调试信息,可通过以下命令查看:
bash
dmesg | grep rga
启用详细日志:
bash
echo 0xff > /sys/module/rga/parameters/debug
6.2 使用 rga-tools 工具
Rockchip 提供了 rga-tools 工具集,可用于测试和调试:
bash
# 测试缩放
rga_tool -i input.jpg -o output.jpg -s 640x360
# 测试旋转
rga_tool -i input.jpg -o output.jpg -r 90
# 测试格式转换
rga_tool -i input.rgb -o output.yuv -f NV12
6.3 常见问题排查
| 问题 | 可能原因 | 解决方法 |
|---|---|---|
| RGA 调用返回错误 | 参数配置错误(格式不匹配、越界) | 检查 width/height/stride/format |
| 输出图像花屏 | 源数据损坏或格式不正确 | 验证源数据,检查格式转换参数 |
| 性能提升不明显 | 使用了虚拟内存而非 DMA-BUF | 改用 fd 方式传递数据 |
| 大分辨率处理失败 | 超出 RGA 支持的最大分辨率 | 检查是否超过 8192x8192 |
| 旋转后图像错位 | 目标图像宽高未互换 | 旋转 90°/270° 时交换宽高 |
七、RGA 在视频处理中的实战案例
7.1 场景:摄像头采集 + RGA 缩放 + 视频编码
需求:从 1080p 摄像头采集视频,缩放到 720p 后编码为 H.264。
c
int camera_to_encoder_pipeline() {
// 1. V4L2 摄像头采集
int cam_fd = open_camera("/dev/video0", 1920, 1080);
dma_buf_t cam_dma = camera_capture_dma(cam_fd);
// 2. RGA 缩放
rga_buffer_t src = {
.fd = cam_dma.fd,
.format = RK_FORMAT_YCrCb_420_SP,
.width = 1920,
.height = 1080,
.stride = 1920
};
rga_buffer_t dst = {
.fd = enc_dma.fd,
.format = RK_FORMAT_YCrCb_420_SP,
.width = 1280,
.height = 720,
.stride = 1280
};
im_rect src_rect = {0, 0, 1920, 1080};
im_rect dst_rect = {0, 0, 1280, 720};
imresize(src, dst, src_rect, dst_rect);
// 3. MPP 视频编码
mpp_encoder_encode(enc_ctx, enc_dma);
return 0;
}
7.2 性能优化建议
- 使用 DMA-BUF:避免内存拷贝,零拷贝传输
- 合并操作:一次调用完成多个转换(如缩放+格式转换)
- 异步调用:RGA 支持异步操作,可与其他任务并行
- 缓存预热:首次调用 RGA 较慢,可预热后开始正式工作
八、总结
RGA 是 RK3568 平台上一颗强大的 2D 图形加速引擎,能够:
✅ 10-20 倍性能提升 :大幅减少图像处理时间
✅ 降低 CPU 占用 :释放 CPU 资源给其他任务
✅ 丰富的功能 :缩放、旋转、裁剪、格式转换一应俱全
✅ 易于集成:librga 提供简洁的 C API
在实际项目中,合理使用 RGA 可以显著提升系统性能和用户体验。特别是在视频处理、摄像头应用、UI 渲染等场景,RGA 是不可或缺的加速工具。
参考资料
- Rockchip RGA 文档:
external/linux-rockchip/librga/docs - librga 源码:https://github.com/airockchip/librga
- RK3568 数据手册:RK3568 TRM(技术参考手册)
如果这篇文章对你有帮助,欢迎点赞、收藏、评论!有问题可以在评论区留言,我会及时回复。