mpp中的例程
- 每一个例程面向一个典型应用,common是通用性主体函数,我们只分析venc
- venc中的main调用venc中的功能函数,再调用common中的功能函数,再调用mpp中的API,再调用 HI3518E内部的硬件单元。
- H.264 H.265 MJPEG 视频编码规范标准
- 1080P、720P、VGA、D1 视频分辨率(清晰度)
- fps(frame per second) 帧率
海思编码规范
例程中结构体和枚举类型定义都是全大写字母用下划线分隔开,定义后面会用下划线带字母表示类型,采用驼峰法命名.
符号 | 含义 |
---|
*_E | 枚举类型 |
*_S | 结构体类型 |
en* | 枚举变量 |
st* | 结构体变量 |
关键变量和API
名词 | 解释 |
---|
PAYLOAD_TYPE_E | 被传输传输文件类型(码流类型) |
butt | 枚举或者结构体中的结尾符 |
VB_CONFIG_S | 视频缓存池设置参数 |
HI_MPI_VB_SetConf() | 设置VB_CONFIG_S的参数到mpp中 |
HI_MPI_VB_Init() | 执行mpp中设置的参数,使生效 |
视频处理名词缩写
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210603151354470.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NjEzMzE0,size_16,color_FFFFFF,t_70)
缩写 | 含义 |
---|
VI | 视频输入 |
VO | 视频输出 |
VPSS | 视频处理 |
VENC | 视频编码 |
VDEC | 视频解码 |
VO | 视频输出 |
AVS | 视频拼接 |
AI | 音频输入 |
AO | 音频输出 |
AENC | 音频编码 |
ADEC | 音频解码 |
REGION | 区域管理 |
- VI模块捕获视频图像,可以对其做剪切,缩放等处理,并输出多路不同分辨率的图像数据。解码模块对编码后的视频流码进行解析,并将解析后的图像数据送VPSS进行图像处理或者送VO显示,可对H254/MPGE4/MPEG2格式的视频流进行解码。
- VPSS模块接收VI和解码模块发送过来的图像,可对图像进行去噪、图像增强、锐化等处理,并实现同源输出多路不同分辨率的图像数据。用于编码,预览,抓拍。
- 编码模块接收VI捕获并经过VPSS处理后输出的图像数据,可叠加用户通过Region模块设置OSD图像,然后按不同的协议进行编码并输出相应码流
- VDA模块接收VI的输出图像,并进行移动侦测和遮挡侦测,最后处处侦测分析结果
- VO模块接收VPSS处理后的图像,可进行播放控制等处理,最后按照用户配置的输出协议输出给外围视频设备。
- AI模块捕获音频数据,然后AENC模块支持按多种音频协议对齐进行编码,最后输出音频码流
- 用户从网络或者外围存储设备获取的音频码流可以直接发送给ADEC模块,ADEC解码多种不同音频格式码流,解码后数据发送给AO模块即可播放声音。
VI
-
概述:视频输入(VI)模块实现的功能:通过ITU-R BT656/601/1120接口或者Digital Camera接口,LVDS接口和HISPI接口接收视频数据
- 当工作在离线模式下,接受到的数据将存入指定内存区域
- 当工作在在线模式下,VI会将接收到的数据直接送到VPSS,在此过程汇总VI可以对接收到的原始视频图像数据进行裁剪等处理,并实现一路原始视频图像输入,输出一路视频图像功能。
2 重要概念
视频输入设备
- 时请输入设备支持若干种时序输入,负责对是虚假进行解析
在线模式与离线模式
- 离线模式:是指VI写出数据到DDR,然后与之绑定的模块从DDR读取数据
- 在线模式:VI与VPSS之间在线数据流传输,在此模块下VI不会写出到DDR,而是直接把数据流送给VPSS
视频物理通道
- 视频物理通道将负责输入设备解析后得到的视频数据输出到DDR。在真正将数据输出到DDR之前,他可以实现裁剪等功能,具体功能键各芯片详细描述
掩码
镜头畸变矫正(LDC)
- Dynamic Contrast Improvement ,动态调节对比度,对图像进行动态对比度调节,即在增强图像暗区亮度时而不是亮区过亮,或者降低亮区亮度时而不使暗区过暗。
什么是视频缓冲池
- 视频的本质是多帧图片,图片的本质是RGB或rawRGB数据,要占用一段连续内存
- 视频的裁剪、缩放、修正处理等各种操作,本质上就是对内存中的数据进行运算
- 视频缓存池(VB, video buffer)就是一段很大,又被合理划分和管理的内存,用来做视频数据的暂存和运算场地
- 公共视频缓存池的公共2字,可以理解为全局变量,也就是各个模块都能访问的一段内存
- 看似视频缓存块在各个模块之间流转,实际上并没有内存复制,而是指针在传递
- 视频缓存池的内存由MPP来维护,我们在系统启动时就把整个SDRAM分成了2部分:系统部分(由linux kernel来维护管理)和mpp部分(由mpp系统来维护管理)
- 缓存池需要几个,每个中包含几个缓存块,每个缓存块多大,都是可以由用户程序设置好参数,然后调用MPP的相应API来向MPP申请分配的。
- 相关的数据结构和API
(1)VB_CONF_S
(2)HI_MPI_VB_SetConf
(3)HI_MPI_VB_Init
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210415112936395.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NjEzMzE0,size_16,color_FFFFFF,t_70)
常用的SENSOR接口
- 常用的sensor接口有三种: MIPI ,LVDS,DC(并口)
- 动态:在同一幅图片中最亮的地方和最暗地方的比例,对硬件有要求
- WDR(宽动态):在同一幅图片中,局部曝光和其他地方的曝光不一样,如下图
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210416095842674.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NjEzMzE0,size_16,color_FFFFFF,t_70#pic_center)
- isp(image signal process):图像信号处理,3518E内部也有ISP硬件单元(自动曝光,自动对焦,自动白平衡)
- 3516内部的ISP属于VI模块,VI模块包含3部分:第一部分MIPI sensor和3516对接的接口,第二部分ISP 图像处理单元,第三部分
视频处理子系统vpss(vedio Process Sub-System)
-
VPSS(vedio Process Sub-System)支持对一幅输入图像进行统一处理,如去噪 去隔行等,然后对各通道分别进行缩放,锐化等处理,最后输出多种部分分辨率的图像
-
VPSS支持的具体图像处理功能包括FRC,Crop,NR,LDC,Rotate,COVER/Coverlay,Scale,Mirror/Flip,FishEye
-
VPSS一般是一进多出、
-
group: VPSS的虚拟化,就是把一个VPSS硬件虚拟成多个VPSS,每个VPSSgroup可以分时复用硬件VPSS
-
channel:通道分成2种,物理通道和扩展通道,VPSS提供多个物理通道,物理通道可以缩放,裁剪扩展通道具备缩放功能,可以把物理通道输出作为扩展通道的输入,把图像缩放成用户需要的分辨率输出
-
FRC:帧率控制分为group帧率控制和chn帧率控制
- group帧率控制:用于控制group对于图像的接收
- 通道帧率控制:用于控制各物理通道和扩展通道图像的处理
-
PIPE :VPSS组的管道,只能取0
-
CROP: 裁剪分为3种:组裁剪,物理通道裁剪以及扩展通道裁剪
- 组裁剪: VPSS对输入图像进行裁剪
- 物理通道裁剪: VPSS对各物理通道输出的图像进行裁剪
- 扩展通道裁剪: VPSS调用VGS对扩展通道的输出图像进行裁剪
-
Sharpen 锐化: 对图像进行锐化处理
-
像素格式转换
支持输入输出图像的数据格式转换
- HI3516EV200 物理通道支持semi-planar422转semi-planar420/单分量, semi-planar420转单分量
-
Scale :对图像进行缩小和放大,物理通道垂直最大支持15倍缩小,最大支持16倍放大, 扩展通道垂直支持30倍缩小,最大支持16倍放大
-
Mirror/File Mirror:水平镜像 Flip上下翻转
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210417165656597.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NjEzMzE0,size_16,color_FFFFFF,t_70)
-
VI/VPASS的协作模式分成以下2种(模式切换由最开始加载ko文件的时候执行的load脚本控制,对应的sys模块参数vi_vpss_online(默认))
- VI/VPSS离线: VI的图像先写入到ddr,VPSS从DDR中载入VI采集的数据进行图形处理,是传统芯片的VI/VPSS的协作模式
- VI/VPSS在线模式:VI进行时序解析后加直接在芯片内部将数据传递到VPSS,中间无DDR写入的过程,在线模式因为不写数据到DDR,所以无法进行CoverEx,OverlayEx,Rotate,LDC等操作,需要在VPSS各通道写出后再进行Rotate/LDC等处理,而且有些功能只有离线下才能支持,比如DIS
- VI/VPSS的绑定就是在线模式
-
通过调用 SYS 模块的绑定接口
,可与 AVS/USER/VDEC/VI 和 VO/VENC/SVP 等模块
进行绑定,其中前者为 VPSS 的输入源,后者为 VPSS 的接收者。用户可通过 MPI 接
口对 GROUP 进行管理。每个 GROUP 仅可与一个输入源绑定。GROUP 的物理通道有
两种工作模式:AUTO 和 USER,两种模式间可动态切换。AUTO 模式下各通道仅可
与一个接收者绑定,主要用于预览和回放场景下做播放控制。USER 模式下各通道可
与多个接收者绑定。需要 特别注意 的是,USER 模式主要用于对同一通道图像进行多
路编码的场景,此模式下播放控制不生效,因此回放场景下不建议使用 USER 模式。
VPSS 只有工作在离线模式下才支持 AUTO 模式
-
group的值一般是数字,代表编号
-
VI的通道对接的是VPSS的group,VPSS的chn对应的是输出流,HI3516EV200的流
VENC 视屏编码
-
单分量:图片信息中只有Y没有UV,就是黑白图片
-
图像编码压缩基本原理 参考:http://blog.csdn.net/newchenxf/article/details/51693753
-
profile: 视屏清晰度从低到高分为 BP MP HP,不同硬件和编码格式支持不同清晰度。
-
MPP手册中图像编码部分解读 参考:http://blog.csdn.net/u013354805/article/details/51988171
-
VENC:
- 如果输入的图爿比VENC图像大,VEN会自动把输入图像缩小成和VENC 一样
- 如果输入图像比VENC小,VENC丢弃输入图像
- 如果输入图像和VENC尺寸相当,VENC会直接开始编码
- 码率控制器
- 码率控制实现对编码码率进行控制,在场景变化时,想要图像稳定编码率会波动。如果编码码率稳定,那么图像质量就会波动。
- 码率控制有CBR VBR FIXQP三种控制方式
- CBR:固定码率,当图像源发生变化时候,图像质量发生变化,由以下两个两控制码率(编码快,但是不灵活,适用于图像不怎么变化的场景)
- u32 StatTime:码率统计时间,时间越长每帧图爿对码率波动越小,码率调节变慢,图像质量质量波动更加轻微
- u32 RowQpDeltal: 行级码率调节控制幅度,值越大码率越平稳,值过大的话复杂度分布不均匀的图片可能会质量不均匀
- VBR: 可变码率,由MaxQp,MinQp,MaxBItrate,ChangPos控制,MaxQp和MinQP设定图像质量范围。MaxBItrate钳位码率统计时间内最大编码率。ChangPos控制开始调节Qp的码率基准线
- FixQp: 固定Qp值,码率统计时间内所有Qp值稳定不变,采用用户设定的Qp值。1帧和p帧的Qp值可以分别设定
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210418153725270.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NjEzMzE0,size_16,color_FFFFFF,t_70)
HI35XX典型系统层次图
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210414151202206.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NjEzMzE0,size_16,color_FFFFFF,t_70)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210414151321912.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM0NjEzMzE0,size_16,color_FFFFFF,t_70)
学习重点
- 学习重点1: 全局把控熟悉整个过程全景视图
- 学习重点2: 掌握细节数据结构元素含义,和遇到的概念
- 学习重点3: 知道某些关键操作在哪里定义,哪里设置,将来需要改的时候在哪里能够找到
绘制VI调用关系图谱SAMPLE_VENC_Ring()
step0
- SAMPLE_COMM_SYS_GetPicSize(enSize[i], &stSize[i]); 从预定义的enSize中获取一帧图片的像素点个数存放到stSize
- SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);给多路摄像头标号到stViconfig中,Makefile定义SENSOR0_TYPE放到第0路设备中
- SAMPLE_VENC_CheckSensor(stViConfig.astViInfo[0].stSnsInfo.enSnsType,stSize[i]);检查摄像头能够输出的像素是否小于上文给出的像素点
- SAMPLE_VENC_ModifyResolution(stViConfig.astViInfo[0].stSnsInfo.enSnsType,&enSize[i],&stSize[i]);重新设置照片类型和像素点大小
- SAMPLE_VENC_GetDefaultVpssAttr(stViConfig.astViInfo[0].stSnsInfo.enSnsType, abChnEnable, stSize, &stParam);初始化VPSS
- GetVpssWrapBufLine(&stParam); ```现在还不知道```
step 1: init sys alloc common vb
- SAMPLE_VENC_GetCommVbAttr(stViConfig.astViInfo[0].stSnsInfo.enSnsType, &stParam, HI_FALSE, &commVbAttr); 初始化射频缓冲池的的参数
- SAMPLE_VENC_SYS_Init(&commVbAttr); 设置视频缓冲池
SAMPLE_COMM_SYS_Init() 初始化视频缓存池
HI_MPI_SYS_Exit(); 去初始化 MPP 系统
HI_MPI_VB_Exit(); 去初始化 MPP 视频缓存池
HI_MPI_VB_SetConfig:设置 MPP 视频缓存池属性
HI_MPI_VB_Init();初始化 MPP 视频缓存池
HI_MPI_SYS_Init();初始化 MPP 系统
step 2: init and start vi
SAMPLE_VENC_VI_Init(&stViConfig, ViVpssMode);
SAMPLE_COMM_VI_SetParam(pstViConfig); 设置VI参数
HI_MPI_SYS_GetVIVPSSMode(&stVIVPSSMode); 获取VI/VPSS的参数
SAMPLE_COMM_VI_UpdateVIVPSSMode(&stVIVPSSMode); 更新参数
HI_MPI_SYS_SetVIVPSSMode(&stVIVPSSMode); 设置参数
SAMPLE_COMM_VI_GetFrameRateBySensor(enSnsType, &u32FrameRate);从摄像头类型获取FPS
HI_MPI_ISP_GetCtrlParam(pstViConfig->astViInfo[0].stPipeInfo.aPipe[0], &stIspCtrlParam); 获取ISP控制参数
ISP_CHECK_PIPE(ViPipe); 检查管道
ISP_CHECK_POINTER(pstIspCtrlParam);
ISP_CH ECK_OPEN(ViPipe);
ioctl(g_as32IspFd[ViPipe], ISP_GET_CTRL_PARAM, pstIspCtrlParam);
HI_MPI_ISP_SetCtrlParam(pstViConfig->astViInfo[0].stPipeInfo.aPipe[0], &stIspCtrlParam); 设置ISP
ISP_CHECK_PIPE(ViPipe);
ISP_CHECK_POINTER(pstIspCtrlParam);
ISP_CHECK_OPEN(ViPipe);
return ioctl(g_as32IspFd[ViPipe], ISP_GET_CTRL_PARAM, pstIspCtrlParam); 把参数写入到ISP中
SAMPLE_COMM_VI_StartVi(pstViConfig); 启动VI
SAMPLE_COMM_VI_StartMIPI(pstViConfig);
SAMPLE_COMM_VI_SetParam(pstViConfig);
SAMPLE_COMM_VI_CreateVi(pstViConfig);
SAMPLE_COMM_VI_CreateIsp(pstViConfig);
SAMPLE_COMM_VI_DestroyVi(pstViConfig);
SAMPLE_COMM_SYS_Exit();
SAMPLE_COMM_VO_Exit();
HI_MPI_SYS_Exit();
HI_MPI_VB_ExitModCommPool(VB_UID_VDEC);
HI_MPI_VB_Exit();
step 2: init and start vi
SAMPLE_VENC_VPSS_Init(VpssGrp, &stParam);
SAMPLE_VENC_VPSS_CreateGrp(VpssGrp, pstParam); 创建用户组
SAMPLE_COMM_VI_GetSizeBySensor(pParam->enSnsType, &enSnsSize); 从摄像头类型获照片类型
SAMPLE_COMM_SYS_GetPicSize(enSnsSize, &stSnsSize);· 获取照片大小
HI_MPI_VPSS_CreateGrp(VpssGrp, &stVpssGrpAttr); 创建用户组
SAMPLE_VENC_VPSS_StartGrp(VpssGrp); 开启用户组
HI_MPI_VPSS_StartGrp(VpssGrp);
SAMPLE_VENC_VPSS_ChnDisable(VpssGrp, i)
SAMPLE_VENC_VPSS_DestoryGrp(VpssGrp);
step 4: Bind VI and VPSS
SAMPLE_COMM_VI_Bind_VPSS(VI_PIPE ViPipe, VI_CHN ViChn, VPSS_GRP VpssGrp) 输入管道和输入通道绑定到用户组
CHECK_RET(HI_MPI_SYS_Bind(&stSrcChn, &stDestChn), "HI_MPI_SYS_Bind(VI-VPSS)");绑定输入通道和VPSS
step 5: start VENC (0: H265 BigStream; 1: JPEG snap with BigStream; 2: H264 SmallStream)
SAMPLE_VENC_GetRcMode();
SAMPLE_RC_CBR() 用户输入帧率控制模式
SAMPLE_VENC_GetGopMode(); 用户选择用group模式,P B I 帧不同
SAMPLE_COMM_VENC_GetGopAttr(enGopMode,&stGopAttr); 从group得到 P B I 的参数
SAMPLE_COMM_VENC_Start() 创建H.265通道
SAMPLE_COMM_VENC_Creat()
SAMPLE_COMM_SYS_GetPicSize()
SAMPLE_COMM_VI_GetSensorInfo(&stViConfig);
SAMPLE_COMM_VI_GetFrameRateBySensor()
HI_MPI_VENC_CreateChn()
SAMPLE_COMM_VENC_CloseReEncode(VencChn);
HI_MPI_VENC_GetChnAttr(VencChn,&stChnAttr);
HI_MPI_VENC_GetRcParam(VencChn,&stRcParam);
HI_MPI_VENC_SetRcParam(VencChn,&stRcParam);
HI_MPI_VENC_StartRecvFrame(VencChn,&stRecvParam); 启动VENC通道
SAMPLE_COMM_VENC_SnapStart(VencChn[1], &stSize[1], bSupportDcf);JPEG 通道
SAMPLE_COMM_VENC_Start()创建H.264VENC通道
SAMPLE_COMM_VPSS_Bind_VENC() 绑定VPSS和VENC
step 7: start get video stream (this thread just Get video channel stream(venc chan[0] and chan[2]))
SAMPLE_COMM_VENC_StartGetStream(VideoChn, 2);
pthread_create(&gs_VencPid, 0, SAMPLE_COMM_VENC_GetVencStreamProc, (HI_VOID*)&gs_stPara);创建线程把保存数据流
HI_MPI_VENC_GetChnAttr(VencChn, &stVencChnAttr); 获取VENC通道属性
SAMPLE_COMM_VENC_GetFilePostfix(enPayLoadType[i], szFilePostfix); 获取后缀名
fopen(aszFileName[i], "wb"); 创建文件保存VENC流数据
HI_MPI_VENC_GetFd(VencChn);从MPP中获取VENC通道文件描述符
HI_MPI_VENC_GetStreamBufInfo()获取码流 buffer 的物理地址和大小。
HI_MPI_VENC_QueryStatus(VencChn, &stStat);查询通道状态
HI_MPI_VENC_GetStream(VencChn, &stStream, -1); 从通道ID获取视屏流
SAMPLE_COMM_VENC_SaveStream(pFile, &stStream);保存视屏流到指定文件
SAMPLE_COMM_VENC_Getdcfinfo(char* SrcJpgPath, char* DstThmPath)从保存的视屏文件保存JPEG文件
HI_MPI_VENC_ReleaseStream(VencChn, &stStream);释放编码通道
HI_MPI_VENC_StopRecvFrame(VencChn);停止接受视屏流
step 8: snap picture process
SAMPLE_COMM_VENC_SnapProcess(VencChn[1], 1, HI_TRUE, HI_FALSE);
SAMPLE_COMM_VENC_StopGetStream();
SAMPLE_COMM_VPSS_UnBind_VENC(VpssGrp,VpssChn[1],VencChn[2]);
SAMPLE_COMM_VENC_Stop(VencChn[2]);
SAMPLE_COMM_VI_UnBind_VPSS(ViPipe,ViChn,VpssGrp);
SAMPLE_COMM_VPSS_Stop(VpssGrp,abChnEnable);
SAMPLE_COMM_VI_StopVi(&stViConfig);
SAMPLE_COMM_SYS_Exit();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)