海思mpp之VENC(视频编码)流程分析

通道和变量说明:
编码通道s32ChnNum=2;//一个是4k120一个是1080p30
enPayLoad[2]  = {PT_H265, PT_H264};//两种编码方式
VpssGrp        = 0;
VpssChn[2]     = {0,1};

一、获取两个编码通道的需要编码的具体分辨率
二、获取sensor的信息
三、检查sensor
主要的工作内容是获取sensor的宽高,检查需要编码的视频的宽高是否大于sensor能够捕获的最大宽高。如果大于则说明编码分辨率设置错误。
四、VI的初始化
1.venc初始化
获取sensor的分辨率,并计算出需要的vb块大小(这里计算了两个,一个是sensor的分辨率,一个是1920 *1080的分辨率),并且缓存池的数量是2(stVbConf.u32MaxPoolCnt = 2;)
设置 MPP 视频缓存池属性,初始化VB,初始化sys:
HI_MPI_SYS_Exit();
HI_MPI_VB_Exit();
HI_MPI_VB_SetConfig(pstVbConfig);
HI_MPI_VB_Init();
HI_MPI_SYS_Init();

2.根据sensor的类型获取帧率u32FrameRate。
3.获取ISP的控制参数。
打开isp_dev设备节点,获取控制参数:ioctl(g_as32IspFd[ViPipe], ISP_GET_CTRL_PARAM, pstIspCtrlParam);
stIspCtrlParam.u32StatIntvl  = u32FrameRate/30;
ioctl(g_as32IspFd[ViPipe], ISP_SET_CTRL_PARAM, pstIspCtrlParam);
4.start mipi
.设置mipi的模式
fd = open("/dev/hi_mipi", O_RDWR);
ioctl(fd, HI_MIPI_SET_HS_MODE, LANE_DIVIDE_MODE_7);
close(fd);
.使能mipi时钟
fd = open("/dev/hi_mipi", O_RDWR);
ioctl(fd, HI_MIPI_ENABLE_MIPI_CLOCK, &devno);
close(fd);
.reset mipi
fd = open("/dev/hi_mipi", O_RDWR);
s32Ret = ioctl(fd, HI_MIPI_RESET_MIPI, &devno);
close(fd);
.使能sensor时钟
fd = open("/dev/hi_mipi", O_RDWR);
ioctl(fd, HI_MIPI_ENABLE_SENSOR_CLOCK, &SnsDev);
close(fd);
.reset sensor
fd = open("/dev/hi_mipi", O_RDWR);
s32Ret = ioctl(fd, HI_MIPI_RESET_SENSOR, &SnsDev);
close(fd);
.设置mipi的属性
fd = open("/dev/hi_mipi", O_RDWR);
ioctl(fd, HI_MIPI_SET_DEV_ATTR, &stcomboDevAttr);//raw图位宽,
close(fd);
.mipi解复位
fd = open("/dev/hi_mipi", O_RDWR);
ioctl(fd, HI_MIPI_UNRESET_MIPI, &devno);
close(fd);
.sensor解复位
open("/dev/hi_mipi", O_RDWR);
ioctl(fd, HI_MIPI_UNRESET_SENSOR, &SnsDev);
close(fd);
5.set vi vpss的工作模式
HI_MPI_SYS_SetVIVPSSMode(&stVIVPSSMode);//定义 VI 各个 PIPE 和 VPSS 各个组的工作模式。
typedef enum hiVI_VPSS_MODE_E
{
VI_OFFLINE_VPSS_OFFLINE = 0,
VI_OFFLINE_VPSS_ONLINE,
VI_ONLINE_VPSS_OFFLINE,
VI_ONLINE_VPSS_ONLINE,
VI_PARALLEL_VPSS_OFFLINE,
VI_PARALLEL_VPSS_PARALLEL,
VI_VPSS_MODE_BUTT
} VI_VPSS_MODE_E;
6.创建vi和ISP
.创建VI
HI_MPI_VI_SetDevAttr(ViDev, &stViDevAttr);
HI_MPI_VI_EnableDev(ViDev);
HI_MPI_VI_SetDevBindPipe(pstViInfo->stDevInfo.ViDev, &stDevBindPipe);//vi设备和物理pipe的绑定关系
HI_MPI_VI_CreatePipe(ViPipe, &stPipeAttr);
HI_MPI_VI_SetChnAttr(ViPipe, ViChn, &stChnAttr);
HI_MPI_VI_EnableChn(ViPipe, ViChn);// vi在线VPSS在线模式、VI离线VPSS在线模式, VI并行VPSS 并行模式下,启动VI通道不生效,直接返回成功。
.创建ISP
以下的操作,每个输入工作通道都需要处理。
获得回调函数指针:sensor_register_callback
执行注册的回调函数:sensor_register_callback
sensor_register_callback
    cmos_init_sensor_exp_function(&stIspRegister.stSnsExp);
    HI_MPI_ISP_SensorRegCallBack(ViPipe, &stSnsAttrInfo, &stIspRegister);
    cmos_init_ae_exp_function(&stAeRegister.stSnsExp);
    HI_MPI_AE_SensorRegCallBack(ViPipe, pstAeLib, &stSnsAttrInfo, &stAeRegister);
    cmos_init_awb_exp_function(&stAwbRegister.stSnsExp);
    HI_MPI_AWB_SensorRegCallBack(ViPipe, pstAwbLib, &stSnsAttrInfo, &stAwbRegister);
