Cambricon CE3226 媒体处理系统(三):视频输出

随着 AI 技术的不断发展,从 Sensor 采集数据,经过处理之后给 AI 模型做图像分析已经变成一个很典型的应用。因此,在嵌入式应用行业,无论是汽车,安防,手机等应用中,对 Sensor 采集的数据做图像处理变得非常重要。针对以上需求,Cambricon CE3226 内部集成了多个复杂的硬件组件,并实现了对应的中间层软件库,能够满足客户对视频处理的各种要求。

本系列博文会对 CNMPS(Cambricon Media Process System,寒武纪媒体处理系统)各个组件功能,工作原理作详细介绍,并对中间层软件作系统分析,方便客户编写自己的应用程序。
本文是该系列博文的第三篇,介绍视频输出系统的组成,工作原理以及软件架构。

一、基本概念

  VO(Video Output,视频输出)模块从内存读取视频数据和图形数据进行叠加,并进行图像后处理,最

终通过相应的显示设备输出。CE3226V100 支持的显示/回写设备、视频层、图形层情况参见图(1)。

图(1)

  • DHD0(Device High Definition 0):HD0 设备,高清显示设备 0。
  • VHD0(Video layer of HD 0):高清视频层 0,属于 DHD0。
  • VHD1:高清视频层 1,属于 DHD0。
  • WD(Write Back Device):回写设备。

 

  • 高清显示设备

CE3226V100 支持 1 个高清显示设备 DHD0 。支持显示设备的详细情况请参见 CE3226V100 支持的显

示 / 回写设备、视频层、图形层 。HD 设备功能属性参见 CE3226V100 设备规格 。设备的视频输出接口

只支持逐行扫描,不支持隔行扫描,设备支持的最大输出时序参见 CE3226V100 视频输出接口时序 。

  • 回写设备

对设备级的视频数据进行捕获,可用于显示和编码。回写设备和显示设备不可同时使用。回写设备只

可以回写设备级,即视频层与图形层进行叠加后的视频数据。

  • 虚拟设备

虚拟设备是软件上的概念,没有与之对应的实际物理设备。

– 内部处理流程:虚拟设备通过 VGU 实现缩放,并将多个视频图像拼接为一整幅图像。

– 发送虚拟设备图像:虚拟设备支持通过用户态调 cnvoGetScreenFrame 接口获取虚拟设备对应视频

层的图像,再发送给其他模块;也支持系统绑定模式下在内核态向其他模块发送虚拟设备图像。

CE3226V100 支持 2 个虚拟设备,设备号为 1~2,对应的虚拟视频层为 2~3 ,虚拟视频层 2 最多支持

16 个通道,虚拟视频层 3 最多支持 4 个通道。

  • 视频层

表示固定在显示设备上的视频层。CE3226 的视频层功能规格请参见 CE3226V100 视频层规格 。

  • 通道

通道是指一个视频的显示区域,通道由视频层进行管理,一个视频层上可包含单个或多个通道,视频

区域必须在通道区域内,通道区域必须在视频层内。通道与通道之间都是独立的,每一个视频层上的

通道的单独进行排号。

使用系统绑定方案时,应该使用视频层号和通道号来进行绑定配置。

  • 通道优先级

高清显示设备支持视频层上多个通道同时输出显示,叠加顺序按照优先级进行排序,当各个通道重叠

时,通道优先级高的显示在上层,如果通道优先级相等,则通道号越大的默认优先级越高。

  • 缩放和显示

对于 CE3226V100 VHD0 最大支持 16 个通道,VHD1 最大支持 4 个通道。通道支持通过 VGU 对图像进

行缩放,再将多个通道的视频图像拼接为一整幅图像,并将这一整幅图像的数据送给设备显示。可支

持的缩放和显示情况参见 CE3226V100 视频层规格 。

视频层不支持缩放,允许对视频层进行裁剪。视频层在显示视频图像时均不进行缩放,只支持裁剪显

示。

  • 旋转

VO 支持对通道的图像进行旋转操作。旋转功能只支持非压缩数据格式。

  • 单画面直通模式

此模式下,VO 通道中的图像可直接显示,不需要 VGU 模块进行缩放和拼接处理,节省一次 VGU 搬移

数据过程,VO 也无需申请私有内存,直通模式需要满足以下条件:

– VO 通道使能,且只有一个通道显示;

– VO 没有使能边框;

– VO 通道图像像素格式和设置的一致;

– VO 通道图像视频格式为 LINEAR;

