RK3568 RGA硬件加速详解:图像缩放、旋转、格式转换10倍提速

目录

    • [一、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 性能优化建议

  1. 使用 DMA-BUF:避免内存拷贝,零拷贝传输
  2. 合并操作:一次调用完成多个转换(如缩放+格式转换)
  3. 异步调用:RGA 支持异步操作,可与其他任务并行
  4. 缓存预热:首次调用 RGA 较慢,可预热后开始正式工作

八、总结

RGA 是 RK3568 平台上一颗强大的 2D 图形加速引擎,能够:

10-20 倍性能提升 :大幅减少图像处理时间

降低 CPU 占用 :释放 CPU 资源给其他任务

丰富的功能 :缩放、旋转、裁剪、格式转换一应俱全

易于集成:librga 提供简洁的 C API

在实际项目中,合理使用 RGA 可以显著提升系统性能和用户体验。特别是在视频处理、摄像头应用、UI 渲染等场景,RGA 是不可或缺的加速工具。


参考资料


如果这篇文章对你有帮助,欢迎点赞、收藏、评论!有问题可以在评论区留言,我会及时回复。

相关推荐
SmartRadio7 天前
基于RK3568实现多电脑KVM共享方案(HDMI采集+虚拟USB键鼠+无缝切换+剪贴板/文件共享)
运维·服务器·网络·电脑·kvm·rk3568
ShiMetaPi7 天前
GM-3568JHF丨ARM+FPGA异构开发板应用开发教程:07 FPGA FSPI 通信案例
arm开发·fpga开发·rk3568
ShiMetaPi12 天前
GM-3568JHF丨ARM+FPGA异构开发板应用开发教程:04 MIPI屏幕检测案例
arm开发·fpga开发·rk3568
ShiMetaPi17 天前
GM-3568JHF丨ARM+FPGA异构开发板应用开发教程:01 UART读写案例
arm开发·单片机·嵌入式硬件·fpga开发·fpga·rk3568
小Pawn爷19 天前
8.RAG构建金融知识库
金融·llm·rga
lkbhua莱克瓦2420 天前
RAG到RGA:生成式AI的范式演进
人工智能·llm·prompt·大语言模型·rag·rga
peixiuhui24 天前
突破边界!RK3576边缘计算网关:为工业智能注入“芯”动力
人工智能·物联网·边缘计算·rk3588·iot·rk3568·rk3576
peixiuhui24 天前
OpenPLC与RK3576边缘计算网关中结合应用的技术案例与分析
人工智能·边缘计算·rk3588·rk3568·openplc·rk3576·g8701
ShiMetaPi1 个月前
GM-3568JHF丨ARM+FPGA异构开发板系列教程:外设教程 09 CAN
arm开发·fpga开发·fpga·rk3568