H264基础概念
简介
H264视频格式,有损压缩的,尽可能降低存储体积下获得较好的图像质量和低带宽图像传输。
帧的概念
经过压缩后的帧分为:I帧、P帧和B帧
I帧:关键帧,采用帧内压缩技术
P帧:向前参考帧,压缩时,只参考前面的帧,采用帧间压缩技术
B帧:双向参考帧,压缩时,既参考前帧,又参考后帧
GOP:图像序列,从当前的I帧到下一个I帧之前(只包括一个I帧)
I帧、P帧、B帧的宏观理解:
在一段时间内,相邻的图像像素、亮度等信息差别较小,所以没必要记录所有帧的完整编码。可以选取这段时间的第一帧图像记录完整编码(I帧),而下一帧图像只记录与第一帧图像之间的差别(P帧),之后的帧以此类推(P帧、B帧)。当图像差别过大时,则再记录一帧完整的编码,作为后续帧的参考,直到下一次图像信息差别过大,这称之为一个序列(GOP)。
压缩方式
帧内压缩
将图像按16x16或者其他像素大小,划分成一个一个的宏块,计算每一个宏块的像素值。当宏块内有相对复杂的像素变化时,还可以在宏块里划分子块,计算每一个子块的像素值。
帧分组
通过两帧之间宏块的对比搜索,判断两帧之间的关联度,关联度高的帧就可以分到一组。
这样一组帧,在压缩时,只保留第一帧的完整数据,其他帧只记录帧间的差别。
帧间压缩
运动矢量与补偿
压缩步骤
-
分组,将变化不大的图像归为一组/序列(GOP)
-
定义帧,将组内的图像帧划分为I帧、P帧、B帧
-
预测帧,以I帧为基础预测P帧,再由I帧和P帧预测B帧
-
数据传输,将I帧数据和预测的差值,进行存储和传输
存储格式
H264有两种格式,一种是VCL即Video Coding Layer,一种是NAL即Network Abstraction Layer。
其中前者就是编码器吐出来的原始编码数据,没有考虑传输和存储问题。后面这种就是为了展现H.264的网络亲和性。
数据格式分析
H264是由一个个的NALU单元组成
一个NALU包含‘START CODE’、‘NALU HEADER’和‘RBSP’三部分
START CODE:00 00 00 01 代表一个NALU的开始
NALU HEADER:紧跟在start code后面的一个字节
HEADER格式:
F | 1bit | forbidden_zero_bit 在H264中必须为0 |
NRI | 2bit | nal_ref_idc,0-3,指示这个NALU的重要性,3最重要 |
Type | 5bit | nal_uint_type,NALU单元的类型 |
NALU类型解释(上表中的Type)
数据格式分析
一个H264视频由多个NALU组成,多种不同的NALU组成序列(sequence),一个H264视频包含一个或者多个序列。
在H264之中,一个序列代表一秒内采集到的视频数据的集合,在FPS为30的情况下,一个squence包含一个SPS、一个PPS、一个SEI、一个IDR(非参考帧,图像原本的数据)、30-1=29个PDR(参考帧,记录图像的变化)
SPS
Sequence Paramater Set,序列参数集。
SPS保存了一组编码视频序列的全局参数,一般处于整个码流的起始位置,有些情况下也可能出现在码流中间(解码器需要从中间开始解码、有码流参数的修改等)。
为了后续解码过程可以使用SPS包含的参数,必须解析SPS
PPS
Picture Paramater Set,图像参数集
通常与SPS一起,保存在文件头中
IDR
一个序列中的首个I帧称之为IDR,IDR作用是立即刷新,从IDR帧开始算新的序列,I帧有被跨序列参考的可能,但IDR不会。
IDR帧是I帧的特殊情况,通常第一个I帧为IDR帧。IDR帧一定为I帧,I帧不一定是IDR帧。
H.264引入IDR帧是为了 解码时候重同步:当解码到IDR帧时,立即清空参考帧队列,重新开始一个新的序列。IDR之后的帧不会使用IDR之前的帧来解码。
slice
一个slice包含某一帧的全部或者部分数据
slice由两部分组成:slice header用于保存slice的总体信息,另一部分slice body通常是一组连续的宏块。
在解码时,宏块会依赖slice header中的信息(例如:第一个宏块的位置,片的类型等)