瑞芯微RKRGA(librga)Buffer API 分析

news/2025/4/2 4:52:30/

一、Buffer API 简介

        在瑞芯微官方的 librga 库的手册中,有两组配置 buffer 的API:

importbuffer 方式:

importbuffer_virtualaddr
importbuffer_physicaladdr
importbuffer_fd

wrapbuffer 方式:

wrapbuffer_virtualaddr
wrapbuffer_physicaladdr
wrapbuffer_fd
wrapbuffer_handle

以及一个释放函数:

releasebuffer_handle

二、使用流程

方式1:图像数据导入RGA驱动内部

        这种方式是官方 librga demo频繁使用的方式,主要用于单张图像或者转换频率小的场景。

(1)使用 importbuffer 函数导入外部内存,返回值为 handle 句柄;

(2)使用 wrapbuffer_handle 包装为 rga_buffer_t 结构;

(3)将 rga_buffer_t 结构传递给 RGA 处理函数;

(4)处理完成后,使用 releasebuffer_handle 释放资源.

这里放一个我修改的 resize demo:

/*** @Description: 将图像导入 RGA 内部统一管理内存,而不是用户自己管理* @param {Mat} &image: * @param {Mat} &resized_image: * @param {Size} &target_size: * @return {*}*/
int RGA_handle_resize(const cv::Mat &image, cv::Mat &resized_image) {/* 8位无符号三通道彩色图像 */ if (image.type() != CV_8UC3) {printf("source image type is %d!\n", image.type());return -1;}rga_buffer_t src_img, dst_img;rga_buffer_handle_t src_handle, dst_handle;size_t src_width = image.cols;size_t src_height = image.rows;size_t dst_width = resized_image.cols;size_t dst_height = resized_image.rows;int src_buf_size, dst_buf_size;int src_format = RK_FORMAT_RGB_888;int dst_format = RK_FORMAT_RGB_888;memset(&src_img, 0, sizeof(src_img));memset(&dst_img, 0, sizeof(dst_img));src_buf_size = src_width * src_height * get_bpp_from_format(src_format);dst_buf_size = dst_width * dst_height * get_bpp_from_format(dst_format);/* 将缓冲区对应的物理地址信息映射到RGA驱动内部,并获取缓冲区相应的地址信息 */// 直接操作Mat.data内存,减少数据复制开销src_handle = importbuffer_virtualaddr(image.data, src_buf_size);dst_handle = importbuffer_virtualaddr(resized_image.data, dst_buf_size);if (src_handle == 0 || dst_handle == 0) {printf("importbuffer failed!\n");return -1;}/* 封装为RGA图像结构 */src_img = wrapbuffer_handle(src_handle, src_width, src_height, src_format);dst_img = wrapbuffer_handle(dst_handle, dst_width, dst_height, dst_format);IM_STATUS STATUS;/*STATUS = imcheck(src_img, dst_img, {}, {});if (IM_STATUS_NOERROR != STATUS) {printf("%d, check error! %s", __LINE__, imStrError(STATUS));return -1;}*//* 执行缩放操作 */ STATUS = imresize(src_img, dst_img);/* 释放内存(正确和错误均执行) */ if (src_handle)releasebuffer_handle(src_handle);if (dst_handle)releasebuffer_handle(dst_handle);if (IM_STATUS_SUCCESS != STATUS) {fprintf(stderr, "rga resize error! %s", imStrError(STATUS));return -1;}return 0;
}

        其中 get_bpp_from_format 函数用于获取对应格式所占用的大小。imcheck 函数用于检查转换后的结构体格式,在验证初期建议开启,在发行版中建议去除,提高效率。

方式2:使用原始图像数据

        这种方式比第一种相对简单和方便,并且速度更快,不需要数据的拷贝。但是需要注意,传入的图像需要提前申请地址空间和大小,堆和栈都可以,如果传入空对象会报错,我这里使用的是 cv::Mat 对象进行数据传输,所以在调用 RGA 函数接口前,需要设置 Mat 对象的大小,或者使用 create 进行大小修正:

// 创建时设置大小
cv::Mat rgb_img(orig_img.rows, orig_img.cols, CV_8UC3);// 先申明
cv::Mat rgb_img;
// 调用前设置大小
rgb_img.create(orig_img.rows, orig_img.cols, CV_8UC3);

