如何使用 IVE
数据类型
二维广义数据
typedef struct hiIVE_DATA_S {
HI_U64 u64PhyAddr; /* RW;数据物理地址 */
HI_U64 u64VirAddr; /* RW;数据虚拟地址 */
HI_U32 u32Stride; /* RW;数据跨度 */
HI_U32 u32Width; /* RW;数据宽 */
HI_U32 u32Height; /* RW;数据高 */
HI_U32 u32Reserved;
} IVE_DATA_S;
typedef IVE_DATA_S IVE_SRC_DATA_S;
typedef IVE_DATA_S IVE_DST_DATA_S;
IVE_DATA_S
:以字节为单位的二维数据信息,主要用于 DMA 。
u32Height
:数据行数。
u32Width
: 一行数据的字节数。
u32Stride
:一行数据的跨度(Stride = Width + 对齐填充字节数),单位字节,仅当IVE_IMAGE_S
像素位宽为1字节时相等。
二维广义图像
typedef struct hiIVE_IMAGE_S {
HI_U64 au64PhyAddr[3]; /* RW;图像物理地址 */
HI_U64 au64VirAddr[3]; /* RW;图像虚拟地址 */
HI_U32 au32Stride[3]; /* RW;图像跨度 */
HI_U32 u32Width; /* RW;图像宽 */
HI_U32 u32Height; /* RW;图像高 */
IVE_IMAGE_TYPE_E enType; /* RW;图像类型 */
} IVE_IMAGE_S;
typedef IVE_IMAGE_S IVE_SRC_IMAGE_S;
typedef IVE_IMAGE_S IVE_DST_IMAGE_S;
IVE_IMAGE_S
: 以像素为单位的二维广义图像信息。
u32Height
:像素行数(需为偶数)。
u32Width
:图像一行的像素个数(需为偶数)。“像素”位宽可以是1字节,2字节等。
au32Stride
:图像一行的像素跨度(Stride = Width + 对齐填充字节数),单位像素。
enType
:图像类型,如U8C1、YUV420P、YUV420SP
等,存储格式见pdf图1-2~10。
au64PhyAddr/au64VirAddr
: 图像内存地址(物理/虚拟),它们的3个数组成员不一定全部使用,使用情况根据图像类型而定,如U8C1
仅使用了成员0,详见pdf表1-1~2。
IVE_IMAGE_S
如何分配IVE_IMAGE_S内存?
参考函数SAMPLE_COMM_IVE_CreateImage
流程:
- 根据字节对齐
SAMPLE_COMM_IVE_CalcStride
计算得到一行的跨度。
HI_U16 SAMPLE_COMM_IVE_CalcStride(HI_U32 u32Width, HI_U8 u8Align)
{
return (u32Width + (u8Align - u32Width % u8Align) % u8Align);
}
pstImg->au32Stride[0] = SAMPLE_COMM_IVE_CalcStride(pstImg->u32Width, IVE_ALIGN);
- 根据图像像素存储格式计算缓存大小。
- 分配连续缓存。
- 初始化内存地址偏移位置。
case IVE_IMAGE_TYPE_YUV422SP:
{
u32Size = pstImg->au32Stride[0] * pstImg->u32Height * 2;
s32Ret = HI_MPI_SYS_MmzAlloc(&pstImg->au64PhyAddr[0], (HI_VOID**)&pstImg->au64VirAddr[0], NULL, HI_NULL, u32Size);
if (s32Ret != HI_SUCCESS)
{
SAMPLE_PRT("Mmz Alloc fail,Error(%#x)\n", s32Ret);
return s32Ret;
}
pstImg->au32Stride[1] = pstImg->au32Stride[0];
pstImg->au64PhyAddr[1] = pstImg->au64PhyAddr[0] + pstImg->au32Stride[0] * pstImg->u32Height;
pstImg->au64VirAddr[1] = pstImg->au64VirAddr[0] + pstImg->au32Stride[0] * pstImg->u32Height;
}
如何交换yuv文件与IVE_IMAGE_S数据?
参照SAMPLE_COMM_IVE_ReadFile
从文件中读数据填入。
参照SAMPLE_COMM_IVE_WriteFile
从结构中导出。
如何从视频流到IVE_IMAGE_S数据?
参照SAMPLE_IVE_Od
流程:
- 启动流
SAMPLE_COMM_IVE_StartViVpssVencVo
- 创建内存
SAMPLE_COMM_IVE_CreateImage
- 获取视频帧
HI_MPI_VPSS_GetChnFrame
- 拷出帧待用
HI_MPI_IVE_DMA
- 释放视频帧
HI_MPI_VPSS_ReleaseChnFrame
- 释放内存
SAMPLE_IVE_Od_Uninit
任务执行
IVE模块提供的功能以任务方式体现,包含一类创建任务接口HI_MPI_IVE_xxx
和一个任务查询接口HI_MPI_IVE_Query
。每当用户调用一次任务创建时就分配一个不同的handle
返回,创建任务时需要指定结果关心标志bInstant
。任务的解释即调用函数只是添加并开启功能,执行结果通过查询方式获取。任务是依次执行的,后者完成前者必完成,所以一组任务下关心和查询最后的任务即可。查询分阻塞和非阻塞。
参考SAMPLE_IVE_TestMemoryProc
流程:
bInstant = HI_FALSE;
s32Ret = HI_MPI_IVE_Sub(&IveHandle, ... , bInstant);
bInstant = HI_TRUE;
s32Ret = HI_MPI_IVE_Hist(&IveHandle, ... , bInstant);
bBlock = HI_TRUE;
s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
while (HI_ERR_IVE_QUERY_TIMEOUT == s32Ret)
{
usleep(100);
s32Ret = HI_MPI_IVE_Query(IveHandle, &bFinish, bBlock);
}