微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

利用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,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;

}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