当前位置: 首页 > news >正文

Hi3518E官方录像例程源码流程分析(三)

文章目录

  • 第二阶段,初始化第一阶段计算好的参数
    • SAMPLE_COMM_SYS_Init
  • 第三阶段,启动VI和chn捕获
    • SAMPLE_COMM_VI_StartVi()
    • SAMPLE_COMM_VI_StartBT656
      • 小阶段1 SAMPLE_COMM_VI_StartMIPI_BT1120()
      • 小阶段1 SAMPLE_COMM_VI_StartDev()
        • HI_MPI_ISP_GetWDRMode
        • HI_MPI_VI_SetWDRAttr
        • HI_MPI_VI_EnableDev
      • 小阶段二 配置和启动VI捕获通道
      • SAMPLE_COMM_VI_StartChn()
        • HI_MPI_VI_SetRotate
        • HI_MPI_VI_EnableChn

源码地址 + 文档资料 – 提取码: chmr

本专栏分析的是mpp\venc\sample\sample_venc.c

第二阶段,初始化第一阶段计算好的参数

    /******************************************step 2: mpp system init. ******************************************/s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf);//VB_CONF_S stVbConf;if (HI_SUCCESS != s32Ret){SAMPLE_PRT("system init failed with %d!\n", s32Ret);goto END_VENC_1080P_CLASSIC_0;}

第二阶段的内容还是很简单的,就是把第一阶段计算好的参数都初始化进系统

SAMPLE_COMM_SYS_Init

先是函数SAMPLE_COMM_SYS_Init

里面的内容也很简单,调用到的函数都是海思官方提供的库函数,我们也没办法看到函数的内部实现,在我给的链接里也有官方的数据手册,里面也有写每个API都是干嘛的

    MPP_SYS_CONF_S stSysConf = {0};HI_S32 s32Ret = HI_FAILURE;//In case there are things left behind before that have not been cleaned up.HI_MPI_SYS_Exit();//firstHI_MPI_VB_Exit(); //lastif (NULL == pstVbConf){SAMPLE_PRT("input parameter is null, it is invaild!\n");return HI_FAILURE;}s32Ret = HI_MPI_VB_SetConf(pstVbConf);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("HI_MPI_VB_SetConf failed!\n");return HI_FAILURE;}s32Ret = HI_MPI_VB_Init();if (HI_SUCCESS != s32Ret){SAMPLE_PRT("HI_MPI_VB_Init failed!\n");return HI_FAILURE;}stSysConf.u32AlignWidth = SAMPLE_SYS_ALIGN_WIDTH;s32Ret = HI_MPI_SYS_SetConf(&stSysConf);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("HI_MPI_SYS_SetConf failed\n");return HI_FAILURE;}s32Ret = HI_MPI_SYS_Init();if (HI_SUCCESS != s32Ret){SAMPLE_PRT("HI_MPI_SYS_Init failed!\n");return HI_FAILURE;}

这里进来先是调用了两个清理函数

    HI_MPI_SYS_Exit();//firstHI_MPI_VB_Exit(); //last

应该是用来防止之前留下的内容没被清理或释放

然后再需要注意一下的就是函数的调用顺序
先清理SYS空间,再是VB(缓存池)
后面的函数是用来设置第一阶段计算好的参数和缓存池,调用顺序是先设置VB,再是SYS

第二阶段的内容就这些,比较简单

第三阶段,启动VI和chn捕获

视频输入(VI)模块实现的功能:VI 可以对接收到的原始视频图像数据进行裁剪(Crop)等处理,并实现一路原始视频图像输入,输出一路视频图像功能。
虽然阶段三看着只有一个函数,但是里面的内容就多了

    /******************************************step 3: start vi dev & chn to capture******************************************/stViConfig.enViMode   = SENSOR_TYPE;stViConfig.enRotate   = ROTATE_NONE;stViConfig.enNorm     = VIDEO_ENCODING_MODE_AUTO;stViConfig.enViChnSet = VI_CHN_SET_NORMAL;stViConfig.enWDRMode  = WDR_MODE_NONE;s32Ret = SAMPLE_COMM_VI_StartVi(&stViConfig);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("start vi failed!\n");goto END_VENC_1080P_CLASSIC_1;}

第三阶段前面先是设置了一些视频参数

