在移动互联网以及4K高清视频概念的热潮推动下,人们盼望着不仅能降低网络带宽、也能保持高清晰度的新技术革新。H265视频编码标准就是在这样的背景下进入人们的视野,相比较上一代H264编码标准,H265在改善码流、编码质量、低延时、编码算法方面下足了功夫,在码率控制方面的能力比H264提升30%~40%,也就是说在相同的带宽下,视频质量要提高30%~40%,这在移动互联网直播技术的应用中具有天然的优势。《中国互联网发展报告2017年度总结》中指出,截止2017年12月,我国手机网民规模达7.53亿,较2016年增加5734万人。网民中使用手机上网的占比由2016年的95.1%提升至97.5%。毫不夸张的说,过去的20年是基于传统PC固定互联网的世界,未来的20年将是基于移动终端(手机、平板)的移动互联网世界,具非官方统计,如今人们每天在手机上花费的时间达到4个小时,其中有1/3的时间是花在网络视频直播上,可见对于H265技术的理解与掌握迫在眉睫。好在我国的华为公司在H265技术上拥有最多的核心专利,是该技术主导者,本文讲述如何在华为海思HI35xx平台上实现H265解码样例。
H265能够如此高效编码,在于它采用了更为复杂的帧内预测编码技术,对于H264,在给定帧,帧内预测在4X4宏块上有9种模式,在8X8和16X16上则只有4种模式,而对于H265,帧内预测方式则多达35种,它的复杂度虽然提升了部分计算资源的占用,却也提高了编码压缩效率。H265还在帧间预测方面优化了算法,它使用更为高效和复杂的层级结构系统代替了H.264的宏块结构,在分割帧中使用四叉树编码结构,也叫编码树单元(CTU,coding tree unit),这就能使H265编码时能对色域或者亮度变化明显的地方精细编码,对场景变化相对较小的地方大块编码从而使得编码效率的进一步提升。
H265的NAL,与H264不同的是,它采用了2个字节的结构,从而能提供更多更详细的信息。我们着重关注Type字段,它是解析H265数据帧的依据,在上层应用中,在RTSP传输过来的视频流时通过对H265的NALU进行解析,即可获取视频的一些参数信息,如帧率、分辨率等,进而配置解码器即可实现解码。在实际的H265数据帧中,往往在帧前面带有00 00 00 01 或 00 00 01分隔符,来标识一帧的起始位置。以00 00 00 01分割之后的下一个字节就是NALU类型,和H264的&0x1f来判断NALU类型不同的是,它采用如下方式:
int type = (code & 0x7E)>>1;
//type的值代表NALU的类型
00 00 00 01 40 01 的nuh_unit_type的值为 32, 语义为视频参数集 VPS
00 00 00 01 42 01 的nuh_unit_type的值为 33, 语义为序列参数集 SPS
00 00 00 01 44 01 的nuh_unit_type的值为 34, 语义为图像参数集 PPS
00 00 00 01 4E 01 的nuh_unit_type的值为 39, 语义为补充增强信息 SEI
00 00 00 01 26 01 的nuh_unit_type的值为 19, 语义为可能有RADL图像的IDR图像的SS编码数据 IDR
00 00 00 01 02 01 的nuh_unit_type的值为1, 语义为被参考的后置图像,且非TSA、非STSA的SS编码数据
我们了解一下海思HIMPP平台解码的概念,HIMPP平台音视频编解码架构遵循下图所示的数据处理流程。H265解码实例走的是HARD DISK->VDEC->VPSS->VO->显示器的流程,这个流程一定要熟悉牢记,代码实现都是围绕这条主线来编写的。
实例源码很简单,先来了解一下实现H.265解码实例的几个函数,以达到了解实例源码大概构造组成,然后再对每个函数进行具体分析。
/*
**函数描述:linux标准信号捕捉函数
**函数功用:接收Ctrl+C信号,用来退出程序,并销毁HIMPP调用
*/
HI_VOID SAMPLE_VDEC_HandleSig(HI_S32 signo)
{
......
}
/*
**函数描述:用于音视频文件读写推流
**函数功用:用fread等文件操作函数读取音视频文件,并解析后推送HIMPP进行解码
*/
int SAMPLE_COMM_VDEC_H265_SendStream( VdecThreadParam *pArgs)
{
......
}
/*
**函数描述:HIMPP系统初始化
**函数功用:配置HIMPP系统的各项参数以满足对目标进行编解码
*/
HI_S32 HI_S32 SAMPLE_VDEC_VdhH265(char *filename)
{
......
}
/*
**主函数
*/
int main(int argc, char *argv[])
{
......
}
在H265解码实例中使用了海思提供的API,故在编译的时候必须包含其相关的库及头文件,然后就可以利用API实现我们的上层业务逻辑。H.265视频解码实例走的是HARDDISK->VDEC->VPSS->VO->显示器的处理流程,这个过程可以细分为八大步骤,这八大步骤在其他类型的音视频编解码样例也类似,可以说这八大步骤是使用海思HIMPP API的关键所在。下面简单介绍这个八大步骤的内容:
Step1:初始化HIMPP SYS和通用VB缓冲,包括设置缓冲区的大小,缓冲区块的数目。需要注意的是,在设置通用VB参数之前,必须确保HIMPP系统已经退出,否则设置失败。
Step2:设置通用缓冲区的公共缓冲池属性。
Step3:配置解码器,包括指定解码类型,这里选PT_H265,然后指定视频大小、解码优先级等等。然后创建解码通道,并是能加收解码流。
Step4:配置VPSS参数,VPSS是对VDEC解码后的流进行处理,如裁剪、降噪等,MPEG解码实例从简单应用出发,仅仅按默认的方式配置VPSS。
Step5:配置VO参数,这一步也很关键,因为它指定了画面输出,包括常见的HDMI和VGA,主要是配置输出显示,图层属性设置、输出位置等信息。
Step6:绑定VDEC与VPSS,实现H264解码流程。
Step7:绑定VPSS与VO,实现H264解码流程。
Step8:推送视频流数据,这一步需要文件读写配合使用,然后对NALU进行分析推流。
H.265解码实例参考了海思提供的样例及库,程序源码及相关库文件请点击这里,修改不同的编译链工具,即可在不同HI35XX系列平台运行。H.265编码标准相比于H.264有了很大的革新,特别是移动互联网的发展以及高清4K视频的需求日益增长,H.265编码标准从襁褓中逐渐走向成熟。本文目的主要是梳理与H.265解码相关的一些知识,以作备忘,当然H.265相关的知识远远不止于此,好在海思提供了API,屏蔽了复杂的解码实现(硬件解码),方便了上层应用的开发。
参考:
http://club.realpower265.com/forum-2-1.html
https://blog.csdn.net/wh8_2011/article/details/52175275
http://www.istis.sh.cn/list/list.aspx?id=8060