查看: 597|回复: 17

[hi3559/hi3559a] 使用HI_MPI_IVE_CSC()将从HI_MPI_VPSS_GetChnFrame()获得的数据进行颜色空间转换问题

[复制链接]
发表于 2019-7-11 13:52:03 | 显示全部楼层 |阅读模式
各位前辈,您好。我的流程是这样的,h264->VDEC->Vpss->IVE->NNIE,我使用HI_MPI_VPSS_GetChnFrame()获得图像yuv数据,因为我的模型使用的是rgb的数据,所以我想用HI_MPI_IVE_CSC()进行数据的转化,下面是我的代码:

HI_VOID * SAMPLE_COMM_VPSS_GetPic(HI_VOID *pArgs)
{
    VPSS_CHN_ATTR_S *pstVpssChnParam =(VPSS_CHN_ATTR_S *)pArgs;
    FILE *fp = HI_NULL;
    HI_S32 s32Ret, s32Cnt = 0;
    HI_S32 s32MilliSec = 20000;
    VPSS_GRP_ATTR_S  stVpssGrpAttr;
    VPSS_CHN_ATTR_S  stVpssChnAttr;
    VPSS_GRP VpssGrp;
    VIDEO_FRAME_INFO_S stVFrame; //定义视频图像帧信息结构体
    HI_CHAR cSaveFile[256];
        VpssGrp = 0;
        VPSS_CHN VpssChn = VPSS_CHN0;  // 0
       
        IVE_HANDLE hIveHandle;
        HI_BOOL bInstant = HI_TRUE;
        HI_BOOL bFinish = HI_FALSE;
    HI_BOOL bBlock = HI_TRUE;
    IVE_SRC_DATA_S stSrcData;
    IVE_DST_DATA_S stDstData;
    IVE_CSC_CTRL_S stCscCtrl;
    stCscCtrl.enMode = IVE_CSC_MODE_VIDEO_BT601_YUV2RGB;
       
    s32Ret =  HI_MPI_VPSS_GetChnAttr(VpssGrp,VpssChn, &stVpssChnAttr);
     
    if(HI_SUCCESS != s32Ret)
    {
        SAMPLE_PRT("chn %d get chn attr fail for %#x!\n", VpssGrp, s32Ret);
        return (HI_VOID *)(HI_FAILURE);
    }
   
       
    while(1)
    {                
        s32Ret = HI_MPI_VPSS_GetChnFrame(VpssGrp, VpssChn, &stVFrame, s32MilliSec);

                stSrcData.u64PhyAddr = stVFrame.stVFrame.u64PhyAddr[0];
                stSrcData.u32Width   = stVFrame.stVFrame.u32Width;
                stSrcData.u32Height  = stVFrame.stVFrame.u32Height;
                stSrcData.u32Stride  = stVFrame.stVFrame.u32Stride[0];

                stDstData.u64PhyAddr = stVFrame.stVFrame.u64PhyAddr[0];
                stDstData.u32Width   = stVFrame.stVFrame.u32Width;
                stDstData.u32Height  = stVFrame.stVFrame.u32Height;
                stDstData.u32Stride  = stVFrame.stVFrame.u32Stride[0];
               
                s32Ret = HI_MPI_SYS_MmzAlloc_Cached(&stSrcData.u64PhyAddr, &stSrcData.u64VirAddr, "User", HI_NULL, stSrcData.u32Height * stSrcData.u32Stride);
               
                if(HI_SUCCESS != s32Ret)
                {
                        printf("HI_MPI_SYS_MmzAlloc_Cached Failed!");
                        return s32Ret;
                }
                memset(stSrcData.u64VirAddr, 1, stSrcData.u32Height * stSrcData.u32Stride);
                s32Ret = HI_MPI_SYS_MmzAlloc_Cached(&stDstData.u64PhyAddr, &stDstData.u64VirAddr, "User", HI_NULL, stDstData.u32Height * stDstData.u32Stride);
                printf("\n ------------s32Ret=%d ---------------\n", s32Ret);
                if(HI_SUCCESS != s32Ret)
                {       
                        HI_MPI_SYS_MmzFree(stSrcData.u64PhyAddr, stSrcData.u64VirAddr);
                        printf("HI_MPI_SYS_MmzAlloc_Cached Failed!");
                        return s32Ret;
                }
                printf("\n ----------------HELLO--------------\n");
                memset(stDstData.u64VirAddr, 0, stDstData.u32Height * stDstData.u32Stride);
                s32Ret = HI_MPI_SYS_MmzFlushCache(0, HI_NULL, 0);
                printf("\n ------------s32Ret=%d ---------------\n", s32Ret);  //空指针错误
                if(HI_SUCCESS != s32Ret)
                {       
                        HI_MPI_SYS_MmzFree(stSrcData.u64PhyAddr, stSrcData.u64VirAddr);
                        HI_MPI_SYS_MmzFree(stDstData.u64PhyAddr, stDstData.u64VirAddr);
                        return s32Ret;
                }
               
                s32Ret = HI_MPI_IVE_CSC(&hIveHandle,&stSrcData,&stDstData,&stCscCtrl,bInstant);
                printf("\n ------------s32Ret=%d ---------------\n", s32Ret);
                if(HI_SUCCESS != s32Ret)
                {       
                        HI_MPI_SYS_MmzFree(stSrcData.u64PhyAddr, stSrcData.u64VirAddr);
                        HI_MPI_SYS_MmzFree(stDstData.u64PhyAddr, stDstData.u64VirAddr);
                        return s32Ret;
                }
               
                if (HI_TRUE == bInstant)
                {
                    s32Ret = HI_MPI_IVE_Query(hIveHandle,&bFinish,bBlock);
                    while(HI_ERR_IVE_QUERY_TIMEOUT == s32Ret)
                    {
                        usleep(100);
                        s32Ret = HI_MPI_IVE_Query(hIveHandle,&bFinish,bBlock);
                    }
                }
               
                HI_MPI_SYS_MmzFree(stSrcData.u64PhyAddr, stSrcData.u64VirAddr);
                HI_MPI_SYS_MmzFree(stDstData.u64PhyAddr, stDstData.u64VirAddr);

    }
    return (HI_VOID *)HI_SUCCESS;
}

