Skip to content

RGA_RgaProcessor

SweerItTer edited this page Feb 21, 2026 · 4 revisions

RgaProcessor API 文档

概述

RgaProcessor 是 utilsCore RGA 模块的核心类,提供 RGA 硬件加速的流水线处理,自动从原始帧队列获取数据,执行格式转换,并输出到缓冲池。

职责

  • 从原始帧队列获取输入数据
  • 执行 RGA 格式转换(YUV → RGB)
  • 管理输出缓冲池
  • 异步线程处理
  • 支持 DMA-BUF 和 MMAP 两种模式

适用场景

  • 视频流实时处理
  • YUV 到 RGB 格式转换
  • YOLO 模型输入预处理
  • UI 显示预处理

依赖关系

  • 依赖: RgaConverter, AsyncThreadPool, ThreadPauser, DmaBuffer
  • 被依赖: VisionPipeline, YoloProcessor 等上层模块

结构体分析

RgbaBuffer 类(优化版本)

职责与用途

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)

设计优势

  1. RAII 资源管理: 自动释放 DMA-BUF 或 MMAP 资源
  2. 异常安全: 构造函数失败时不会泄漏资源
  3. 移动语义: 高效的所有权转移,避免深拷贝
  4. 内存类型感知: 根据内存类型采用不同的释放策略
  5. 线程安全: 使用原子操作保护使用状态

使用示例

#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 输出缓冲池大小

公共 API 方法

构造函数

RgaProcessor(Config& cfg)

参数说明:

  • cfg (输入): 配置结构体(引用)

返回值: 无

所有权归属:

  • RgaProcessor 拥有缓冲池和工作线程的所有权
  • rawQueue 使用弱引用,不持有所有权

注意事项:

  1. 构造时会初始化缓冲池和工作线程
  2. 使用弱引用持有 rawQueue,避免循环引用
  3. 配置参数会影响输出缓冲区的大小

使用例程:

// 在 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()

注意事项:

  1. 析构函数会自动停止处理线程
  2. 释放所有缓冲池资源
  3. 确保资源正确清理,避免内存泄漏
  4. 如果RgaProcessor仍在运行,析构函数会等待工作线程结束

使用例程:

{
    RgaProcessor::Config cfg;
    // ... 配置参数
    RgaProcessor processor(cfg);
    processor.start();
    
    // 使用processor处理数据
    // ...
    
    // 离开作用域时自动调用析构函数,释放所有资源
}

setThreadAffinity() - 设置线程亲和性

void setThreadAffinity(int cpu_core)

参数说明:

  • cpuCore (输入): CPU 核心编号(0-based)

返回值: 无

所有权归属: 无

注意事项:

  1. 绑定工作线程到指定 CPU 核心
  2. 需要适当的权限
  3. 用于性能优化

start() - 启动处理

void start()

参数说明: 无

返回值: 无

所有权归属: 无

注意事项:

  1. 启动工作线程,开始从 rawQueue 获取数据
  2. 如果已启动,无效果
  3. 必须先调用 setThreadAffinity()(可选)

stop() - 停止处理

void stop()

参数说明: 无

返回值: 无

所有权归属: 无

注意事项:

  1. 停止工作线程
  2. 等待所有异步任务完成
  3. 释放缓冲池

pause() - 暂停处理

void pause()

参数说明: 无

返回值: 无

所有权归属: 无

注意事项:

  1. 暂停从 rawQueue 获取数据
  2. 使用 ThreadPauser 实现
  3. 已处理的帧可以继续使用

dump() - 获取处理后的帧

int dump(FramePtr& frame, int64_t timeout=5)

参数说明:

  • frame (输出): 输出参数,接收处理后的 FramePtr
  • timeout (输入): 超时时间(秒,默认 5)

返回值:

  • 成功: 返回缓冲区索引(>= 0)
  • 失败/超时: 返回 -1

所有权归属:

  • frame 的所有权转移给调用者
  • 缓冲区索引用于后续 releaseBuffer()

注意事项:

  1. 从缓冲池获取已处理的帧
  2. 如果没有可用帧,等待超时
  3. 必须在使用后调用 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");
}

releaseBuffer() - 释放缓冲区

void releaseBuffer(int index)

参数说明:

  • index (输入): 缓冲区索引(由 dump() 返回)

返回值: 无

所有权归属:

  • 释放缓冲区的所有权,使其可被复用

注意事项:

  1. 必须在使用完 dump() 返回的缓冲区后调用
  2. 索引必须在有效范围内 [0, poolSize-1]
  3. 缓冲区会被标记为可复用

使用例程:

FramePtr frame;
int index = rgaProcessor.dump(frame);

if (index >= 0) {
    // 使用 frame
    processFrame(frame);
    
    // 归还缓冲区
    rgaProcessor.releaseBuffer(index);
}

dumpDmabufAsXXXX8888() - 静态方法:导出 DMA-BUF

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 的所有权由调用者管理

注意事项:

  1. 静态方法,不需要实例
  2. 用于调试,将 DMA-BUF 导出为 RGBA8888 格式的文件
  3. 使用 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 标记缓冲区使用状态

典型使用场景

场景 1: VisionPipeline 中的使用

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;
    }
};

场景 2: YOLO 模型输入

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");
    }
}

场景 3: 调试导出

// 将 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 处理
  • 主线程不会被阻塞
  • 提高整体吞吐量

缓冲池优化

  • 预分配输出缓冲区
  • 减少动态内存分配
  • 提高缓存命中率

注意事项

  1. 线程安全: dump() 和 releaseBuffer() 应该配对使用
  2. 超时处理: dump() 可能超时,需要检查返回值
  3. 索引管理: releaseBuffer() 需要传入正确的索引
  4. 缓冲池大小: poolSize 应根据实际使用情况设置
  5. 弱引用: rawQueue 使用弱引用,需要确保 FrameQueue 存在
  6. 格式支持: 只支持特定的 RGA 格式转换
  7. DMA-BUF 模式: usingDMABUF=true 时需要硬件支持
  8. 内存泄漏: 确保所有 dump() 返回的索引都被 releaseBuffer() 释放

相关文档


参考资料

主页

API 文档

DMA 模块

DRM 模块

NET 模块

V4L2 模块

V4L2Param 模块

RGA 模块

MPP 模块

Sys 模块

Mouse 模块

Utils 模块

Clone this wiki locally