一共就两个关键步骤:

(1)将 cv::Mat 对象的 data 数据传递给 wrapbuffer_virtualaddr 函数,得到 rga_buffer_t 结构体;

(2)将 rga_buffer_t 结构传递给 RGA 处理函数;

这里同样是 resize demo:

/*** @Description: 直接内存映射图像数据,图像的生命周期由用户管理* @param {Mat} &image: 输入的源图像,使用 OpenCV 的 Mat 结构表示* @param {Mat} &resized_image: 输出的目标图像,经过缩放处理后的图像* @return {*} 返回 0 表示成功*/
int RGA_resize(const cv::Mat &image, cv::Mat &resized_image)
{if (image.type() != CV_8UC3) // 8位无符号三通道彩色图像{printf("source image type is %d!\n", image.type());return -1;}rga_buffer_t src_img;rga_buffer_t dst_img;size_t img_width = image.cols;size_t img_height = image.rows;size_t target_width = resized_image.cols;size_t target_height = resized_image.rows;memset(&src_img, 0, sizeof(src_img));memset(&dst_img, 0, sizeof(dst_img));// 将源图像和目标图像的数据填充至 rga_buffer_t 结构体(函数内部就是填充 rga_buffer_t)// 该函数用于用户自己管理的图像内存// OpenCV 的 MAT 格式为 RGB888,没有 A 通道src_img = wrapbuffer_virtualaddr((void *)image.data, img_width, img_height, RK_FORMAT_RGB_888);// 创建的 RGA 缓冲区,它直接引用了 resized_image.data 的内存地址,这意味着 dst_img 和 resized_image 共享同一块内存dst_img = wrapbuffer_virtualaddr((void *)resized_image.data, target_width, target_height, RK_FORMAT_RGB_888);IM_STATUS STATUS;STATUS = imresize(src_img, dst_img);if (IM_STATUS_SUCCESS != STATUS) {fprintf(stderr, "rga resize error! %s", imStrError(STATUS));return -1;}// printf("resizing .... %s\n", imStrError(STATUS));return 0;
}

三、importbuffer 系列函数

        这些函数用于将外部内存导入RGA驱动内部,实现硬件快速访问物理连续/非物理连续的内存:

1、importbuffer_virtualaddr

rga_buffer_handle_t importbuffer_virtualaddr(void *va, int size);
rga_buffer_handle_t importbuffer_virtualaddr(void *va, int width, int height, int format);
rga_buffer_handle_t importbuffer_virtualaddr(void *va, im_handle_param_t *param);
  • 作用:将虚拟地址(VA)内存导入RGA驱动
  • 参数:
    • va: 虚拟地址指针
    • size: 内存大小(字节)
    • width/height/format: 图像参数
    • param: 包含详细参数的im_handle_param_t结构体

2、importbuffer_physicaladdr

rga_buffer_handle_t importbuffer_physicaladdr(uint64_t pa, int size);
rga_buffer_handle_t importbuffer_physicaladdr(uint64_t pa, int width, int height, int format);
rga_buffer_handle_t importbuffer_physicaladdr(uint64_t pa, im_handle_param_t *param);
  • 作用:将物理地址(PA)内存导入RGA驱动
  • 参数与virtualaddr版本类似,但使用物理地址

3、importbuffer_fd

rga_buffer_handle_t importbuffer_fd(int fd, int size);
rga_buffer_handle_t importbuffer_fd(int fd, int width, int height, int format);
rga_buffer_handle_t importbuffer_fd(int fd, im_handle_param_t *param);
  • 作用:将DMA-BUF文件描述符(fd)内存导入RGA驱动
  • 参数与virtualaddr版本类似,但使用文件描述符

性能比较:physical address > fd > virtual address,一般推荐使用fd作为buffer类型

四、wrapbuffer 系列函数

这些函数用于将输入输出的图像参数转化为统一的rga_buffer_t结构:

1、wrapbuffer_virtualaddr

rga_buffer_t wrapbuffer_virtualaddr(void* vir_addr, int width, int height, int format, int wstride, int hstride);
  • 作用:包装虚拟地址内存为RGA缓冲区结构
  • 参数:
    • vir_addr: 虚拟地址
    • width/height: 图像宽高
    • format: 像素格式
    • wstride/hstride: 宽高步长(可选)

