H264画面组
H264并不会记录每帧图像的完整数据,而是只记录一帧完整的图像,其它帧通过相对于此帧的像素变化来表示
由于短时间内,图像绝大部分是不会发生变化的,因此这种记录方式,可以大幅节省存储空间
参照帧和若干组相对变化帧,就构成了一个完整的H264画面组,简称GOP(Group of Picture)
H264画面组构成
- I帧,Intra Picture,关键帧,存储完整的图像数据,供其它帧参考
- 一个GOP可以包含多个I帧,在图像变化比较大时,单个I帧可能只在几帧内有参考价值,因此需经常刷新新的I帧
- IDR帧,Instant Decoding Refresh,即时解码帧,特殊的I帧,除了存储完整的图像数据,还起到刷新图像参数参数的作用。比如视频分辨率或码率中间改变了,编辑器可以通过读取IDR帧进行刷新。每个GOP的首帧一定是IDR帧
- P帧,Predictive Frame,前向预测帧,通过记录和前一个I/P帧的图像变化,来表示当前帧
- B帧,Bi-Directional Interpolated Prediction Frame,双向预测帧,通过记录和前一个I/P帧,后一个P帧的图像变化,来表示当前帧
- P帧和B帧虽然可以有效节省存储空间,但是其解码难度较大,影响性能,而且PB帧的长期积累,可能会导致和I帧之间的误差积累越来越大,因此PB帧出现的比例也不是越多越好
- SP帧和SI帧,随着H264/AVC的发展,为了适应带宽变化,码流切换,快进快退,进度恢复等应用需求,而推出的新型帧。SP帧和SI帧可以参考多个参照帧,来推断出当前帧的图像
- SP帧基于帧间预测技术,SI帧基于帧内预测技术。视频切换时如果只是视频格式切换,但视频内容不变,适合使用SP帧。视频切换时如果视频内容改变,则适合使用SI帧
帧内压缩和帧间压缩
- 宏块划分。将图片划分为若干个16×16的区块,如果图片像素比较复杂,还可以将大块再划分为若干8×8,4×4小块,这样是为了方便图片压缩算法的执行
- 帧内压缩和帧内预测。每帧画面内都会有一些像素是肉眼不易察觉的,我们就可以不保存这部分像素数据,起到压缩效果。此外,如果某个区块和周围区块像素极其相似,那么可以不保存这个区块的像素,还原图像时,通过其它的区块就能推测出当前块的大致数据,这个叫做帧内预测
- 帧间压缩和帧间预测。当视频在短时间内帧数据变化比较小时,我们只需保存首帧的完整像素,其它帧只需记录变化像素即可,还原图像时,根据参照帧和像素变化,就能推测出其它帧的数据,这个叫做帧间预测
H264码流结构
- H264码流由若干NAL(Network Abstraction Layer,网络抽象层)单元构成,简称NALU
- NAL单元又分为两种:VCL单元(VCL NAL Unit),非VCL单元(Non-VCL NAL Unit)
- VCL单元(Video Coding Layer,视频编码层),负责定义编码结构,宏块划分,帧内预测等功能
- 非VCL单元,负责视频数据的封包,以便在网络中进行传输
- 一个NAL单元包括起始码,NAL头,数据包三部分
- NALU以0x00000001作为起始码,占四个字节
- 我们一般将NALU中的数据包简称为RBSP(Raw Byte Sequence Packet/Payload,原始字节序列)
- 一段RBSP可以包含完整的帧数据(IDR,SLICE),也可以只包含由帧图像分割成的切片数据(SLICE_DPA,SLICE_DPB,SLICE_DPC)
- NAL头包括三部分数据:forbidden_bit,nal_reference_bit,nal_unit_type
- 第1位为禁止位,0表示正常,1表示错误,应当丢掉此单元
- 第2-3位为重要性指示位,数字越大越重要,网络繁忙时,可以丢掉重要性低的帧
- 第4-8位为单元类型位,表示帧的类型
从NALU中获取NAL_UNIT_TYPE
NALU中起始码占四个字节,禁止位+重要性位+NAL_UNIT_TYPE占一个字节
禁止位,重要性位一般都是固定的,所以根据第五个字节的数值就能判断出NAL_UNIT_TYPE的数值 NAL_UNIT_TYPE
- SLICE:非IDR帧完整切片,包括P帧,B帧,普通I帧,SP/SI帧
- SLICE_DPA:非IDR帧切片块A,切片介绍见下节
- SLICE_DPB:非IDR帧切片块B
- SLICE_DPC:非IDR帧切片块C
- IDR:IDR帧
- SEI:Supplementary Enhancement Information,补充增强信息,对图像数据进行补充描述
- SPS:Sequence Parameter Set,序列参数集,包含图像宽高等配置信息
- PPS:Picture Parameter Set,图像参数集,存储图像和算法相关参数
- AUD:帧分隔符,两个AUD之间是一个完整的帧,9表示后面的是非IDR帧,10表示后面的是IDR帧
切片
除了IDR帧,其它帧图像在NALU即不是以帧为单位存储的,也不是以宏块为单位存储的
一般以若干宏块组成一个切片,若干切片组成一帧图像,这些切片存储在不同的NALU中
如果图像的所有宏块,都包含在同一个切片中,这个切片就是SLICE型的
否则是SLICE_DPA,SLICE_DPB或SLICE_DPC型的 NALU序列顺序
这是一个具有代表性的NALU序列,先是SPS和PPS单元来说明图像信息,接着是IDR给出参照帧完整图像,最后是若干Slice相对帧切片
我们以后做推流或者片段分析时,一段数据至少得包含SPS+PPS+IDR,才能完整还原一帧的图像