前言
H264视频编码技术诞生于2003年,至今已有十余载,技术相当成熟,它的优势在于有高的视频的压缩率,利用帧间和帧内预测(Estimation)、变换(Transform)和反变换、量化(Quantization)和反量化、环路滤波(Loop Filter)、熵编码(Entropy Coding)等视频编码技术,可以实现高质量、低码率的视频流编码。H.264提供了网络抽象层NALU(Network Abstraction Layer)概念对编码出来的视频码流进一步格式封装,使得H.264的文件能容易地在不同网络上传输,以达到低带宽占用、低播放延时的目的。相信在未来几年H.264仍是视频编码的主流技术,尽管在2013年提出了H.265新一代视频编码技术,但是H265的压缩率仅仅提高40%,复杂程度却提升%50以上,这对硬件性能提出新的要求。本文讲述如何在海思HI35xx平台上实现H.264解码。
背景知识
先来弄清楚视频格式和视频编码的相互关系,视频格式可以理解为一个容器,它将编码器生成的多媒体内容(视频,音频,字幕,章节信息等)混合封装在一起的标准,这样就能很好处理视频、音频、字幕的播放同步问题,常见的视频格式有mp4、avi、flv、rmvb、mkv等等。视频编码属于后处理技术,它其实是非必须的,但是从摄像机采集出来的数据十分庞大,不适合网络传输和存储,故需要对视频进行编码压缩,以达到低码率、高成像质量的目的,常见的视频编码技术有h.263,h.264,mpeg-4。接下来我们了解一下海思HIMPP平台解码的概念,HIMPP平台音视频编解码架构遵循下图所示的数据处理流程。H264解码实例走的是HARD DISK->VDEC->VPSS->VO->显示器的流程,这个流程一定要熟悉牢记,代码实现都是围绕这条主线来编写的。
H264解码实例
实例源码很简单,先来了解一下实现H.264解码实例的几个函数,以达到了解实例源码大概构造组成,然后再对每个函数进行具体分析。
/*
**函数描述:linux标准信号捕捉函数
**函数功用:接收Ctrl+C信号,用来退出程序,并销毁HIMPP调用
*/
HI_VOID SAMPLE_VDEC_HandleSig(HI_S32 signo)
{
......
}
/*
**函数描述:用于音视频文件读写推流
**函数功用:用fread等文件操作函数读取音视频文件,并解析后推送HIMPP进行解码
*/
int SAMPLE_COMM_VDEC_H264_SendStream( VdecThreadParam *pArgs)
{
......
}
}
/*
**函数描述:HIMPP系统初始化
**函数功用:配置HIMPP系统的各项参数以满足对目标进行编解码
*/
HI_S32 HI_S32 SAMPLE_VDEC_VdhH264(char *filename)
{
......
}
/*
**主函数
*/
int main(int argc, char *argv[])
{
......
}
下面重点讲解SAMPLE_VDEC_VdhH264(char*filename)这个函数,它是H264解码样例的重点函数。HIMPP系统的API函数是海思提供的SDK开发包,调用它相关的接口,在编译时必须将其提供的相应库文件进行包含编译。下面结合样例程序讲述如何使用HIMPP提供的API实现自己的业务逻辑。H.264视频解码实例走的是HARDDISK->VDEC->VPSS->VO->显示器的处理流程,这个过程可以细分为八大步骤,这八大步骤在其他类型的音视频编解码样例也类似,可以说这八大步骤是使用海思HIMPP API的灵魂。下面简单介绍这个八大步骤的内容:
Step1:初始化HIMPP SYS和通用VB缓冲,包括设置缓冲区的大小,缓冲区块的数目。需要注意的是,在设置通用VB参数之前,必须确保HIMPP系统已经退出,否则设置失败。
Step2:设置通用缓冲区的公共缓冲池属性。
Step3:配置解码器,包括指定解码类型,这里是H.264解码样例,当然选PT_H264啦,然后指定视频大小、解码优先级等等。然后创建解码通道,并是能加收解码流。
Step4:配置VPSS参数,VPSS是对VDEC解码后的流进行处理,如裁剪、降噪等,MPEG解码实例从简单应用出发,仅仅按默认的方式配置VPSS。
Step5:配置VO参数,这一步也很关键,因为它指定了画面输出,包括常见的HDMI和VGA,主要是配置输出显示,图层属性设置、输出位置等信息。
Step6:绑定VDEC与VPSS,实现H2