2、wrapbuffer_physicaladdr

rga_buffer_t wrapbuffer_physicaladdr(uint64_t phy_addr, int width, int height, int format, int wstride, int hstride);
  • 作用:包装物理地址内存为RGA缓冲区结构
  • 参数与virtualaddr版本类似,但使用物理地址

3、wrapbuffer_fd

rga_buffer_t wrapbuffer_fd(int fd, int width, int height, int format, int wstride, int hstride);
  • 作用:包装DMA-BUF文件描述符为RGA缓冲区结构
  • 参数与virtualaddr版本类似,但使用文件描述符

4、wrapbuffer_handle

rga_buffer_t wrapbuffer_handle(rga_buffer_handle_t handle, int width, int height, int format, int wstride = width, int hstride = height);
  • 作用:包装已导入的RGA缓冲区句柄为rga_buffer_t结构
  • 参数:
    • handle: 由importbuffer_*函数返回的句柄
    • 其他参数与上述wrapbuffer函数类似

五、releasebuffer_handle

IM_STATUS releasebuffer_handle(rga_buffer_handle_t handle);
  • 作用:释放由importbuffer_*函数导入的缓冲区
  • 参数:handle - 要释放的缓冲区句柄
  • 返回值:成功返回IM_STATUS_SUCCESS,否则返回错误码


http://www.ppmy.cn/news/1584531.html

相关文章

flutter优秀项目推荐

以下是几个值得推荐的 Flutter 开源项目,涵盖不同领域(UI 库、工具、完整应用等),适合学习和实际开发参考: 1. UI 组件库 & 动画 (1) flutter_ui_challenges 亮点:100 个精美的 UI 设计实现&#xff…

通过 Adobe Acrobat DC 实现 Word 到 PDF 的不可逆转换

目录 一、前言二、什么是不可逆PDF转换?三、准备工作四、详细转换步骤4.1 基础转换4.2 文档转曲(最终不可逆处理)4.2.1 检查并安装所需字体(转曲前建议完成)4.2.2 PDF文件转曲步骤 五、验证转换效果六、常见问题解决方…

C++学习之Linux文件编译、调试及库制作

目录 1.rwx对于文件和目录的区别 2.gcc编译过程 3.数据段合并和地址回填说明 4.gcc编译其他参数 5.函数库简介 6.静态库的使用 7.动态库的简介 8.动态库制作基本流程 9.启动APP错误解决方案12 10.启动APP错误解决方案34 11.makefile一组规则 12.makefile的两个函数 …

若依专题——基础应用篇

若依搭建 搭建后端项目 ① Git 克隆并初始化项目 ② MySQL 导入与配置 ③ 启动 Redis 搭建后端项目注意事项? ① 项目初始化慢,执行clean、package ② MySQL导入后,修改application-druid.yml ③ Redis有密码,修改ap…

聚类注意点

聚类注意点 样本异常数据 K均值(K-Means)是聚类中最常用的方法之一,它基于点与点距离的相似度来计算最佳类别归属。但K均值在应用之前一定要注意两种数据异常: 数据的异常值:数据中的异常值能明显改变不同点之间的距离…

NLP高频面试题(十七)——什么是KV Cache

在当今火热的大语言模型领域,模型的参数动辄数十亿甚至上千亿,随着输入的上下文(token长度)增加,推理过程中的计算量和显存消耗都会显著增加。其中,KV Cache 是大模型推理过程中的一种重要优化技术。 本文…

如何屏蔽mac电脑更新提醒,禁止系统更新

最烦mac的系统更新提醒了,过几天就是更新弹窗提醒,现在可以直接禁掉了,眼不见心不乱,不然一升级,开发环境全都不能用了,那才是最可怕的,屏蔽的方法也很简单,就是屏蔽mac系统更新的请…

太阳能台风预警宣传信号智慧杆:科技赋能防灾减灾的新标杆

在全球气候变化持续加剧、台风灾害频繁发生的大背景之下,借助科技手段提高预警效率以及保障公共安全,已然成为现代城市管理领域的关键课题。太阳能台风预警宣传信号智慧杆(以下简称 “智慧杆”)适时出现,凭借其以绿色能…