stViConfig.enViMode = SENSOR_TYPE;这个是传感器类型,前面提到过的我用的传感器是AR0130
stViConfig.enRotate = ROTATE_NONE;这个参数决定了输出的视频是否需要旋转,如输出的视频是原视频旋转90度或180度这种
stViConfig.enNorm = VIDEO_ENCODING_MODE_AUTO;这个再上一章节也有提到,就是PAL和NTSC两种格式,这里选的是AUTO自动选择
stViConfig.enViChnSet = VI_CHN_SET_NORMAL;这个参数决定输出的视频是否翻转或镜像
stViConfig.enWDRMode = WDR_MODE_NONE;WDR(Wide Dynamic Range),宽动态

SAMPLE_COMM_VI_StartVi()

HI_S32 SAMPLE_COMM_VI_StartVi(SAMPLE_VI_CONFIG_S* pstViConfig)
{HI_S32 s32Ret = HI_SUCCESS;SAMPLE_VI_MODE_E enViMode;  if(!pstViConfig){SAMPLE_PRT("%s: null ptr\n", __FUNCTION__);return HI_FAILURE;}enViMode = pstViConfig->enViMode;//Determine whether the image source is a sensorif(!IsSensorInput(enViMode)){s32Ret = SAMPLE_COMM_VI_StartBT656(pstViConfig);}else{	//sansor choices32Ret = SAMPLE_COMM_VI_StartIspAndVi(pstViConfig);}return s32Ret; 
}

进来以后会先进入这个if判断
这里面就是判断是否支持之前定义过的视频格式

    if(!IsSensorInput(enViMode)){........}IsSensorInput()
{switch(enViMode){case SAMPLE_VI_MODE_1_D1:case SAMPLE_VI_MODE_BT1120_1080P:case SAMPLE_VI_MODE_BT1120_720P:bRet = HI_FALSE;break;default:break;}
}

然后我们命中到这个函数

SAMPLE_COMM_VI_StartBT656

这里面的内容就多了

    VI_DEV ViDev;VI_CHN ViChn;HI_U32 u32DevNum = 1;HI_U32 u32ChnNum = 1;

进来先是设备数和通道数初始化

小阶段1 SAMPLE_COMM_VI_StartMIPI_BT1120()

HI_S32 SAMPLE_COMM_VI_StartMIPI_BT1120(SAMPLE_VI_MODE_E enViMode)
{HI_S32 fd;combo_dev_attr_t *pstcomboDevAttr = NULL;fd = open("/dev/hi_mipi", O_RDWR);if (fd < 0){printf("warning: open hi_mipi dev failed\n");return -1;}if( (enViMode == SAMPLE_VI_MODE_BT1120_720P)||(enViMode == SAMPLE_VI_MODE_BT1120_1080P) ){pstcomboDevAttr = &MIPI_BT1120_ATTR;}else{}if (NULL == pstcomboDevAttr){printf("Func %s() Line[%d], unsupported enViMode: %d\n", __FUNCTION__, __LINE__, enViMode);close(fd);return HI_FAILURE;   }if (ioctl(fd, HI_MIPI_SET_DEV_ATTR, pstcomboDevAttr)){printf("set mipi attr failed\n");close(fd);return HI_FAILURE;}close(fd);return HI_SUCCESS;
}

这里面就是打开vi驱动设备了

fd = open("/dev/hi_mipi", O_RDWR);
ioctl(fd, HI_MIPI_SET_DEV_ATTR, pstcomboDevAttr)

打开设备以后在根据设备数量启动设备
在这里插入图片描述

由手册可知Hi3518EV200只有一个vi设备

小阶段1 SAMPLE_COMM_VI_StartDev()

进来先是开辟内存空间?
根据我的传感器会定位到这个

case APTINA_AR0130_DC_720P_30FPS:memcpy(&stViDevAttr,&DEV_ATTR_9M034_DC_720P_BASE,sizeof(stViDevAttr));break;

然后就是把前面设置的参数真正写入硬件处理,调用到的也是海思官方提供的库函数
就是之前这些

    stViConfig.enViMode   = SENSOR_TYPE;stViConfig.enRotate   = ROTATE_NONE;stViConfig.enNorm     = VIDEO_ENCODING_MODE_AUTO;stViConfig.enViChnSet = VI_CHN_SET_NORMAL;stViConfig.enWDRMode  = WDR_MODE_NONE;

然后是海思官方的宽动态(WDR)设置

