3588 rga的使用

        3588出来有一段时间了,比之前的3399性能提高了不少。并且自带算力6T。在视频实时编解码和AI分析有着出色的表现。

        前面几篇博客也提到了3399 视频 ai的一些处理,在3588上面,mpp是通用的,代码几乎不用修改可以直接用。但是rga方式变了,统一了各个平台的使用接口。接口调用方式也变得很简单。

        主要就是以下的函数

        

enum FormatType {
    NV12,
    RGB24,
    BGR24,
    ARGB32
};

struct RgaData {
    /// 存储解码后流的数据,用户可以之间用相应显示软件播放,比如opengl或者qt
    unsigned char *data;
    /// 帧的大小
    unsigned int totalSize;
    /// 高度
    unsigned int height;
    /// 宽度
    unsigned int width;
    /// 类型
    FormatType type;
};

struct DmaBuf {
        void *buf;
        int fd;
};

/// rgaDataIn 输入
/// rgaData 输出
bool CRgaIm2d::transRga(const std::string &url, RgaData &rgaDataIn, RgaData &rgaData)
{
    uint32_t rgaSize = rgaData.width * rgaData.height * get_bpp_from_format(m_mapType[rgaData.type]);
    /// 3588这步的配置得加,否则会出现不支持64位地址的现象
    imconfig(IM_CONFIG_SCHEDULER_CORE, IM_SCHEDULER_RGA3_CORE0 | IM_SCHEDULER_RGA3_CORE1);
    /// 这步根据自己业务来,主要是分配输出的内存采用dma的方式
    if (m_mapData.find(url) == m_mapData.end())
    {
        for (int i = 0; i < RGA_BUFFER_NUM; i++)
        {
            DmaBuf buf;
            /// DMA_PATH "/dev/dma_heap/system"
            dmaBufAlloc(DMA_PATH, rgaSize, &buf.fd, &buf.buf);
            m_mapData[url].push_back(buf);
        }
        m_mapNum[url] = 0;
    }
    int i = m_mapNum[url] % RGA_BUFFER_NUM;
    DmaBuf buf = m_mapData[url][i];
    /// buffer封装
    rga_buffer_t src = wrapbuffer_virtualaddr(rgaDataIn.data, rgaDataIn.width, rgaDataIn.height, m_mapType[rgaDataIn.type]);
    rga_buffer_t dst = wrapbuffer_fd(buf.fd, rgaData.width, rgaData.height, m_mapType[rgaData.type]);
    /// 我们的业务不仅仅是格式转换,也有缩放等。所以统一调用此接口。已经包含了格式转换的功能
    imresize(src, dst);
    rgaData.data = (unsigned char *)buf.buf;
    rgaData.totalSize = rgaSize;
    m_mapNum[url] = i + 1;
    return true;
}

        以上代码可根据自己业务调整,我们在申请输出内存的时候,采用了dma的方式。用户可以根据自己的需求,在输入和输出的时候,都采用dma申请的方式,加快转换的速度

        dma申请内存的代码如下:

        

/// DmaManager.h
#ifndef __FFMPEG_DECODE_DMAMANAGER_H__
#define __FFMPEG_DECODE_DMAMANAGER_H__

#include <string>

namespace ffmpeg {

bool dmaBufAlloc(const std::string &dmaPath, int bufSize, int *fd, void **buf);
void dmaBufFree(int bufSize, int *fd, void *buf);

}

#endif /* __FFMPEG_DECODE_DMAMANAGER_H__ */

/// DmaManager.cpp
#include "DmaManager.h"

#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

#include "Print/Print.h"

namespace ffmpeg {

typedef unsigned long long __u64;
typedef  unsigned int __u32;

struct dma_heap_allocation_data {
	__u64 len;
	__u32 fd;
	__u32 fd_flags;
	__u64 heap_flags;
};

#define DMA_HEAP_IOC_MAGIC              'H'
#define DMA_HEAP_IOCTL_ALLOC            _IOWR(DMA_HEAP_IOC_MAGIC, 0x0, struct dma_heap_allocation_data)

bool dmaBufAlloc(const std::string &dmaPath, int bufSize, int *fd, void **buf)
{
    int prot;
    void *mmap_va;
    int cma_heap_fd = -1;
    struct dma_heap_allocation_data buf_data;

    /* open cma fd */
    if (cma_heap_fd < 0) {
        cma_heap_fd = open(dmaPath.c_str(), O_RDWR);
        if (cma_heap_fd < 0) {
            errorf("open %s fail!\n", dmaPath.c_str());
            return false;
        }
    }

    /* alloc buffer */
    memset(&buf_data, 0x0, sizeof(struct dma_heap_allocation_data));

    buf_data.len = bufSize;
    buf_data.fd_flags = O_CLOEXEC | O_RDWR;
    int ret = ioctl(cma_heap_fd, DMA_HEAP_IOCTL_ALLOC, &buf_data);
    if (ret < 0) {
        errorf("RK_DMA_HEAP_ALLOC_BUFFER failed\n");
        return false;
    }

    /* mmap va */
    if (fcntl(buf_data.fd, F_GETFL) & O_RDWR)
        prot = PROT_READ | PROT_WRITE;
    else
        prot = PROT_READ;

    /* mmap contiguors buffer to user */
    mmap_va = (void *)mmap(NULL, buf_data.len, prot, MAP_SHARED, buf_data.fd, 0);
    if (mmap_va == MAP_FAILED) {
        errorf("mmap failed: %s\n", strerror(errno));
        return -errno;
    }

    *buf = mmap_va;
    *fd = buf_data.fd;

    return true;
}

void dmaBufFree(int bufSize, int *fd, void *buf)
{
    munmap(buf, bufSize);
    close(*fd);
    *fd = -1;
}

}

        以上为3588 rga的使用方法,还是比较简单易用的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值