1.什么是音视频?
比如我们下载的mp4格式(还有rmvb、avi)的电影
2.什么是h264?
对摄像头采集的每一帧视频需要进行编码,由于视频中存在空间和时间的冗余, 需要用算法来去除这些冗余。H264是专门去除这些冗余的算法,我们把这种算法称为H264编码,当然还有mpeg4、vp9等编码,它们的区别就是实现的算法不一样。
3.为什么需要对视频编码?
可能有的人会问可不可以将每一帧保存到文件,音频再单独保存呢?答案是在早期是可以的,在早期放映视频的电影院中,确实是通过保存每一帧的画面数据,音频数据单独存放,来达到保存视频文件的效果。一个胶卷30公斤重,是不是觉得很离谱。随着科技的发展,现在肯定不会这样做了,第一,存储问题。第二,网络传输问题。所以需要对视频编码来去冗余(空间、时间、编码、视觉、知识)。
4.什么是封装格式和编码格式?
比如一个.rar的压缩包,这个压缩包就相当于一个封装格式,压缩包里的文件相当于是编码格式。mp4就是封装格式。如下引用的图所示
5.什么是I帧、P帧、B帧?
如下图byte数据就是
I帧:完整编码的帧叫I帧
P帧:参考之前的I帧生成的只包含差异部分编码的帧叫P帧
B帧:参考前后的帧编码的帧叫B帧
除了I/P/B帧外,还有图像序列GOP
GOP:两个I帧之间是一个图像序列,在一个图像序列中只有一个I帧
按显示顺序(播放顺序)排列的帧
按解码顺序排列的帧
以上只是简单介绍了一下I帧、B帧、P帧的概念
6.什么是NALU单元?
H264原始码流(又称为裸流),是由一个接一个的NALU单元组成
上图中的 NALU头 + RBSP(切片) 就相当与一个 NALU 。每个单元都按独立的NAL单元传送。单元的信息头(一个字节)定义了RBSP单元的类型,NAL单元的其余部分为RBSP数据。
7.什么是切片?
视频序列就是一帧一帧的图像
把一张图片划分成若干个小的区域,这些小的区域称之为宏块
H264默认是使用 16X16 大小的区域作为一个宏块,也可以划分成 8X8 大小
8.程序如何解析上面byte数据的呢?
上面说了分隔符是0x00000001,也就是起始码,根据起始码后面的一个字节的后五位来确定NAL单元的类型,如下图所示
06转为二进制后取后五位并转为十进制为6,表示补充增强信息单元,即SEI
67同上十进制为7 ,表示序列参数集,即SPS
68同上十进制为8 ,表示序图像参数集,即PPS
65同上十进制为5 ,表示IDR图像中的片,即 I帧
注意:起始码:如果NALU对应的Slice为一帧的开始,则用4字节表示,即0x00000001;否则用3字节表示,0x000001 。 脱壳操作:为了使NALU主体不包括起始码,在编码时每遇到两个字节(连续)的0,就插入一字节0x03,以和起始码相区别。解码时,则将相应的0x03删除掉。
H264解码NAL头信息的nal_referrence_idc(NRI)用于在重建过程中标记一个NAL单元的重要性
1. 值为0表示这个NAL单元没有用预测,因此可以被解码器抛弃而不会有错误扩散
2. 值高于0表示NAL单元要用于无漂移重构,且值越高,对此NAL单元丢失的影响越大
3. NAL头信息的隐藏比特位,在H264编码器中默认为0,当网络识别到单元中存在比特错误时,可将其置为1。隐藏比特位主要用于适应不同种类的网络环境(比如有线无线相结合的环境)
以上就是NAL单元解码的流程,首先从NAL单元中提取出RBSP语法结构,然后上图所示的流程处理RBSP语法结构,不同的NALU类型走不同的处理流程
上面大概介绍了一下H264的编码原理,H264的压缩原理没有具体介绍,有时间再与大家分享一下,感兴趣的可以去学习一下(帧分组、运动估计与补偿、帧内预测、对残差数据做DCT)