– VO 通道图像大小(stVFrame.Size)= 通道大小(stRect)= 画布大小(stImageSize);

  • 图形层绑定

CE3226V100 支持 2 个图形层 G0 和 G1、G0 以及 G1 固定绑定在 DHD0 上。

  • 解压和压缩

– 视频数据解压。

CE3226V100 支持输入源图像是压缩数据(格式为段压缩,256Bytes 为一段)。视频层、通道均支

持解压功能,通道使用解压功能时不支持旋转功能。非单通道直通模式,不支持解压功能。

– 视频数据压缩。

CE3226V100 回写设备支持输出压缩数据图像(格式为段压缩,256Bytes 为一段)。

  • 输入和输出数据格式

VO 支持输入和输出指定格式的数据,这里的输出是指回写数据到 DDR 。可支持的输入输出数据格

式参见 CE3226V100 支持的输入输出数据格式 。其中 PIXEL FORMAT、VIDEO FORMAT、COMPRESS

MODE 和 DYNAMIC RANGE 项分别列出了芯片支持的输入输出像素格式、视频格式、压缩模式和视频

动态范围。

  • 像素格式转换

VO 工作于非直通模式时支持像素格式转换,如果输入通道的图像像素格式和视频层设置的像素格式

不同,可通过 VGU 进行像素格式转换。

  • 分辨率

分辨率主要有以下 4 种概念:

– 设备分辨率指显示设备的输出有效像素点数,由设备输出时序决定。

– 显示分辨率指视频层画面在设备上的有效区域,由视频层属性中的 stDispRect 成员决定。

– 画布分辨率指一块用来存放 VGU 拼接后输出视频数据的内存区域,由视频层属性中的 stImageSize

决定。单画面直通时无此定义。

– 图像分辨率指图像的有效像素点数,由实际的图像决定。

  • 低功耗策略

VO 模块使用低功耗策略,在模块加载后或用例退出后,VO 时钟是关闭的,此时手动读写 VO 模块的

寄存器可能导致读写错误或系统卡死。

 

二、软硬件限制

图(2)表示不同的输出接口的规格
图(2)

 
图(3)表示输出接口最大分辨率和帧率
图(3)

 

图(4)表示视频层规格
图(4)

三、API & 关键代码

1.驱动交互 API

如图(5),/mps/out/include/cn_vo.h 头文件中分别针对 Layer、channel 导出了 api 函数,具体实现封装在/mps/out/lib/libcn_vi.so 动态库文件中。这些 API函数直接与驱动程序交互。

涉及的数据类型在 /mps/out/include/cn_common_vo.h 中。
图(5)

针对 VO 设备,实现了如下 API 函数

cnS32_t cnvoSetPubAttr(cnS32_t s32Dev, const cnvoPubAttr_t *pstPubAttr);//设置 VO 属性

cnS32_t cnvoGetPubAttr(cnS32_t s32Dev, cnvoPubAttr_t *pstPubAttr);//获取 VO 属性

 

cnS32_t cnvoEnable (cnS32_t s32Dev);//启动 VO

cnS32_t cnvoDisable(cnS32_t s32Dev);//关闭 VO

 

针对 layer,实现了以下主要 API 函数

cnS32_t cnvoSetVideoLayerAttr(cnS32_t s32Layer, const cnvoVideoLayerAttr_t *pstLayerAttr);//设置 layer 属性

cnS32_t cnvoSetVideoLayerPriority(cnS32_t s32Layer, cnU32_t u32Priority);//设置视频层优先级

cnS32_t cnvoSetVideoLayerBoundary(cnS32_t s32Layer, const cnvoLayerBoundary_t *pstLayerBoundary);//设置视频层区域边框的宽高和颜色

                                                               

通道相关的 API 如下:

cnS32_t cnvoSetChnAttr(cnS32_t s32Layer, cnS32_t s32Chn, const cnvoChnAttr_t *pstChnAttr); //设置 VO 通道属性

cnS32_t cnvoEnableChn (cnS32_t s32Layer, cnS32_t s32Chn);//启动视频输出通道

 

cnS32_t cnvoSendFrame(cnS32_t s32Layer, cnS32_t s32Chn, cnVideoFrameInfo_t *pstVFrame, cnS32_t s32MilliSec);  //将视频图像送入指定的输出通道

 

cnS32_t cnvoGetChnFrame(cnS32_t s32Layer, cnS32_t s32Chn, cnVideoFrameInfo_t *pstVFrame, cnS32_t s32MilliSec);  //获取显示帧率

