H264简介-也叫做 AVC
H.264,在MPEG的标准⾥是MPEG-4的⼀个组成部分–MPEG-4 Part 10,⼜叫Advanced Video Codec,因此常常称为MPEG-4 AVC或直接叫AVC。
原始数据YUV,RGB为什么要压缩-知道就行
在⾳视频传输过程中,视频⽂件的传输是⼀个极⼤的问题;⼀段分辨率为1920*1080,每个像素点为RGB占⽤3个字节,帧率是25的视频,对于传输带宽的要求是:
1920x1080x3x25/1024/1024=148.315MB/s, 这个是每秒的 bytes 数
换成bps则意味着视频每秒带宽为 148.315MB/s x 8 = 1186.523Mbps
1186.523Mbps,这样的速率对于⽹络存储是不可接受的。因此视频压缩和编码技术应运⽽⽣。
H264编码原理
帧内压缩
对于视频⽂件来说,视频由单张图⽚帧所组成,⽐如每秒25帧,但是图⽚帧的像素块之间存在
相似性,因此视频帧图像可以进⾏图像压缩;H264采⽤了16*16的分块⼤⼩对,视频帧图像
进⾏相似⽐较和压缩编码。如下图所示:
帧间压缩
H264采⽤了独特的I帧、P帧和B帧策略 来实现,连续帧之间的压缩;
H264将视频分为连续的帧进⾏传输,在连续的帧之间使⽤I帧、P帧和B帧。
同时对于帧内⽽⾔,将图像分块为⽚、宏块和字块进⾏分⽚传输;通过这个过程实现对视频⽂件的压缩包装。
IDR(Instantaneous Decoding Refresh,即时解码刷新)
⼀个序列的第⼀个图像叫做 IDR 图像(⽴即刷新图像),IDR 图像都是 I 帧图像。
I和IDR帧都使⽤帧内预测。I帧不⽤参考任何帧,但是之后的P帧和B帧是有可能参考这个I帧之
前的帧的。
但是在解码的时候,I 和 IDR 有区别。举例如下:在第一个解码的时候,解码到B8的时候,可以参考I10前面的P7.
在第二个解码的时候,B9 就只能参考 IDR8和 P11,不能参考IDR8之前的帧。
下⾯是⼀个H264码流的举例(从码流的帧分析可以看出来B帧不能被当做参考帧)
在假设条件下分析上图,假设GOP1 的是每秒25帧,也就是一帧画面需要1000/25 = 40ms.
I帧解码的时候时间点在0,那么读取下一帧B要依赖于 P,接着找下一帧是不是P,还不是,在找,直到找到P,也就是说:在 找P的时候已经过去了160ms了,大致如下:
I0 B40 B80 B120 P160
I0 B160
这意味着什么呢?在做实时性要求高的场景时,最好不要使用B帧
H264编码结构- NALU
发I帧之前,⾄少要发⼀次SPS和PPS。
SPS:序列参数集,SPS中保存了⼀组编码视频序列(Coded video sequence)的全局参数。
PPS:图像参数集,对应的是⼀个序列中某⼀幅图像或者某⼏幅图像的参数。
I帧:帧内编码帧,可独⽴解码⽣成完整的图⽚。
P帧: 前向预测编码帧,需要参考其前⾯的⼀个I 或者B 来⽣成⼀张完整的图⽚。
B帧: 双向预测内插编码帧,则要参考其前⼀个I或者P帧及其后⾯的⼀个P帧来⽣成⼀张完整的图⽚。
NALU的功能
NAL层即网络抽象层(Network Abstraction Layer),是为了方便在网络上传输的一种抽象层。一般网络上传输的数据包有大小限制,而AVC的帧大小远远大于网络传输的字节大小限制。因此要对AVC的数据流进行拆包,将一帧数据拆分为多个包传输。和NAL层相对是VAL层,即视频编码层(Video Coding Layer)
NALU就是经过分组后的一个一个数据包。
每个NALU = 由一个1字节的NALU头部 + 一个包含控制信息或编码视频数据的字节流组成。
NALU头部包含了NALU的类型以及其重要性的信息。NALU的类型指示了NALU的用途或功能,可以用于识别不同类型的单元,例如参数集和用于参考的片段。用于参考的参数集和片段被认为是重要或高优先级的,因为它们的丢失可能会导致难以解码后续的编码片段。非参考片段被认为对解码器的影响较小,因为它们的丢失不会影响进一步的解码。这些信息可以选择性地用于在传输过程中对某些NALU进行优先级排序。
每个NALU中的VCL数据即编码序列以一个或多个即时解码器刷新(IDR)访问单元开始,其中包含一个或多个IDR片段,每个IDR片段都是一个帧内编码的片段。接下来是默认的片段类型,即非IDR编码的片段,以及/或者数据分割片段。数据分割片段将编码视频数据的不同组件分别放在单独的NAL单元中,这在存在传输错误的情况下可能很有用。非VCL NAL单元包括参数集、补充增强信息参数,这些参数对解码和显示视频数据可能有用,但对于正确解码来说并非必需,以及定义编码部分之间边界的分隔符。