利用3156硬核实现yuv直方图数据提取

利用3156硬核实现yuv直方图数据提取

  • . 一 主要思路和步骤:

    1. 分配物理空间HI_MPI_SYS_MmzAlloc_Cached
    2. 在一个线程中循环获取帧(*HI_MPI_VI_GetFrame*)
    3. 将原始帧物理地址搬运至新开辟的地址(直接最原始帧的物理地址操作会出现问题,直方图提取可能会失败) HI_MPI_IVE_DMA
    4. 调用ive的API函数实现直方图提取HI_MPI_IVE_HIST
    5. 由于硬核处理函数都是对物理地址做操作,用户态想获取数据必须将其转换为虚拟地址,即调用HI_MPI_SYS_Mmap
  • 二 实现代码如下

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,1,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,NULL, HI_NULL, 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,Error(%#x)\n",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,Error(%#x)\n",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,viIveChn(%d),Error(%#x)\n",viIveChn,s32Ret);
            }

    usleep(1000);
    }
    return HI_NULL;

}



  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值