一.RGA讲解
1.RGA的定义
RGA模块是RV1126用于2D图像的裁剪、缩放、旋转、镜像、图片叠加等格式转换的模块。比方说:要把一个原分辨率1920 * 1080的视频压缩成1280 * 720的视频,此时就要用到RGA模块了。比方说下图:
比方说把一个视频用RGA进行旋转,如下图:
比方说把一个视频用RGA进行镜像处理(镜像就是指物体相对于该物体反射出来的虚像,就像一个人照镜子,反射出来的图像),如下图:
要注意的是RGA是直接对VI的图像进行处理,并不是对VENC数据进行处理,这一点要非常注意。
2.RGA结构体的定义
RGA结构体分为:rga区域属性结构体,rga属性结构体。
2.1. RGA区域属性结构体
定义
typedef struct rkRGA_INFO_S {
IMAGE_TYPE_E imgType;
RK_U32 u32X;
RK_U32 u32Y;
RK_U32 u32Width;
RK_U32 u32Height;
RK_U32 u32HorStride; // horizontal stride
RK_U32 u32VirStride; // virtual stride
} RGA_INFO_S
成员解释:
成员名称 | 描述 |
imgType | 图像格式类型。 |
u32X | RGA的X轴坐标。 |
u32Y | RGA的Y轴坐标。 |
u32Width | RGA的宽度。 |
u32Height | RGA的高度。 |
u32HorStride | 虚宽。一般和宽度一样 |
u32VirStride | 虚高。一般和高度一样 |
2.2. RGA属性结构体
typedef struct rkRGA_ATTR_S {
RGA_INFO_S stImgIn; // input image info
RGA_INFO_S stImgOut; // output image info
RK_U16 u16Rotaion; // support 0/90/180/270.
RK_BOOL bEnBufPool;
RK_U16 u16BufPoolCnt;
RGA_FLIP_E enFlip;
} RGA_ATTR_S;
成员名称 | 描述 |
stImgIn | 输入图像信息。 |
stImgOut | 输出图像信息。 |
u16Rotaion | 旋转角度。取值范围:0,90,180,270。 |
bEnBufPool | 使能缓冲池。 |
u16BufPoolCnt | 缓冲池计数。 |
enFlip | 镜像控制。支持水平镜像、垂直镜像、水平垂直镜像。 |
enFlip | 镜像控制。支持水平镜像、垂直镜像、水平垂直镜像。 |
stImgIn:输入图像信息,一般填写的是原分辨率参数。比方说CMOS摄像头分辨率是1920*1080,则stImgIn分辨率就是1920*1080
stImgOut:输出图像信息,一般填写的是原分辨率参数。比方说要输出的是1280 * 720,则stImgOut分辨率就是1280 * 720
u16Rotation: 旋转角度,取值范围0, 90 ,180, 270
bEnBufPool:使能缓冲池
u16BufPoolCnt:缓冲池计数
enFlip:镜像控制,RGA_FLIP_E具体选项如下:
RGA_FLIP_H: 水平翻转,如下图:
RGA_FLIP_V:垂直翻转,如下图:
RGA_FLIP_HV:垂直+水平翻转
3.常用API
1.RK_MPI_RGA_CreateChn //创建RGA通道。
【语法】
RK_S32 RK_MPI_RGA_CreateChn(RGA_CHN RgaChn, RGA_ATTR_S *pstRgaAttr);
【参数】
参数名称 描述 输入/输出
RgaChn RGA通道号。取值范围:[0, RGA_MAX_CHN_NUM)。 输入
pstAttr RGA通道属性指针。 输入
第一个参数:RGA通道号,取值范围是[0, RGA_MAX_CHN_NUM],也就是16
第二个参数:RGA通道属性结构体指针
返回值描述:
0 成功。
非0 失败,其值参见错误码。
【需求】
头文件:rkmedia_api.h
库文件:libeasymedia.so
2.RK_MPI_RGA_DestroyChn //销毁RGA通道
【语法】
RK_S32 RK_MPI_RGA_DestroyChn(RGA_CHN RgaChn);
【参数】
RgaChn RGA通道号。取值范围:[0, RGA_MAX_CHN_NUM)。 输入
返回值描述:
0 成功。
非0 失败,其值参见错误码。
【需求】
头文件:rkmedia_api.h
库文件:libeasymedia.so
二.获取RGA的数据并保存
这部分属于实战内容,主要功能是先通过VI模块获取摄像头数据,并通过RGA模块对VI数据进行分辨率压缩,最终保存到本地文件。
1.流程
RV1126 VI模块采集摄像头并通过RGA缩小分辨率然后保存到本地文件的流程
1.1初始化VI模块:
VI模块的初始化实际上就是对VI_CHN_ATTR_S的参数进行设置、然后调用RK_MPI_VI_SetChnAttr设置VI模块并使能RK_MPI_VI_EnableChn
1.2初始化RGA模块:
RGA模块的初始化实际上就是对RGA_ATTR_S的参数进行设置、然后调用RK_MPI_RGA_CreateChn设置RGA模块。
1.3绑定VI节点和RGA节点:
1.3.1RK_MPI_SYS_Bind
绑定VI节点和RGA节点,使其两个模块能够关联起来,使用的API是RK_MPI_SYS_Bind。我们来看看这个API的具体定义:
【描述】
数据源到数据接收者绑定接口。
【语法】
RK_S32 RK_MPI_SYS_Bind(const MPP_CHN_S *pstSrcChn,const MPP_CHN_S *pstDestChn);
参数名称 | 描述 | 输入/输出 |
pstSrcChn | 源通道指针。 | 输入 |
pstDestChn | 目的通道指针。 | 输入 |
返回值描述:
0 成功。
非0 失败,其值参见错误码。
MPP_CHN_S成员变量:
成员名称 | 描述 |
enModId | 模块号。 |
s32DevId | 设备号。 |
s32ChnId | 通道号。 |
s32DevId:设备号ID,默认为0
s32ChnId:通道号ID,这里的通道号跟初始化的通道号一致。
enModId:模块号,指的是目前使用的模块ID。
比方说:正在使用的是VI模块,那模块ID就是RK_ID_VI。
又比方说正在使用的是RGA模块,那模块ID就是RK_ID_RGA。
所以说,模块号ID就是取决于你当前正在使用的是哪一个模块,enModId清单如下图:
我们现在是要将VI与RGA绑定,像这个需求是要让VI模块和RGA模块关联起来,那就需要创建两个MPP_CHN_S。一个是RGA的MPP_CHN_S,它的enModId是RK_ID_RGA,s32ChnId是创建的ID。另外一个是VI的MPP_CHN_S,它的enModId是RK_ID_VI,s32ChnId是创建的ID。
MPP_CHN_S vi_chn_s;
vi_chn_s.enModId = RK_ID_VI;
vi_chn_s.s32ChnId = 0;
MPP_CHN_S rga_chn_s;
rga_chn_s.enModId = RK_ID_RGA;
rga_chn_s.s32ChnId = 0;
ret = RK_MPI_SYS_Bind(&vi_chn_s, &rga_chn_s);
1.4开启多线程采集RGA的数据
开启一个线程去采集每一帧RGA模块的数据,使用的API是RK_MPI_SYS_GetMediaBuffer, 模块ID是RK_ID_RGA,通道号ID是RGA创建的ID号。这个API的具体作用已经在之前的获取VI数据的课程里面已经讲解过,我们直接上伪代码:
while(1)
{
.........................
mb = RK_MPI_SYS_GetMediaBuffer(RK_ID_RGA, s32_chn_id, -1);
fwrite(RK_MPI_MB_GetPtr(mb), RK_MPI_MB_GetSize(mb), 1, nv12_file);
}
2.写代码
1.初始化Vi模块
1.1初始化VI模块
1.2设置VI
这里要用到管道号和通道号,去宏定义