出现空指针错误,有前辈知道这是什么原因吗?十分感谢!
 楼主| 发表于 2019-7-11 20:45:37 | 显示全部楼层
zhuangweiye 发表于 2019-7-11 16:38
既然是输入参数非法,就把输入参数都打出来看看

另外:

前辈,这是我修改后的:
s32Ret = HI_MPI_VPSS_GetChnFrame(VpssGrp, VpssChn, &stVFrame, s32MilliSec);
stSrcData.enType = IVE_IMAGE_TYPE_YUV420SP;
stSrcData.au64PhyAddr[0] = stVFrame.stVFrame.u64PhyAddr[0];
stSrcData.au64PhyAddr[1] = stVFrame.stVFrame.u64PhyAddr[1];
stSrcData.au64PhyAddr[2] = stVFrame.stVFrame.u64PhyAddr[2];

stSrcData.u32Width   = stVFrame.stVFrame.u32Width;
stSrcData.u32Height  = stVFrame.stVFrame.u32Height;


stDstData.enType = IVE_IMAGE_TYPE_U8C3_PACKAGE;
stDstData.u32Width   = stVFrame.stVFrame.u32Width;
stDstData.u32Height  = stVFrame.stVFrame.u32Height;
stDstData.au32Stride[0]  = stVFrame.stVFrame.u32Stride[0] * 3; //1920
stDstData.au32Stride[1]  = stVFrame.stVFrame.u32Stride[1] * 3;
stDstData.au32Stride[2]  = stVFrame.stVFrame.u32Stride[2] * 3;

s32Ret = HI_MPI_SYS_MmzAlloc_Cached(&stDstData.au64PhyAddr[0], &stDstData.au64VirAddr[0], "User", HI_NULL, stDstData.u32Height * stDstData.u32Width * 3);

if(HI_SUCCESS != s32Ret)
{       

        HI_MPI_SYS_MmzFree(stDstData.au64PhyAddr[0], stDstData.au64VirAddr[0]);
        return s32Ret;
}

s32Ret = HI_MPI_IVE_CSC(&hIveHandle,&stSrcData,&stDstData,&stCscCtrl,bInstant);
printf("----------------stSrcData =%d,stDstData=%d \n",stSrcData, stDstData);
printf("\n ------------s32Ret=%d ---------------\n", s32Ret);  //参数超出合法范围
if(HI_SUCCESS != s32Ret)
{       
        HI_MPI_SYS_MmzFree(stDstData.au64PhyAddr[0], stDstData.au64VirAddr[0]);
        return s32Ret;
}

