hisi芯片系统概述
首先先来了解一下海思芯片SOC,下图是hi3519A芯片设计图
图1 hi3519AV100 芯片设计图
芯片的设计图有助于我们对海思的图像处理有一个大致的了解,从上图中我们可以看到,芯片SOC里集成了众多控制芯片,比如负责深度学习的NNIE硬核,负责图像处理的IVE硬核,视频编解码单元H265/H264Codec,以及图像处理单元ISP等。
为了减少用户对于硬件的直接操作,海思为用户封装了许多对于硬件的操作接口,能够控制芯片完成相应的媒体处理功能,对上屏蔽了硬件的处理细节,用户能够将精力集中在业务功能上,达到快速开发的目的。这些相关硬件接口就构成了下图中的媒体软件处理平台层。我们进行视频图像的处理主要是要调用该层提供的相关接口来完成相应的功能,也必须要按照它提供的操作流程来执行相关功能的完成,所以需要熟悉它提供的相关接口的使用方法和使用限制,开发手册中提供了系统的处理流程以及具体的API描述,仔细阅读该文档能帮助我们更好地完成开发工作。
图2 海思35xx 系统层次图
海思媒体软件处理平台概述
海思媒体处理平台的主要内部处理流程如图3所示,主要分为 VI-视频输入,VPSS-视频处理,VENC-视频编码,VDEC-视频解码,VO-视频输出,AVS-视频拼接等模块
图 3 mpp 内部处理流程图
从上图可以看出,可以根据用户需求完成多种方案实现,比如视频输出,视频监控等方案。有的功能单个模块就能完成,而更多的功能则需要依赖模块之间“联动”完成。各个模块之间的关系,比如,第一条pipeline是:sensor -> VI -> VPSS -> VENC -> 压缩码流 或者 sensor -> VI -> VPSS -> VO -> 显示屏,这应该是单目相机上常用的pipeline。第二条pipeline是:存储介质 -> VDEC -> VPSS -> VENC ->压缩码流 或者 存储介质 -> VDEC -> VPSS -> VO -> 显示屏,这个应该是在智能盒子上做视频文件相关应用常见的pipeline。至于第三条pipeline:sensors -> VI -> VPSS -> AVS ->VENC -> 压缩码流,这个是多目相机、拼接码流常见的pipeline。最后一组则是音频的单独应用,音频编解码。
海思媒体处理芯片内部几个重要的硬件模块的主要功能描述如下:
VI:捕获视频图像,可做剪切,去噪等处理,并输出多路不同分辨率的图像数据,主要是bayer图像数据(可认为是对应芯片图中的Image Subsystem)
VPSS: 接收其他模块发送的图像数据,可对图像进行图像增强、锐化等处理,并同源输出多路不同分辨率的图像数据
VENC:编码模块负责接收其他模块处理输出的数据,可叠加用户通过Region模块设置的OSD图像,然后输出不同协议编码的码流数据(可做视频OSD叠加)
下面分别从系统控制,以及VI,VPSS,VENC这三个模块进行介绍。
系统控制
主要是需要完成系统硬件的复位,基本的初始化,MPP系统业务模块的初始化等
hisi芯片的内存管理机制
hisi35系列芯片将内存划分为OS内存和MMZ(Media Memory Zone)内存,而且用户可以通过load脚本继续划分MMZ内存以供某功能某块单独使用。
OS内存:是指由操作系统管理的内存,MMZ内存是指由MMZ驱动模块进行管理供媒体业务单独使用的内存,在驱动加载时可以指定该模块管理内存的大小。
MMZ全称Media Memory Zone:中文名“多媒体内存区域”,海思整套系统(MPPNNIEIVE等)都是基于其专有内存进行数据传输、存储的。OS内存可以用free命令查看,而MMZ则使用cat /proc/media-mem可以查看到系统总共、已使用的、剩余的MMZ,包括每一块已经使用的MMZ的使用情况。
图 4 MMZ内存实例
图4中的flags表示什么,不是很清楚,有知道的可以告知一声(kvirt是否表示虚拟地址?)。
图 5 kernel 内存分布
另外,kernel的内存分布中,有一块vmalloc区域,大小申请了496M,对应的虚拟地址为:0xe0800000-0xff800000,从上面MMZ内存的虚拟地址来看,有很多块内存的虚拟地址落在了vmalloc申请的地址段,所以猜测这块内存应该是用来load内核ko文件的,而且映射的应该是MMZ的内存,另外发现有name为vb的内存也虚拟地址也在vmalloc,这是海思在load MMZ ko驱动的时候就分配好的VB内存么?
有关于MMZ内存的具体实现可以参考一下这篇MMZ内存驱动
VB:video buffer
VB在海思媒体处理中也是一个重要的概念,VB的本质上就是一个物理地址连续的MMZ内存块,只不过在MPP层里提供了一系列初始化,申请,释放操作的接口,所以VB其实也属于MMZ内存。
一组大小相同,物理地址连续的缓存块(VB)组成一个视频缓存池(VB POOL)。这个视频缓存池的作用就是给MPP提供大块物理内存管理功能,负责内存的分配和回收。因为VB的使用者主要是海思的硬件模块,比如vi/vpss/venc等等, 需要连续的物理地址, 有点类似早期的linux为硬件DMA分配内存也要求物理地址连续。
海思文档提供了一张公共VB缓存池的数据流图。公共缓冲池是在系统初始化中分配的,具体分配的接口就是HI_MPI_VB_SetConf()和HI_MPI_VB_Init()。我们可以通过这两个接口按照所需VB数量和VB大小不同的缓冲池,比如下图,A和B都是缓存池,缓存池内的每个缓存块的大小都一致,而A1和B1的缓存块大小一般不一样。这里假设A缓存池里的缓存块大小为100k,B中的缓存块大小为200k,而海思模块使用VB的原则是选择满足要求的最小的VB,就是当海思模块要用一个90k的VB时,会优先从100k的那个vb pool中去申请,有就用,没有就去200k那个vb pool中申请,再没有就会报vb fail的错误。
公共缓存池中的VB使用者是VI/VPSS/VENC/VDA/VO,而且以VI为主要的使用者,文档中也说所有的视频输入通道都可以从公共视频缓存池中获取视频缓存块用于保存采集的图像。
图 6 公共VB缓冲池数据流图
除了通过HI_MPI_VB_Init建立的公共视频缓存池,用户也可以调用接口HI_MPI_VB_CreatePool创建一个视频缓存VB池。然后配合某模块通道的xxx_attachPool(VPSS,VENC,VDEC有该接口)绑定到某个通道上,那么就只有该通道可以使用,比如HI_MPI_VENC_AttachVbPool被VENC的0通道绑定之后,就只有VENC CHN 0可以使用该VB。
结构体VB_SOURCE_E定义了VB的来源选择。这个枚举类型一般只用在编、解码器中,详细可以参考海思文档
typedef enum hiVB_SOURCE_E{ VB_SOURCE_COMMON = 0, VB_SOURCE_MODULE = 1, VB_SOURCE_PRIVATE = 2, VB_SOURCE_USER = 3, VB_SOURCE_BUTT} VB_SOURCE_E;
其中,在编码器中,编码帧存(参考帧和重构帧)分配支持两种方式:PrivateVB池和UserVB池方式
PrivateVB:创建编码通道时有VENC创建PrivateVB池作为该通道的参考帧和重构帧buffer, 这种模式下不需要用户进行相关操作,只需要修改hi35xx_h164e.ko模块参数 enH264eVBSource的VB类型为:VB_SOURCE_PRIVATE,由内存完成帧存分配
使用privateVB的好处就是,各个通道之间是独立的,互不影响,单独销毁某个通道上的图像对其他通道无影响,使用灵活方便。
UserVB: 创建编码通道的时候不创建编码帧vb池,而是需要用户调用HI_MPI_VB_CreatePool手动创建,再调用HI_MPI_VENC_AttachVbPool把某个编码通道绑定到固定的vb池中。修改hi35xx_h164e.ko模块参数 enH264eVBSource的VB类型为:VB_SOURCE_USER。
UserVB的好处就是手动把n个通道绑定到VB池中,这样对于多个相同分辨率的编码通道,使用UserVB方式可以减少内存小号。
ModuleVB池:创建解码通道时不分配解码帧的buffer,而是由用户调用HI_MPI_VB_CreateVBPool接口创建专属于解码模块的ModuleVB池,该VB池只允许VDEC获取VB块。
解码模块同样有UserVB和PrivateVB。解码模块这三种解码帧存类型的分配可以通过接口HI_MPI_VDEC_SetModParam的参数恩enVdecVBSource来设置.
MMZ内存使用
使用MMZ有2个地方需要注意:地址(虚拟地址vs物理地址)和缓存(可缓存vs不可缓存)
地址(虚拟地址vs物理地址)
海思内部模块基本上都是直接操作物理地址,海思提供了虚拟地址和物理地址之间互相映射的API,为我们在用户态下操作物理内存提供了方式。实际使用时还需要注意以下事项:
物理地址:实际拿到的海思地址,在海思中只有一些模块能够直接访问物理地址(CPU不能访问),一般用于硬件加速、不同进程间地址交换;
虚拟地址:在本程序的地址页表上的地址,就如同OS MEM一样使用即可,CPU可以直接访问,也就是说在进程内可以直接读写该地址。如果要在不同进程间交换,需要考虑使用共享内存等机制。
缓存(可缓存vs不可缓存)
这里的“缓存”是指,MMZ的虚拟地址会被CPU的寄存器缓存。
可缓存:MMZ虚拟地址会被CPU的寄存器同步保存一份,以做缓存命中,因此可缓存的MMZ会极大提高程序的读写性能;但是一定记住在外部模块需要读写该MMZ之前要调用flush接口做同步。调用HI_MPI_SYS_MmzAlloc_Cached申请可cache的MMZ虚拟地址
不可缓存:不会被CPU的寄存器保存,也就是每次CPU读写该MMZ时都必然是和内存做读写,可以想见性能必然不高;但是这样的好处是编程人员不需要考虑一致性问题,不需要做flush。调用HI_MPI_SYS_MmzAlloc申请不可cache的MMZ虚拟地址
还有一点必须记住,程序必须及时调用HI_MPI_SYS_MmzFree
释放掉不用的MMZ,海思系统并不会帮助回收程序申请的MMZ内存。
实际中,设计底层硬件比如VDEC、VENC、VPSS都只能操作VB内存,不能直接操作MMZ。
VI模块
VI模块划分了4个部分:DEV–>PIPE–>PHY_CHN|EXT_CHN
图7 VI模块结构
各个芯片的设备数量
芯片 | DEV | PIPE | PHY_CHN | EXT_CHN |
Hi3559AV100ES | 6 | 6 | 2 | 8 |
Hi3559AV100 | 8 | 8 | 1 | 8 |
Hi3519AV100 | 5 | 6 | 2 | 8 |
输入设备DEV负责对时序进行解析。PIPE绑定在DEV后方,包含了ISP的相关处理功能,主要是对图像数据进行流水线处理,输出YUV图像个通道。PIPE主要包含了PIPE_FE和PIPE_BE,PIPE_FE主要负责从DEV接收BAYER格式的图像数据,PIPE_BE主要负责执行图像处理ISP,执行完ISP后输出YUV图像。PHY_CHN物理通道负责将处理后的数据输出到DDR,通道包含了剪裁,缩减等功能(不同型号不同)。
DEV和MIPI的绑定关系以及PIPE和DEV的绑定关系详细描述可以参考开发手册,开发手册里有详细规定,这里不过多展开描述。
这里强调一下,DEV设备和MIPI设备绑定后不可动态更改,Hi3559和3519的DEV和MIPI的绑定关系是固定的,基本是一一对应的关系。DEV和时序输入接口(MIPI,SLVS,BT.1120等)的绑定有约束关系,该约束关系在文档中有描述,具体要根据硬件实际管脚连接来确定使用了哪一个DEV。
PIPE可以和任意的DEV绑定,一个DEV可以绑定多个PIPE(用于WDR模式),线性模式下一个DEV绑定一个PIPE。每一个PIPE对应着一个或2个的PHY_CHN(物理通道),物理通道具有裁剪功能,且输出图像格式为YUV,基本可以认为PHY_CHN和PIPE是一体的。
可通过cat /proc/umap/vi查看vi的相关属性配置
图 8 DEV和Bind PIPE属性
图 9 物理通道属性
图 10 VI设备里的各个模块的绑定关系
sensor的从模式
从模式sensor,我觉得是sensor的管脚连接到了SENSOR_HSx/SENSOR_VSx,x根据不同芯片有不同取值,3559A芯片x取值为0-3,从模式sensor需要使用vi的从模式模块,且从模式模块与vi的PIPE对应关系是固定的,要确定需要使用的PIPE(只有特定的PIPE才有数据),首先需要根据硬件图确定sensor连接到哪个SENSOR_HSx/SENSOR_VSx,然后查阅文档可以确定这个sensor对应的从模式模块以及该从模式模块对应的PIPEID,使用时创建并打开该PIPE,就可以从该PIPE中获取到图像数据。
VPSS模块
VPSS-视频处理子系统,可以完成一系列的视频处理功能包括,FRC帧率控制,CROP剪裁,3DNR3D降噪,像素格式转换,旋转,马赛克等。
最新评论