-
Notifications
You must be signed in to change notification settings - Fork 2
RGA_RgaProcessor
SweerItTer edited this page Feb 21, 2026
·
4 revisions
RgaProcessor 是 utilsCore RGA 模块的核心类,提供 RGA 硬件加速的流水线处理,自动从原始帧队列获取数据,执行格式转换,并输出到缓冲池。
- 从原始帧队列获取输入数据
- 执行 RGA 格式转换(YUV → RGB)
- 管理输出缓冲池
- 异步线程处理
- 支持 DMA-BUF 和 MMAP 两种模式
- 视频流实时处理
- YUV 到 RGB 格式转换
- YOLO 模型输入预处理
- UI 显示预处理
- 依赖: RgaConverter, AsyncThreadPool, ThreadPauser, DmaBuffer
- 被依赖: VisionPipeline, YoloProcessor 等上层模块
RgbaBuffer 是使用 RAII(资源获取即初始化)模式管理的 RGA 输出缓冲区类,提供:
- 自动资源管理(DMA-BUF 或 MMAP)
- 线程安全的状态管理
- 移动语义支持,禁用拷贝语义
- 内存类型感知的资源释放
namespace utils::rga {
class RgbaBuffer {
public:
/**
* @brief 构造函数 - 创建DMA-BUF缓冲区
* @param dmaBuf DMA-BUF共享指针
* @throws std::invalid_argument 如果DMA-BUF无效
*/
RgbaBuffer(std::shared_ptr<DmaBuffer> dmaBuf);
/**
* @brief 构造函数 - 创建MMAP缓冲区
* @param data 内存地址
* @param size 缓冲区大小
* @throws std::invalid_argument 如果参数无效
*/
RgbaBuffer(void* data, size_t size);
/**
* @brief 析构函数 - 自动释放资源
*/
~RgbaBuffer();
// 禁用拷贝构造和赋值
RgbaBuffer(const RgbaBuffer&) = delete;
RgbaBuffer& operator=(const RgbaBuffer&) = delete;
// 允许移动语义
RgbaBuffer(RgbaBuffer&& other) noexcept;
RgbaBuffer& operator=(RgbaBuffer&& other) noexcept;
/**
* @brief 检查缓冲区是否有效
* @return true如果缓冲区有效,false否则
*/
bool isValid() const noexcept;
/**
* @brief 检查缓冲区是否正在使用
*/
bool isInUse() const noexcept { return in_use_; }
/**
* @brief 设置缓冲区使用状态
*/
void setInUse(bool inUse) noexcept { in_use_ = inUse; }
/**
* @brief 获取共享缓冲区状态
*/
std::shared_ptr<SharedBufferState> getState() const noexcept { return state_; }
/**
* @brief 获取DMA-BUF文件描述符(仅DMA-BUF模式)
*/
int getFd() const noexcept;
/**
* @brief 获取虚拟地址(仅MMAP模式)
*/
void* getVirtualAddress() const noexcept;
/**
* @brief 获取缓冲区大小
*/
size_t getSize() const noexcept;
/**
* @brief 获取内存类型
*/
Frame::MemoryType getMemoryType() const noexcept { return memory_type_; }
private:
std::shared_ptr<SharedBufferState> state_;
bool in_use_ = false;
Frame::MemoryType memory_type_ = Frame::MemoryType::MMAP;
};
} // namespace utils::rga| 字段 | 类型 | 说明 |
|---|---|---|
state_ |
std::shared_ptr<SharedBufferState> |
共享缓冲区状态(RAII管理) |
in_use_ |
bool |
缓冲区使用状态(原子操作保证线程安全) |
memory_type_ |
Frame::MemoryType |
内存类型(DMA-BUF 或 MMAP) |
- RAII 资源管理: 自动释放 DMA-BUF 或 MMAP 资源
- 异常安全: 构造函数失败时不会泄漏资源
- 移动语义: 高效的所有权转移,避免深拷贝
- 内存类型感知: 根据内存类型采用不同的释放策略
- 线程安全: 使用原子操作保护使用状态
#include "utils/rga/rgaProcessor.h"
// 创建DMA-BUF缓冲区
auto dmaBuf = DmaBuffer::create(1920, 1080, DRM_FORMAT_NV12, 0, 0);
utils::rga::RgbaBuffer buffer1(dmaBuf);
// 创建MMAP缓冲区
size_t bufferSize = 1920 * 1080 * 4;
void* mmapData = mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
utils::rga::RgbaBuffer buffer2(mmapData, bufferSize);
// 检查缓冲区有效性
if (buffer1.isValid() && buffer1.getMemoryType() == Frame::MemoryType::DMABUF) {
int fd = buffer1.getFd();
// 使用DMA-BUF文件描述符
}
// 移动语义示例
utils::rga::RgbaBuffer buffer3 = std::move(buffer1);
// buffer1 现在处于有效但空的状态
---
## 类分析
### RgaProcessor 类
#### 职责与用途
RgaProcessor 是 RGA 处理流水线的封装类,提供:
- 自动从帧队列获取数据
- RGA 格式转换处理
- 缓冲池管理
- 线程控制(启动/停止/暂停)
- 支持异步线程池处理
#### 设计模式
- **生产者-消费者**: 从原始帧队列消费,生产到输出缓冲池
- **对象池**: 使用 RgbaBuffer 向量管理输出缓冲区
- **异步处理**: 使用 AsyncThreadPool 异步执行 RGA 处理
---
## Config 配置结构体
### 职责与用途
Config 结构体用于配置 RgaProcessor 的运行参数。
### 结构体定义
```cpp
struct Config {
std::weak_ptr<FrameQueue> rawQueue; // 原始帧队列(弱引用)
uint32_t width = 0; // 图像宽度
uint32_t height = 0; // 图像高度
bool usingDMABUF = false; // 是否使用 DMA-BUF
int dstFormat = RK_FORMAT_RGBA_8888; // 目标格式
int srcFormat = RK_FORMAT_YCbCr_420_SP; // 源格式
int poolSize = 4; // 缓冲池大小
};| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
rawQueue |
weak_ptr<FrameQueue> |
- | 原始帧队列(弱引用,避免循环引用) |
width |
uint32_t |
0 | 图像宽度(0 表示使用输入帧的宽度) |
height |
uint32_t |
0 | 图像高度(0 表示使用输入帧的高度) |
usingDMABUF |
bool |
false | true=使用 DMA-BUF 模式, false=使用 MMAP 模式 |
dstFormat |
int |
RK_FORMAT_RGBA_8888 |
目标格式(RGA 格式) |
srcFormat |
int |
RK_FORMAT_YCbCr_420_SP |
源格式(RGA 格式) |
poolSize |
int |
4 | 输出缓冲池大小 |
RgaProcessor(Config& cfg)参数说明:
-
cfg(输入): 配置结构体(引用)
返回值: 无
所有权归属:
- RgaProcessor 拥有缓冲池和工作线程的所有权
- rawQueue 使用弱引用,不持有所有权
注意事项:
- 构造时会初始化缓冲池和工作线程
- 使用弱引用持有 rawQueue,避免循环引用
- 配置参数会影响输出缓冲区的大小
使用例程:
// 在 VisionPipeline 中初始化
RgaProcessor::Config rgaConfig;
rgaConfig.rawQueue = rawFrameQueue;
rgaConfig.width = 1920;
rgaConfig.height = 1080;
rgaConfig.usingDMABUF = true;
rgaConfig.dstFormat = RK_FORMAT_RGB_888;
rgaConfig.srcFormat = convertV4L2toRGAFormat(V4L2_PIX_FMT_NV12);
rgaConfig.poolSize = 5;
RgaProcessor rgaProcessor(rgaConfig);~RgaProcessor()参数说明: 无
返回值: 无
所有权归属:
- 自动释放所有资源,包括工作线程和缓冲池
- 如果RgaProcessor仍在运行,会自动调用stop()
注意事项:
- 析构函数会自动停止处理线程
- 释放所有缓冲池资源
- 确保资源正确清理,避免内存泄漏
- 如果RgaProcessor仍在运行,析构函数会等待工作线程结束
使用例程:
{
RgaProcessor::Config cfg;
// ... 配置参数
RgaProcessor processor(cfg);
processor.start();
// 使用processor处理数据
// ...
// 离开作用域时自动调用析构函数,释放所有资源
}void setThreadAffinity(int cpu_core)参数说明:
-
cpuCore(输入): CPU 核心编号(0-based)
返回值: 无
所有权归属: 无
注意事项:
- 绑定工作线程到指定 CPU 核心
- 需要适当的权限
- 用于性能优化
void start()参数说明: 无
返回值: 无
所有权归属: 无
注意事项:
- 启动工作线程,开始从 rawQueue 获取数据
- 如果已启动,无效果
- 必须先调用 setThreadAffinity()(可选)
void stop()参数说明: 无
返回值: 无
所有权归属: 无
注意事项:
- 停止工作线程
- 等待所有异步任务完成
- 释放缓冲池
void pause()参数说明: 无
返回值: 无
所有权归属: 无
注意事项:
- 暂停从 rawQueue 获取数据
- 使用 ThreadPauser 实现
- 已处理的帧可以继续使用
int dump(FramePtr& frame, int64_t timeout=5)参数说明:
-
frame(输出): 输出参数,接收处理后的 FramePtr -
timeout(输入): 超时时间(秒,默认 5)
返回值:
- 成功: 返回缓冲区索引(>= 0)
- 失败/超时: 返回 -1
所有权归属:
- frame 的所有权转移给调用者
- 缓冲区索引用于后续 releaseBuffer()
注意事项:
- 从缓冲池获取已处理的帧
- 如果没有可用帧,等待超时
- 必须在使用后调用 releaseBuffer() 归还索引
使用例程:
FramePtr frame;
int index = rgaProcessor.dump(frame, 5);
if (index >= 0) {
// 成功获取帧
// 使用 frame 进行 YOLO 推理
auto result = yoloModel->infer(frame);
// 归还缓冲区
rgaProcessor.releaseBuffer(index);
} else {
// 超时或失败
printf("No frame available\n");
}void releaseBuffer(int index)参数说明:
-
index(输入): 缓冲区索引(由 dump() 返回)
返回值: 无
所有权归属:
- 释放缓冲区的所有权,使其可被复用
注意事项:
- 必须在使用完 dump() 返回的缓冲区后调用
- 索引必须在有效范围内 [0, poolSize-1]
- 缓冲区会被标记为可复用
使用例程:
FramePtr frame;
int index = rgaProcessor.dump(frame);
if (index >= 0) {
// 使用 frame
processFrame(frame);
// 归还缓冲区
rgaProcessor.releaseBuffer(index);
}static bool dumpDmabufAsXXXX8888(
int dmabuf_fd,
uint32_t width,
uint32_t height,
uint32_t size,
uint32_t pitch,
const char* path
)参数说明:
-
dmabuf_fd(输入): DMA-BUF 文件描述符 -
width(输入): 图像宽度 -
height(输入): 图像高度 -
size(输入): 缓冲区大小 -
pitch(输入): 每行字节数 -
path(输入): 输出文件路径
返回值:
-
true: 导出成功 -
false: 导出失败
所有权归属:
- dmabuf_fd 的所有权由调用者管理
注意事项:
- 静态方法,不需要实例
- 用于调试,将 DMA-BUF 导出为 RGBA8888 格式的文件
- 使用 RGA 进行格式转换
使用例程:
// 将 DMA-BUF 导出为图片文件
int fd = buffer->fd();
bool success = RgaProcessor::dumpDmabufAsXXXX8888(
fd,
1920,
1080,
buffer->size(),
buffer->pitch(),
"/tmp/output.png"
);1. 调用 start()
↓
2. 工作线程启动
↓
3. 从 rawQueue 获取原始帧
↓
4. 执行 RGA 格式转换
↓
5. 将结果存入 bufferPool_
↓
6. 通知等待中的 dump() 调用
↓
7. 继续处理下一帧
- 使用
std::vector<RgbaBuffer>管理输出缓冲区 - 通过
currentIndex_轮询可用的缓冲区 - 使用
in_use标记缓冲区使用状态
class VisionPipeline::Impl {
std::unique_ptr<RgaProcessor> rgaProcessor;
std::shared_ptr<FrameQueue> rgaFrameQueue;
void rgaProcessorInit() {
RgaProcessor::Config cfg;
cfg.rawQueue = rgaFrameQueue;
cfg.width = 1920;
cfg.height = 1080;
cfg.usingDMABUF = true;
cfg.dstFormat = RK_FORMAT_RGB_888;
cfg.srcFormat = convertV4L2toRGAFormat(V4L2_PIX_FMT_NV12);
cfg.poolSize = 5;
rgaProcessor = std::make_unique<RgaProcessor>(cfg);
rgaProcessor->setThreadAffinity(1);
rgaProcessor->start();
}
FramePtr getCurrentRGAFrame(FramePtr& out) {
FramePtr frame;
int index = rgaProcessor->dump(frame, 5);
if (index >= 0) {
out = frame;
// 使用完毕后释放
rgaProcessor->releaseBuffer(index);
}
return frame;
}
};RgaProcessor rgaProcessor(rgaConfig);
// 循环获取处理后的帧
while (running) {
FramePtr frame;
int index = rgaProcessor.dump(frame);
if (index >= 0) {
// 执行 YOLO 推理
auto result = yoloPool->acquire();
result = yoloPool->infer(frame);
yoloPool->release(result);
// 释放缓冲区
rgaProcessor.releaseBuffer(index);
} else {
printf("No frame available\n");
}
}// 将 RGA 处理后的缓冲区导出为图片
FramePtr frame;
int index = rgaProcessor.dump(frame);
if (index >= 0) {
int fd = frame->dmabuf_fd();
RgaProcessor::dumpDmabufAsXXXX8888(
fd,
frame->width(),
frame->height(),
frame->size(),
frame->pitch(),
"/tmp/debug.png"
);
rgaProcessor.releaseBuffer(index);
}- 使用 RGA 硬件加速格式转换
- 零拷贝 DMA-BUF 传输
- 减少 CPU 负载
- 使用 AsyncThreadPool 异步执行 RGA 处理
- 主线程不会被阻塞
- 提高整体吞吐量
- 预分配输出缓冲区
- 减少动态内存分配
- 提高缓存命中率
- 线程安全: dump() 和 releaseBuffer() 应该配对使用
- 超时处理: dump() 可能超时,需要检查返回值
- 索引管理: releaseBuffer() 需要传入正确的索引
- 缓冲池大小: poolSize 应根据实际使用情况设置
- 弱引用: rawQueue 使用弱引用,需要确保 FrameQueue 存在
- 格式支持: 只支持特定的 RGA 格式转换
- DMA-BUF 模式: usingDMABUF=true 时需要硬件支持
- 内存泄漏: 确保所有 dump() 返回的索引都被 releaseBuffer() 释放
- RgaConverter - RGA 格式转换
- DmaBuffer - DMA-BUF 缓冲区
- AsyncThreadPool - 异步线程池
- ThreadPauser - 线程暂停控制
- RGA 模块总览
主页
API 文档
DMA 模块
DRM 模块
- DRM 模块总览
- DeviceController - DRM 设备控制器
- DrmLayer - DRM 图层管理
- PlanesCompositor - DRM 平面合成器
- DrmBpp - DRM 格式定义
NET 模块
- NET 模块总览
- TcpServer - TCP 服务器
- SocketConnection - Socket 连接管理
- CommandHandler - 命令处理器
- DataPacket - 数据包
V4L2 模块
- V4L2 模块总览
- CameraController - V4L2 摄像头控制器
- Frame - V4L2 帧数据结构
- FormatTool - V4L2 格式工具
- Exception - V4L2 异常类
V4L2Param 模块
- V4L2Param 模块总览
- ParamControl - 参数控制
- ParamLogger - 参数日志
- ParamProcessor - 参数处理器
RGA 模块
- RGA 模块总览
- RgaConverter - RGA 转换器
- RgaProcessor - RGA 处理器
- FormatTool - RGA 格式工具
MPP 模块
- MPP 模块总览
- EncoderContext - 编码器上下文
- EncoderCore - 编码器核心
- JpegEncoder - JPEG 编码器
- StreamWriter - 流写入器
- MppResourceGuard - MPP 资源守护
- FileTools - 文件工具
- FormatTool - 格式工具
Sys 模块
- Sys 模块总览
- CpuMonitor - CPU 监控器
- MemoryMonitor - 内存监控器
- Base - 基础类
Mouse 模块
- Mouse 模块总览
- Watcher - 鼠标监视器
Utils 模块
- Utils 模块总览
- AsyncThreadPool - 异步线程池
- ConcurrentQueue - 并发队列
- FdWrapper - 文件描述符包装器
- FenceWatcher - 围栏监视器
- FixedSizePool - 固定大小对象池
- Logger - 日志记录器
- ObjectsPool - 对象池
- OrderedQueue - 有序队列
- ProgressBar - 进度条
- SafeQueue - 安全队列
- SharedBufferState - 共享缓冲区状态
- SimpleVariant - 简单变体类型
- ThreadPauser - 线程暂停器
- ThreadUtils - 线程工具
- Types - 类型定义
- UdevMonitor - Udev 监视器