如何使用 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流程:

  1. 根据字节对齐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);

  1. 根据图像像素存储格式计算缓存大小。
  2. 分配连续缓存。
  3. 初始化内存地址偏移位置。
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流程:

  1. 启动流SAMPLE_COMM_IVE_StartViVpssVencVo
  2. 创建内存SAMPLE_COMM_IVE_CreateImage
  3. 获取视频帧HI_MPI_VPSS_GetChnFrame
  4. 拷出帧待用HI_MPI_IVE_DMA
  5. 释放视频帧HI_MPI_VPSS_ReleaseChnFrame
  6. 释放内存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);
}
posted @ 2021-03-17 08:24  派大海星  阅读(744)  评论(0编辑  收藏  举报