if (HI_TRUE == bInstant)
{
    s32Ret = HI_MPI_IVE_Query(hIveHandle,&bFinish,bBlock);
    while(HI_ERR_IVE_QUERY_TIMEOUT == s32Ret)
    {
        usleep(100);
        s32Ret = HI_MPI_IVE_Query(hIveHandle,&bFinish,bBlock);
    }
}

HI_MPI_SYS_MmzFree(stDstData.au64PhyAddr, stDstData.au64VirAddr);
输出的stSrcData =-1753577680,stDstData=-1753777760。
实在不知道怎么修改了,希望前辈能指点一二。
回复 支持 1 反对 0

使用道具 举报

发表于 2019-7-11 14:21:19 | 显示全部楼层
一般来说是这样的:

HI_MPI_SYS_MmzAlloc_Cached(&u64PhyAddr, &pVirAddr, "",  HI_NULL, u32Size);
....
HI_MPI_SYS_MmzFlushCache(u64PhyAddr, pVirAddr, u32Size);
...


s32Ret = HI_MPI_SYS_MmzFlushCache(0, HI_NULL, 0);
楼主用0, NULL, 0 是什么意思?
 楼主| 发表于 2019-7-11 15:25:15 | 显示全部楼层
zhuangweiye 发表于 2019-7-11 14:21
一般来说是这样的:

HI_MPI_SYS_MmzAlloc_Cached(&u64PhyAddr, &pVirAddr, "",  HI_NULL, u32Size);

文档上说置为0表示操作整个cache
我现在将其修改为:
s32Ret = HI_MPI_SYS_MmzFlushCache(&stDstData.u64PhyAddr, &stDstData.u64VirAddr, stDstData.u32Height * stDstData.u32Stride);
但是s32Ret的返回值是-1;
如果将其·屏蔽掉,执行到
s32Ret = HI_MPI_IVE_CSC(&hIveHandle,&stSrcData,&stDstData,&stCscCtrl,bInstant);
printf("\n ------------s32Ret=%d ---------------\n", s32Ret);  //参数超出合法范围

