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的使用方法,还是比较简单易用的