cnS32_t cnvoReleaseChnFrame(cnS32_t s32Layer, cnS32_t s32Chn, const cnVideoFrameInfo_t *pstVFrame);//释放输出通道图像数据

cnS32_t cnvoSetChnFrameRate(cnS32_t s32Layer, cnS32_t s32Chn, cnS32_t s32ChnFrmRate); //设置通道帧率

cnS32_t cnvoShowChn(cnS32_t s32Layer, cnS32_t s32Chn); //显示视频输出通道的图像

cnS32_t cnvoHideChn(cnS32_t s32Layer, cnS32_t s32Chn); //隐藏视频输出通道的图像

 

cnS32_t cnvoSetChnRotation(cnS32_t s32Layer, cnS32_t s32Chn, cnEnRotation_t enRotation);//设置旋转

 

2.用户 API

为了方便客户应用开发,MPS 在以上 API 基础上,继续封装了一层 API,供开发人员间接对 VO 模块进行设置、初始化、启动等操作。相关函数通过 /mps/sample/common/cnsample_comm.h 导出。具体函数实现在/mps/sample/common/cnsample_comm_vo.cpp 文件中实现。

cnsample_comm_vo.cpp 中实现了2 个类似的函数供用户 APP 直接使用,分别是 cnsampleCommVoStartVo()和 cnsampleCommVoStartLayerChn()。下面分别介绍这两个函数。

 

2.1

cnsampleCommVoStartVo()函数调用层级如下:

    |--cnsampleCommVoStartVo(cnsampleVoConfig_t *pstVoConfig)

        |--cnsampleCommVoStartDev(voDev_t VoDev, cnvoPubAttr_t *pstPubAttr)

            |--cnvoSetPubAttr(cnS32_t s32Dev, const cnvoPubAttr_t *pstPubAttr)

            |--cnvoEnable (cnS32_t s32Dev)

        |--cnsampleCommVoGetWH(cnvoEnIntfSync_t enIntfSync, cnU32_t* pu32W, …)

        |--cnvoSetDisplayBufLen(cnS32_t s32Layer, cnU32_t u32BufLen)

        |--cnsampleCommVoStartLayer(voLayer_t VoLayer, const cnvoVideoLayerAttr_t* pstLayerAttr)

            |--cnvoSetVideoLayerAttr(cnS32_t s32Layer, const cnvoVideoLayerAttr_t *pstLayerAttr)

            |--cnvoEnableVideoLayer (cnS32_t s32Layer)

        |--cnsampleCommVoStartChn(voLayer_t VoLayer, cnsampleVoMode_t enMode)

            |--cnvoGetVideoLayerAttr(cnS32_t s32Layer, cnvoVideoLayerAttr_t *pstLayerAttr)

            |--cnvoSetChnAttr(cnS32_t s32Layer, cnS32_t s32Chn, const cnvoChnAttr_t *pstChnAttr)

            |--cnvoEnableChn (cnS32_t s32Layer, cnS32_t s32Chn)

 

cnsampleCommVoStartVo()函数具体分析如下,图(6)、图(7)为其函数体:

图(6)

图(7)

cnsampleCommVoStartVo()函数体首先定义一系列设置 VO,Layer,channel 的参数变量,首先根据输入参数

pstvoconfig 结构体指针中的成员值去填充 VO 的属性,然后调用 cnsampleCommVoStartDev() 启动 VO 设备。

VO 启动之后,调用 cnsampleCommVoGetWH()获取 VO 设备的宽度、高度、帧率。填充 Layer 属性后启动 Layer

设备。最后调用 cnsampleCommVoStartChn()启动 channel。启动的 channel 显示窗口根据图(8)所示的算法确定位置。
图(8)

其中 s32x,s32y 为 x,y轴起点位置,u32Width,u32Height 为宽度和高度。i为窗口个数。

宏ALIGN_DOWN(addr, size)  ((addr)&(~((size)-1))) 用于计算上述四个参数,并作偶数(行数和列数)对齐。

下图(9)所示为窗口个数为 2、4、8、9 的情况下显示布局。

 
图(9)

 

2.2 cnsampleCommVoStartLayerChn()函数与 cnsampleCommVoStartVo()类似,不同之处在于不启动 VO 设备,

一般用于在 VO 设备启动后改变 Layer 和 channel 的属性参数。

  

参考资料:

    寒武纪媒体处理系统开发者手册-CN-v0.8.0.pdf

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论