会出现上面这个问题,找不到解决的方法,前辈知道是为什么吗?
发表于 2019-7-11 15:30:48 | 显示全部楼层
本帖最后由 zhuangweiye 于 2019-7-11 15:34 编辑
qn1562136485 发表于 2019-7-11 15:25
文档上说置为0表示操作整个cache
我现在将其修改为:
s32Ret = HI_MPI_SYS_MmzFlushCache(&stDstData.u ...


HI_MPI_SYS_MmzFlushCache(&stDstData.u64PhyAddr, &stDstData.u64VirAddr..

拜托楼主把& 去掉

另外
文档上写的

pVirAddr 待操作数据的起始虚拟地址指针。不能传NULL
 楼主| 发表于 2019-7-11 16:21:04 | 显示全部楼层
zhuangweiye 发表于 2019-7-11 15:30
HI_MPI_SYS_MmzFlushCache(&stDstData.u64PhyAddr, &stDstData.u64VirAddr..

拜托楼主把& 去掉

前辈,我对循环里面的代码进行了下面这样的修改:
s32Ret = HI_MPI_VPSS_GetChnFrame(VpssGrp, VpssChn, &stVFrame, s32MilliSec);
               
stSrcData.u64PhyAddr = stVFrame.stVFrame.u64PhyAddr[0];
stSrcData.u32Width   = stVFrame.stVFrame.u32Width;
stSrcData.u32Height  = stVFrame.stVFrame.u32Height;
stSrcData.u32Stride  = stVFrame.stVFrame.u32Stride[0];

       
stDstData.u32Width   = stVFrame.stVFrame.u32Width;
stDstData.u32Height  = stVFrame.stVFrame.u32Height;
stDstData.u32Stride  = stVFrame.stVFrame.u32Stride[0];
               
s32Ret = HI_MPI_SYS_MmzAlloc_Cached(&stDstData.u64PhyAddr, &stDstData.u64VirAddr, "User", HI_NULL, stDstData.u32Height * stDstData.u32Stride);
printf("\n ------------s32Ret=%d ---------------\n", s32Ret); //0

memset(stDstData.u64VirAddr, 0, stDstData.u32Height * stDstData.u32Stride);
s32Ret = HI_MPI_SYS_MmzFlushCache(stDstData.u64PhyAddr, stDstData.u64VirAddr, stDstData.u32Height * stDstData.u32Stride);
printf("\n ------------s32Ret=%d ---------------\n", s32Ret);  //0
if(HI_SUCCESS != s32Ret)
{       
     HI_MPI_SYS_MmzFree(stDstData.u64PhyAddr, stDstData.u64VirAddr);
     return s32Ret;
}
               
s32Ret = HI_MPI_IVE_CSC(&hIveHandle,&stSrcData,&stDstData,&stCscCtrl,bInstant);
printf("\n ------------s32Ret=%d ---------------\n", s32Ret);  // -1608679421,参数超出合法范围
if(HI_SUCCESS != s32Ret)
{       
        HI_MPI_SYS_MmzFree(stSrcData.u64PhyAddr, stSrcData.u64VirAddr);
        HI_MPI_SYS_MmzFree(stDstData.u64PhyAddr, stDstData.u64VirAddr);
        return s32Ret;
}
               
if (HI_TRUE == bInstant)
{
        s32Ret = HI_MPI_IVE_Query(hIveHandle,&bFinish,bBlock);
        while(HI_ERR_IVE_QUERY_TIMEOUT == s32Ret)
        {
                         usleep(100);
                        s32Ret = HI_MPI_IVE_Query(hIveHandle,&bFinish,bBlock);
          }

}
               
HI_MPI_SYS_MmzFree(stSrcData.u64PhyAddr, stSrcData.u64VirAddr);
HI_MPI_SYS_MmzFree(stDstData.u64PhyAddr, stDstData.u64VirAddr);


执行到 s32Ret = HI_MPI_IVE_CSC(&hIveHandle,&stSrcData,&stDstData,&stCscCtrl,bInstant); 的时候出现参数超过合法范围的错误,屏幕上打印出:
[Func]:HI_MPI_SYS_MmzFree [Line]:1078 [Info]: System unmap mmz memory failed!
我的图帧的分辨率是1920×1080的。
发表于 2019-7-11 16:38:36 | 显示全部楼层
qn1562136485 发表于 2019-7-11 16:21
前辈,我对循环里面的代码进行了下面这样的修改:
s32Ret = HI_MPI_VPSS_GetChnFrame(VpssGrp, VpssChn, ...

既然是输入参数非法,就把输入参数都打出来看看

另外:
stSrcData/stDstData 结构里的enType都没有填
发表于 2019-7-12 09:43:54 | 显示全部楼层
楼主问题解决了吗,我也遇到相同问题,QQ469366429,可以私聊下吗
发表于 2019-7-12 10:05:37 | 显示全部楼层
qn1562136485 发表于 2019-7-11 20:45
前辈,这是我修改后的:
s32Ret = HI_MPI_VPSS_GetChnFrame(VpssGrp, VpssChn, &stVFrame, s32MilliSec) ...

printf("----------------stSrcData =%d,stDstData=%d \n",stSrcData, stDstData);
打印参数不是这样的, 要把结构里面的成员都打出来

楼主enType填了,stSrcData的stride又漏了

另外:
地址和海思函数返回值请用%x,不要用%d
 楼主| 发表于 2019-7-12 17:47:54 | 显示全部楼层
zhuangweiye 发表于 2019-7-12 10:05
printf("----------------stSrcData =%d,stDstData=%d \n",stSrcData, stDstData);
打印参数不是这样的 ...

前辈,现在我的 HI_MPI_IVE_CSC(&hIveHandle,&stSrcData,&stDstData,&stCscCtrl,bInstant);
返回成功了,我想将转换后的图像数据保存下来,看图像数据有没有出错。但是映射地址的时候返回的是空指针,没有数据。并且报错:mmap error:Input/output error。尝试了很久都没有发现是哪里不对。
下面是我更新后的代码:

stSrcData.enType = IVE_IMAGE_TYPE_YUV420SP;   //广义图像的物理地址数组
stSrcData.au64PhyAddr[0] = stVFrame.stVFrame.u64PhyAddr[0];  //0
stSrcData.au64PhyAddr[1] = stVFrame.stVFrame.u64PhyAddr[1];  //
stSrcData.au64VirAddr[0] = stVFrame.stVFrame.u64VirAddr[0];  //0
stSrcData.au64VirAddr[1] = stVFrame.stVFrame.u64VirAddr[1];  //
stSrcData.au32Stride[0] = stVFrame.stVFrame.u32Stride[0];  //1920
stSrcData.au32Stride[1] = stVFrame.stVFrame.u32Stride[1];  //1920


stSrcData.u32Width   = stVFrame.stVFrame.u32Width;//1920
stSrcData.u32Height  = stVFrame.stVFrame.u32Height; //1080

stDstData.enType = IVE_IMAGE_TYPE_U8C3_PACKAGE;
stDstData.u32Width   = stSrcData.u32Width; //高宽同stSrcData
stDstData.u32Height  = stSrcData.u32Height;
stDstData.au32Stride[0]  = stSrcData.au32Stride[0]*3; //1920 ×3
stDstData.au32Stride[1]  = stVFrame.stVFrame.u32Stride[1]*3;

s32Ret = HI_MPI_SYS_MmzAlloc_Cached(&stDstData.au64PhyAddr[0], &stDstData.au64VirAddr[0], "User", HI_NULL, stDstData.u32Height*stDstData.au32Stride[0]);  //1080×1920×3

if(HI_SUCCESS != s32Ret)
{       
        HI_MPI_SYS_MmzFree(stSrcData.au64PhyAddr[0], stSrcData.au64VirAddr[0]);
        printf("HI_MPI_SYS_MmzAlloc_Cached Failed!");
        return s32Ret;
}

memset(stDstData.au64VirAddr[0], 0, stDstData.u32Height*stDstData.au32Stride[0]);
s32Ret = HI_MPI_SYS_MmzFlushCache(stDstData.au64PhyAddr[0], stDstData.au64VirAddr[0], stDstData.u32Height*stDstData.au32Stride[0]);
if(HI_SUCCESS != s32Ret)
{       

        HI_MPI_SYS_MmzFree(stDstData.au64PhyAddr[0], stDstData.au64VirAddr[0]);
        return s32Ret;
}

s32Ret = HI_MPI_IVE_CSC(&hIveHandle,&stSrcData,&stDstData,&stCscCtrl,bInstant);

if(HI_SUCCESS != s32Ret)
{       
        HI_MPI_SYS_MmzFree(stDstData.au64PhyAddr[0], stDstData.au64VirAddr[0]);
        return s32Ret;
}

pImage = (HI_U8*)HI_MPI_SYS_Mmap(stDstData.au64PhyAddr[0], stDstData.u32Height*stDstData.au32Stride[0]); //pImage返回是一个空指针, stDstData.au64PhyAddr[0]的值是 71c41000,

if (HI_NULL == pImage)
{
        printf("HI_MPI_SYS_Mmap fail \n");
        //HI_MPI_SYS_Munmap(pImage, stDstData.u32Height*stDstData.au32Stride[0]);
        return;
}
发表于 2019-7-12 18:08:12 | 显示全部楼层
qn1562136485 发表于 2019-7-12 17:47
前辈,现在我的 HI_MPI_IVE_CSC(&hIveHandle,&stSrcData,&stDstData,&stCscCtrl,bInstant);
返回成功了 ...

s32Ret = HI_MPI_SYS_MmzAlloc_Cached(&stDstData.au64PhyAddr[0], &stDstData.au64VirAddr[0], "User", HI_NULL, stDstData.u32Height*stDstData.au32Stride[0]);  //1080×1920×3

这里不是分配内存的时候已经有虚拟地址了吗, 再去mmap做什么?
 楼主| 发表于 2019-7-12 20:19:16 | 显示全部楼层
zhuangweiye 发表于 2019-7-12 18:08
s32Ret = HI_MPI_SYS_MmzAlloc_Cached(&stDstData.au64PhyAddr[0], &stDstData.au64VirAddr[0], "User",  ...

恩,前辈,我明白了真的是十分感谢您!我能够获得数据了,如果想把这些数据存成图片(想看一下图像有没有损坏),有这样的API接口呢,我应该往哪个方向努力呢?
发表于 2019-7-15 09:16:26 | 显示全部楼层
qn1562136485 发表于 2019-7-12 20:19
恩,前辈,我明白了真的是十分感谢您!我能够获得数据了,如果想把这些数据存成图片(想看一下图像有没有 ...

没有

按想要的格式, 自己写文件即可
 楼主| 发表于 2019-7-15 20:56:39 | 显示全部楼层
zhuangweiye 发表于 2019-7-15 09:16
没有

按想要的格式, 自己写文件即可

是的,已经实现。多谢前辈的指导,非常感谢!
发表于 2019-7-20 15:06:22 | 显示全部楼层
看懂了 基本上。  速度怎么样?  是不是rgb显示 也要这样做?  做lcd 屏幕显示的话
您需要登录后才可以回帖 登录 | 注册

本版积分规则

© 2008-2017 当前位置 易百纳技术社区论坛 返回 易百纳技术社区 ( 苏ICP备14036084 )   Powered by Discuz! X3.1
快速回复 返回顶部 返回列表