HI_MPI_ISP_GetWDRMode
HI_MPI_VI_SetWDRAttr

设备启动

HI_MPI_VI_EnableDev

小阶段二 配置和启动VI捕获通道

由手册得3518EV支持一个物理通道和两个扩展通道

视频物理通道负责将输入设备解析后得到的视频数据输出到 DDR。在真正将数据
输出到 DDR 之前,它可以实现裁剪等功能,

扩展通道是物理通道的扩展,主要实现缩放功能,其数据来源于物理通道。
Hi3516A/Hi3518EV200/Hi3519V100 最多支持 16 个扩展通道。
在这里插入图片描述
物理通道Chn0和扩展通道Chn1,Chn2
在这里插入图片描述
在这里插入图片描述
阶段二先是对各个通道输出的视频尺寸大小做了设置

        switch (enViMode){case SAMPLE_VI_MODE_BT1120_720P:           stCapRect.u32Width = 1280;stCapRect.u32Height = 720;break;case SAMPLE_VI_MODE_BT1120_1080P:           stCapRect.u32Width  = 1920;stCapRect.u32Height = 1080;break; default:stCapRect.u32Width  = 1920;stCapRect.u32Height = 1080;break;}

然后进入这个函数

SAMPLE_COMM_VI_StartChn()

进来以后就是设置每个通道输出的视频的大小,是否旋转,是否镜像,是否翻转,是什么格式YUV420 \ 422

    if(pstViConfig){enViChnSet = pstViConfig->enViChnSet;enRotate = pstViConfig->enRotate;}/* step  5: config & start vicap dev */memcpy(&stChnAttr.stCapRect, pstCapRect, sizeof(RECT_S));stChnAttr.enCapSel = VI_CAPSEL_BOTH;/* to show scale. this is a sample only, we want to show dist_size = D1 only */stChnAttr.stDestSize.u32Width = pstTarSize->u32Width;stChnAttr.stDestSize.u32Height = pstTarSize->u32Height;stChnAttr.enPixFormat = PIXEL_FORMAT_YUV_SEMIPLANAR_420;   /* sp420 or sp422 */stChnAttr.bMirror = HI_FALSE;stChnAttr.bFlip = HI_FALSE;switch(enViChnSet){case VI_CHN_SET_MIRROR:stChnAttr.bMirror = HI_TRUE;break;case VI_CHN_SET_FLIP:stChnAttr.bFlip = HI_TRUE;break;case VI_CHN_SET_FLIP_MIRROR:stChnAttr.bMirror = HI_TRUE;stChnAttr.bFlip = HI_TRUE;break;default:break;}

默认的帧率控制

    stChnAttr.s32SrcFrameRate = -1;stChnAttr.s32DstFrameRate = -1;

然后是海思的设置通道参数的库函数

HI_MPI_VI_SetRotate

打开通道

HI_MPI_VI_EnableChn

相关文章:

  • JVM:程序计数器、虚拟机栈、本地方法栈
  • Docker Compose 中配置 Host 网络模式
  • Spring Task(笔记)
  • Android --- FrameWork 入门:Product是什么?
  • winfrom 查询某字符串 找到它在 richTextbox 的位置 定位 并高亮 并且滚动定位到所查询的字符串所在的行
  • Meltdown原理介绍:用户空间读取内核内存
  • apt3.0和apt2.0的区别
  • AI数字人分身无限克隆,开启IP视频创作新纪元!
  • 如何判断一个js对象是否拥有某个属性(区分自身属性和原型链上的属性)?
  • [管理与领导-129]:向上管理-组织架构、股权架构、业务架构、流程架构,看每个人在组织中的位置和重要性
  • Angular 框架详解:从入门到进阶
  • 数据库主从复制
  • 解决Ubuntu终端命令不能补全的问题
  • Linux:解决 yum 官方源无法使用(CentOS 7)
  • postman使用技巧
  • Postman做自动化测试
  • opencv函数展示
  • 【数字图像处理】数字图像空间域增强(3)
  • WIFI扫描记录
  • Spark-SQL核心编程(二)(三)
  • 做网站的大创结项/引流最好的推广方法
  • 网站建设与维护结课论文/厦门seo顾问屈兴东
  • 个人网站吗/创建app平台
  • 我的网站360搜索被做跳转/杭州百度seo
  • 海南省建设网站的公司/微信附近人推广引流
  • 南宁网站建设费用/网站提交入口