利用3156硬核实现yuv直方图数据提取
-
. 一 主要思路和步骤:
二 实现代码如下
static HI_VOID *SAMPLE_Ive_ViToVenc(HI_VOID *pArgs)
{
HI_S32 s32Ret;
//SAMPLE_IVE_MODEL_INFO_S *pstBgModelInfo;
//SAMPLE_IVE_BG_MODEL_S *pstBgModel;
VI_FRAME_INFO_S stFrameInfo;
VI_FRAME_INFO_S stExtFrameInfo;
VI_CHN viChn = 0;
VI_CHN viIveChn = 2;
HI_BOOL bEncode =HI_TRUE;
IVE_HANDLE IveHandle;
HI_U32 *pImage = NULL;
HI_U8 *pbuf_Y;
IVE_MEM_INFO_S stDst;
HI_VOID *pVirtDst;
HI_VOID *pVirtDst2;
pbuf_Y = (HI_U8*)malloc(442368);
memset(pbuf_Y,1,442368);
pImage = (HI_U8*)malloc(256*4);
memset(pImage,256*4);
//创建HI_MPI_IVE_DMA需要的两个地址结构体,分别传值原地址和目的地址
IVE_SRC_INFO_S stSrc2;
IVE_MEM_INFO_S stDst2;
CYF_IVE_MD_S pstMd; //建立一个dma搬运的目的帧结构
HI_BOOL bInstant = HI_TRUE;
HI_U32 phy_addr,size;
if (HI_MPI_VI_SetFrameDepth(viIveChn,1))
{
printf("HI_MPI_VI_SetFrameDepth err,viIveChn chn %d \n",viIveChn);
return ;
}
usleep(50000);
int sum =0;
//为dma搬运目的结构分配物理内存
s32Ret = HI_MPI_SYS_MmzAlloc_Cached(&pstMd.stSrc.u32PhyAddr[0],&pVirtDst2,NULL,HI_NULL,442368*3/2); //D1分辨率768*576的yuv422数据
//为直方图提取操作的目的地址分配物理内存
s32Ret = HI_MPI_SYS_MmzAlloc_Cached (&stDst.u32PhyAddr,&pVirtDst,256*4*3); // 用户态分配内存, 直方图256bin的u32数据(单通道)
if(s32Ret==HI_FAILURE)
{
printf("HI_MPI_SYS_MmzAlloc_Cached Failed!\n");
return HI_FAILURE;
}
usleep(50000);
while (1)
{
//获取每一帧数据
s32Ret = HI_MPI_VI_GetFrame(viIveChn,&stExtFrameInfo);
if (HI_SUCCESS != s32Ret)
{
printf("HI_MPI_VI_GetFrame fail,viIveChn(%d),Error(%#x)\n",viIveChn,s32Ret);
continue;
}
/*************************** DMA内存搬运**********/
//确定源数据地址和搬运目的地址
//stSrc2.enSrcFmt = IVE_SRC_FMT_SP422; //加入这句出错。
stSrc2.stSrcmem.u32PhyAddr= stExtFrameInfo.stVFrmInfo.stVFrame.u32PhyAddr[0];
stSrc2.stSrcmem.u32Stride = stExtFrameInfo.stVFrmInfo.stVFrame.u32Stride[0];
stSrc2.u32Width = stExtFrameInfo.stVFrmInfo.stVFrame.u32Width;
stSrc2.u32Height = stExtFrameInfo.stVFrmInfo.stVFrame.u32Height;
stDst2.u32PhyAddr = pstMd.stSrc.u32PhyAddr[0];
stDst2.u32Stride =stExtFrameInfo.stVFrmInfo.stVFrame.u32Stride[0];
bInstant = HI_FALSE;
s32Ret = HI_MPI_IVE_DMA(&IveHandle,&stSrc2,&stDst2,bInstant); ///????参数错误失败返回
if (HI_SUCCESS != s32Ret)
{
printf("HI_MPI_IVE_DMA fail,s32Ret);
return s32Ret;
}
pstMd.stSrc.u32Height = stExtFrameInfo.stVFrmInfo.stVFrame.u32Height;
pstMd.stSrc.u32Width = stExtFrameInfo.stVFrmInfo.stVFrame.u32Width;;
/****************************** HIST2 从内存搬运后的地方做hist*************************/
HI_BOOL bFinish,bBlock;
HI_BOOL bInstant = HI_TRUE;
IVE_SRC_INFO_S Src;
Src.enSrcFmt = IVE_SRC_FMT_SINGLE;
Src.stSrcmem.u32PhyAddr = pstMd.stSrc.u32PhyAddr[0]; //帧数据搬运后的地址
Src.stSrcmem.u32Stride = pstMd.stSrc.u32Width;
Src.u32Width = pstMd.stSrc.u32Width;
Src.u32Height = pstMd.stSrc.u32Height;
stDst.u32Stride = pstMd.stSrc.u32Width; //直方图数据目的地址
s32Ret = HI_MPI_IVE_HIST(&IveHandle,&Src,&stDst,bInstant); //操作后将结果指针指向分配好的地址上
if (HI_SUCCESS != s32Ret)
{
printf("%s: HI_MPI_IVE_HIST Failed!\n",__FUNCTION__);
return HI_FAILURE;
}
s32Ret = HI_MPI_IVE_Query(IveHandle,&bFinish,bBlock); //查询是否操作成功
if(s32Ret != HI_SUCCESS)
{
printf("HI_MPI_IVE_Query fail,s32Ret);
return;
}
pImage = (HI_U32 *)HI_MPI_SYS_Mmap(stDst.u32PhyAddr,256*4); //物理地址映射给用户虚拟地址
if(pImage ==NULL)
{
printf("%s: HI_MPI_SYS_Mmap Failed!\n");
}
HI_U32 pix3 = (HI_U32)(*(pImage+10));
printf("pix his is %u \n",pix3);
HI_MPI_SYS_Munmap(pImage,256*4);
/****************************** HIST2 从内存搬运后的地方做hist*************************/
s32Ret = HI_MPI_VI_ReleaseFrame(viIveChn,&stExtFrameInfo);
if (HI_SUCCESS != s32Ret)
{
printf("HI_MPI_VI_ReleaseFrame fail,s32Ret);
}
usleep(1000);
}
return HI_NULL;
}