根据sensor的不同,注册不同的控制总线(iic或者ssp)
HI_MPI_AE_Register(IspDev, &stAeLib);
HI_MPI_AWB_Register(IspDev, &stAwbLib)

HI_MPI_ISP_MemInit(ViPipe);
HI_MPI_ISP_SetPubAttr(ViPipe, &stPubAttr);
HI_MPI_ISP_Init(ViPipe);
pthread_create(&g_IspPid[*pIspDev], pstAttr, SAMPLE_COMM_ISP_Thread, (HI_VOID*)pIspDev);
SAMPLE_COMM_ISP_Thread
    HI_MPI_ISP_Run(IspDev);

五、VPSS初始化
1.通过sensor的型号确定分辨率
2. VPSS start
HI_MPI_VPSS_CreateGrp(VpssGrp, pstVpssGrpAttr);
    //以下两个操作同一个goroup下面的4个通道都需要
    HI_MPI_VPSS_SetChnAttr(VpssGrp, VpssChn, &pastVpssChnAttr[VpssChn]);
    HI_MPI_VPSS_EnableChn(VpssGrp, VpssChn);
HI_MPI_VPSS_StartGrp(VpssGrp);
六、VI bind VPSS
stSrcChn.enModId   = HI_ID_VI;
stSrcChn.s32DevId  = ViPipe;
stSrcChn.s32ChnId  = ViChn;
stDestChn.enModId  = HI_ID_VPSS;
stDestChn.s32DevId = VpssGrp;
stDestChn.s32ChnId = 0;
HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);
七、start stream venc
确定用户选择的rc模式和gop模式,并根据这些用户选择确定gop属性。
八、encode h.265 h.264
1.VENC creat
HI_MPI_VENC_CreateChn(VencChn, &stVencChnAttr);//参数中对h.264 h.265 jpeg等编码做了区分。
2.HI_MPI_VENC_StartRecvFrame(VencChn,&stRecvParam);//开启编码通道接收输入图像, 允许指定接收帧数,超出指定的帧数后自动停止接收图像

3. stSrcChn.enModId   = HI_ID_VPSS;
stSrcChn.s32DevId  = VpssGrp;
stSrcChn.s32ChnId  = VpssChn;

stDestChn.enModId  = HI_ID_VENC;
stDestChn.s32DevId = 0;
stDestChn.s32ChnId = VencChn;
HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);// h.265 h.264 VpssChn和VencChn的值分别是0和1. VpssGrp = 0

九、stream save process
pthread_create(&gs_VencPid,0,SAMPLE_COMM_VENC_GetVencStreamProc, (HI_VOID*)&gs_stPara);
SAMPLE_COMM_VENC_GetVencStreamProc// get stream from each channels and save them
    
十、exit process
1.杀死上面创建的获取数据流的线程
pthread_join(gs_VencPid, 0);
2.VPSS 和VENC解绑定VENC停止。要分为H264 H265,参数要求同上面绑定操作一样。
3.下面两步操作需要分为H264 H265, VencChn取值分别为0,1
HI_MPI_VENC_StopRecvFrame(VencChn);//stop recv picture
HI_MPI_VENC_DestroyChn(VencChn);// Distroy Venc Channel
4.VI和VPSS解绑定
stSrcChn.enModId   = HI_ID_VI;
stSrcChn.s32DevId  = ViPipe;
stSrcChn.s32ChnId  = ViChn;

stDestChn.enModId  = HI_ID_VPSS;
stDestChn.s32DevId = VpssGrp;
stDestChn.s32ChnId = 0;
HI_MPI_SYS_UnBind(&stSrcChn, &stDestChn)
5.VPSS停止
HI_MPI_VPSS_StopGrp(VpssGrp);
    HI_MPI_VPSS_DisableChn(VpssGrp, VpssChn);
HI_MPI_VPSS_DestroyGrp(VpssGrp);
6.VI stop
SAMPLE_COMM_VI_DestroyIsp(pstViConfig);
SAMPLE_COMM_VI_DestroyVi(pstViConfig);
SAMPLE_COMM_VI_StopMIPI(pstViConfig);
7.sysexit
HI_MPI_SYS_Exit();
HI_MPI_VB_Exit();

 

你可能感兴趣的:(mpp,Hi3559V100,hi3559av100)