目录
海思3518的sample中,创建好视频缓存池及初始化完毕后,就进入第三步,开启vedio in device和channel
海思video input模块架构介绍
海思的3518E的内部ISP单元是隶属于VI模块的,海思的video input模块包含三大部分
- 和sensor的接口对接
- ISP
- device,用来采集图像的硬件单元,也是视频通道的入口
海思video input模块功能介绍
有的sensor内部有AD转换,数字信号出来之后,就到device,也就是海思VI的第三部分
有的sensor没有内置AD转换器,需要外界一个AD转换
主要实现的功能
将sensor采集到的数字视频信号进行isp处理,再进行镜头畸变矫正(LDC)、动态对比度调节(DCI)、DIS(消抖)模块处理,最后通过dev将处理好的视频丢进通道,和其他模块进行交互
结构体说明
/******************************************
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;
}
主要的结构体为
SAMPLE_VI_CONFIG_S stViConfig
SAMPLE_VI_CONFIG_S如下
其中
- stViConfig.enViMode为makefile中配置的sensor
- stViConfig.enRotate为NULL即不旋转
- stViConfig.enNorm为自动选择编码制式
- stViConfig.enViChnSet为无翻转
- stViConfig.enWDRMode为不选用WDR
函数调用关系
流程分析
SAMPLE_COMM_VI_StartVi
函数中,首先执行的是IsSensorInput
,此函数的功能为判断输入的视频是否是由sensor采集的,输入参数为makefile中配置的sensor类型
HI_BOOL IsSensorInput(SAMPLE_VI_MODE_E enViMode)
{
HI_BOOL bRet = HI_TRUE;
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;
}
return bRet;
}
如代码所示,若makefile中配置的是D1、BT1120,则判定为不是sensor采集的视频,这两个是老式电视的标准。
enViMode = pstViConfig->enViMode;
if(!IsSensorInput(enViMode))
{
s32Ret = SAMPLE_COMM_VI_StartBT656(pstViConfig);
}
else
{
s32Ret = SAMPLE_COMM_VI_StartIspAndVi(pstViConfig);
}
如果是传统的电视标准,则走的是startBT656这一条,若是用sensor采集的,就用startIspAndVi这一路。
显然,我们要研究的是走sensor的这条路
于是进入SAMPLE_COMM_VI_StartIspAndVi
函数
step 1: mipi configure
mipi是sensor和3518e的接口
常用Sensor的接口有三种:
- MIPI
- LVDS
- DC
/******************************************
step 1: mipi configure
******************************************/
s32Ret = SAMPLE_COMM_VI_StartMIPI(pstViConfig);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("%s: MIPI init failed!\n", __FUNCTION__);
return HI_FAILURE;
}
这部分只有一个SAMPLE_COMM_VI_StartMIPI
函数,这个函数中有一个SAMPLE_COMM_VI_SetMipiAttr
,作用是设置sensor的一些属性
SAMPLE_COMM_VI_SetMipiAttr
中,首先打开mipi驱动加载进去后/dev底下生成的文件
接着根据不同的sensor为SAMPLE_COMM_VI_SetMipiAttr
填充不同的参数
最后通过ioctl
将参数设置给sensor
step 2: configure sensor and ISP(include WDR mode)
这一步也可以跳过,就看你要不要用3518处理你的图像
/******************************************
step 2: configure sensor and ISP (include WDR mode).
note: you can jump over this step, if you do not use Hi3516A interal isp.
******************************************/
s32Ret = SAMPLE_COMM_ISP_Init(pstViConfig->enWDRMode);
if (HI_SUCCESS != s32Ret)
{
SAMPLE_PRT("%s: Sensor init failed!\n", __FUNCTION__);
return HI_FAILURE;
}
第一步先注册sensor的回调,为什么这么做,需要结合sensor和isp处理来看
第二部注册AE(自动曝光),进行自动曝光
第三步初测AWB,进行自动白平衡
第四步注册AF,自动对焦
第五步申请isp单元所用内存
第六步设置WDR宽动态相关属性,属性由参数传入
第七步设置sensor的pub属性,不同sensor的阵列不同,参考详解相机的sensor工作原理,设置完毕后,由HI_MPI_ISP_SetPubAttr
将属性写入
第八步最终初始化,将上面设置好的属性进行落实
step 3: run isp thread
- SAMPLE_COMM_ISP_Run();
- pthread_create(&gs_IspPid, &attr, (void* ()(void))
- Test_ISP_Run, NULL)
- Test_ISP_Run(HI_VOID *param)
- HI_MPI_ISP_Run(IspDev);
上一步所有isp相关的属性设置完毕后,将isp放在一个线程里面跑
思考:为什么海思不把isp全部做好? 因为它支持多种sensor,每个sensor参数不同,所以需要用户自己配置。海思方案是做好算法,做好数据结构,让用户进行填充。
工作中,有一种情况是可以和厂商沟通,定好sensor后isp部分由厂商完成
这一部分是isp相关操作,isp方向需要重点研究
step 4 : config & start vicap dev
isp在线程中跑起来之后,进入这一步start device
device,用来采集图像的硬件单元,也是视频通道的入口
首先HI_MPI_VI_SetDevAttr
,将sensor采集图像的起始点、图像尺寸进行设置
然后HI_MPI_ISP_GetWDRMode
获取WDR模式
获取之后HI_MPI_VI_SetWDRAttr
进行设置
最后将HI_MPI_VI_EnableDev
VI enable
Step 5: config & start vicap chn (max 1)
在之前通过sensor判断已经定好了通道的数量
这边就依次将通道打开
在函数SAMPLE_COMM_VI_StartChn
中,通过SDK提供的API可以对channel的属性、旋转进行设置,最后将通道enable
至此,海思VI模块完毕,后续的操作都是对通道进行操作