H.264原始码流(裸流)是由一个接一个NALU组成,它的功能分为两层,VCL(视频编码层)和 NAL(网络提取层)
在VCL进行数据传输或存储之前,这些编码的VCL数据,被映射或封装进NALU
一个NALU = 一组对应于视频编码的NALU头部信息 + 一个原始字节序列负荷RBSP(Raw Byte Sequence Payload)
NALU的头 + RBSP 就相当于一个NALU(Nal Unit),每个单元都按独立的NALU传送
一个原始的H.264 NALU 单元常由 [StartCode] [NALU Header] [NALU Payload] 三部分组成,其中 Start Code 用于标示这是一个NALU 单元的开始,必须是”00 00 00 01” 或”00 00 01”
1、NAL Header由三部分组成,forbidden_bit(1bit),nal_reference_bit(2bits)(优先级),nal_unit_type(5bits)(类型)
0:未规定
1:非IDR图像中不采用数据划分的片段
2:非IDR图像中A类数据划分片段
3:非IDR图像中B类数据划分片段
4:非IDR图像中C类数据划分片段
5:IDR图像的片段
6:补充增强信息 (SEI)
7:序列参数集
8:图像参数集
9:分割符
10:序列结束符
11:流结束符
12:填充数据
13 – 23:保留
24 – 31:未规定
标识NAL单元中的RBSP数据类型,其中,nal_unit_type为1, 2, 3, 4, 5及12的NAL单元称为VCL的NAL单元,其他类型的NAL单元为非VCL的NAL单元。
2、SODB与RBSP
SODB 数据比特串:是编码后的原始数据.
RBSP 原始字节序列载荷:在原始编码数据的后面添加了结尾比特,一个 bit“1”若干比特“0”,以便字节对齐
SODB + RBSP trailing bits = RBSP
NAL header(1 byte) + RBSP = NALU
1帧 = n个片
1片 = n个宏块
1宏块 = 16x16yuv数据
1、Slice(片)
一个片 = Slice Header + Slice Data
片是通过编码图片后切分通过高效的方式整合出来的概念,一张图片有一个或者多个片,而片由NALU装载并进行网络传输的,但是NALU不一定是切片,NALU 还有可能装载着其他用作描述视频的信息。设置片的目的是为了限制误码的扩散和传输,应使编码片相互间是独立的,某片的预测不能以其他片中的宏块为参考图像,这样某一片中的预测误差才不会传播到其他片中。每个图像中,若干宏块(Macroblock)被排列成片,一个视频图像可编程一个或更多个片,每片包含整数个宏块 (MB),每片至少包含一个宏块。
2、宏块(Macroblock)
宏块是视频信息的主要承载者,一个编码图像通常划分为多个宏块组成,包含着每一个像素的亮度和色度信息,视频解码最主要的工作则是提供高效的方式从码流中获得宏块中像素阵列。
3、图像、场、帧
图像是个集合概念,顶 场、底场、帧都可以称为图像,在 H.264里提到的“帧”通常就是指不分场的图像。视频的一场或一帧可用来产生一个编码图像,一帧通常是一个完整的图像,当采集视频信号时,如果采用隔行扫描(奇.偶数行),则描下来的一帧图像就被分为了两个部分,这每一部分就被称为 [场],根据次序氛围: [顶场] 和 [底场]
4、I、P、B帧
I帧 帧内编码帧,又称intra picture,I 帧通常是每个 GOP(MPEG 所使用的一种视频压缩技术)的第一个帧,经过适度地压缩,做为随机访问的参考点,可以当成图象,I帧可以看成是一个图像经过压缩后的产物
P帧 前向预测编码帧,又称predictive-frame,通过充分将低于图像序列中前面已编码帧的时间冗余信息来压缩传输数据量的编码图像,也叫预测帧
B帧 双向预测帧,又称bi-directional interpolated prediction frame,既考虑与源图像序列前面已编码帧,也顾及源图像序列后面已编码帧之间的时间冗余信息来压缩传输数据量的编码图像,也叫双向预测帧
I frame:自身可以通过视频解压算法解压成一张单独的完整的图片
P frame:需要参考其前面的一个I frame 或者B frame来生成一张完整的图片
B frame:则要参考其前一个I或者P帧及其后面的一个P帧来生成一张完整的图片
5、DTS、PTS
PTS(Presentation Time Stamp) 主要用于度量解码后的视频帧什么时候被显示出来
DTS(Decode Time Stamp) 主要是标识内存中的bit流再什么时候开始送入解码器中进行解码
DTS主要用于视频的解码,在解码阶段使用,PTS主要用于视频的同步和输出,在display的时候使用,再没有B frame的时候输出顺序一样
6、GOP
GOP是画面组,一个GOP是一组连续的画面。
GOP一般有两个数字,如M=3,N=12.M制定I帧与P帧之间的距离,N指定两个I帧之间的距离。增大图片组能有效的减少编码后的视频体积,但是也会降低视频质量
7、IDR
一个序列的第一个图像叫做 IDR 图像(立即刷新图像),IDR 图像都是 I 帧图像。
I和IDR帧都使用帧内预测。I帧不用参考任何帧,但是之后的P帧和B帧是有可能参考这个I帧之前的帧的。IDR就不允许这样。
H.264 引入 IDR 图像是为了解码的重同步,当解码器解码到 IDR 图像时,立即将参考帧队列清空,将已解码的数据全部输出或抛弃,重新查找参数集,开始一个新的序列,这样,如果前一个序列出现重大错误,在这里可以获得重新同步的机会,IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码
8、帧内预测(也叫帧内压缩)
帧内预测是利用视频空间域的相关性,使用同一帧图像内邻近已编码像素预测当前的像素,以达到有效去除视频时域冗余的目的
9、帧间预测(也叫帧间压缩)
H.264 帧间预测是利用已编码视频帧/场和基于块的运动补偿的预测模式。
10、PPS、SPS
在H.264标准协议中规定了多种不同的NAL Unit类型,其中类型7表示该NAL Unit内保存的数据为Sequence Paramater Se,在H.264的各种语法元素中,SPS中的信息至关重要,如果其中的数据丢失或出现错误,那么解码过程很可能会失败。
SPS即Sequence Paramater Set,又称作序列参数集,SPS中保存了一组编码视频序列(Coded video sequence)的全局参数,所谓的编码视频序列即原始视频的一帧一帧的像素数据经过编码之后的结构组成的序列,而每一帧的编码后数据所依赖的参数保存于图像参数集中。
一般情况SPS和PPS的NAL Unit通常位于整个码流的起始位置,但在某些特殊情况下,在码流中间也可能出现这两种结构,原因是:
1)解码器需要在码流中间开始解码;
2)编码器在编码的过程中改变了码流的参数(如图像分辨率等);
3)在做视频播放器时,为了让后续的解码过程可以使用SPS中包含的参数,必须对其中的数据进行解析
H.264中另一重要的参数集合为图像参数集Picture Paramater Set(PPS),通常情况下,PPS类似于SPS,在H.264的裸码流中单独保存在一个NAL Unit中,只是PPS NAL Unit的nal_unit_type值为8,而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。
H264压缩技术:
其中,I帧:关键帧,采用帧内压缩技术;P帧:向前参考帧,在压缩时,只参考前面已经处理的帧,采用帧间压缩技术;B帧:双向参考帧,在压缩时,它即参考前面的帧,又参考它后面的帧,采用帧间压缩技术
H264压缩基本原理
1、划分宏块
H264默认是使用 16X16 大小的区域作为一个宏块,也可以划分成 8X8 大小的宏块,划分好宏块后,计算宏块的象素值,以此类推,计算一幅图像中每个宏块的像素值。
2、划分子块
H264对比较平坦的图像使用 16X16 大小的宏块,但为了更高的压缩率,还可以在 16X16 的宏块上更划分出更小的子块,子块的大小可以是 8X16、 16X8、 8X8、 4X8、 8X4、 4X4,非常的灵活,这样再经过帧内压缩,可以得到更高效的数据。
3、帧分组
于视频数据主要有两类数据冗余,一类是时间上的数据冗余,另一类是空间上的数据冗余,其中时间上的数据冗余是最大的,对于这些关联特别密切的帧,其实我们只需要保存一帧的数据,其它帧都可以通过这一帧再按某种规则预测出来,所以说视频数据在时间上的冗余是最多的。为了达到相关帧通过预测的方法来压缩数据,就需要将视频帧进行分组。H264编码器会按顺序,每次取出两幅相邻的帧进行宏块比较,计算两帧的相似度,通过宏块扫描与宏块搜索可以发现这两个帧的关联度是非常高的,进而发现这一组帧的关联度都是非常高的。因此,上面这几帧就可以划分为一组。
帧分组算法是:在相邻几幅图像画面中,一般有差别的像素只有10%以内的点,亮度差值变化不超过2%,而色度差值的变化只有1%以内,我们认为这样的图可以分到一组。在这样一组帧中,经过编码后,我们只保留第一帖的完整数据,其它帧都通过参考上一帧计算出来,我们称第一帧为IDR/I帧,其它帧我们称为P/B帧,这样编码后的数据帧组我们称为GOP。
4、运动估计与补偿(帧间预测)
H264编码器首先按顺序从缓冲区头部取出两帧视频数据,然后进行宏块扫描。当发现其中一幅图片中有物体时,就在另一幅图的邻近位置(搜索窗口中)进行搜索,如果此时在另一幅图中找到该物体,那么就可以计算出物体的运动矢量了。运动矢量计算出来后,将相同部分(也就是绿色部分)减去,就得到了补偿数据。我们最终只需要将补偿数据进行压缩保存,以后在解码时就可以恢复原图了,压缩补偿后的数据只需要记录很少的一点数据,我们把运动矢量与补偿称为帧间压缩技术,它解决的是视频帧在时间上的数据冗余。
5、帧内预测
人眼对图象都有一个识别度,对低频的亮度很敏感,对高频的亮度不太敏感,所以基于一些研究,可以将一幅图像中人眼不敏感的数据去除掉。这样就提出了帧内预测技术。H264的帧内压缩与JPEG很相似,一幅图像被划分好宏块后,对每个宏块可以进行 9 种模式的预测。找出与原图最接近的一种预测模式。帧内预测后的图像与原始图像的对比,将原始图像与帧内预测后的图像相减得残差值,再将我们之前得到的预测模式信息一起保存起来,这样我们就可以在解码时恢复原图了
6、对残差数据做DCT转换
可以将残差数据做整数离散余弦变换,去掉数据的相关性,进一步压缩数据。这还不够,还可以进行CABAC无损压缩
7、CABAC(Context Adaptive Binary Arithmetic Coder 上下文自适应二级制算术编码) 压缩
CABAC也是给高频数据短码,给低频数据长码,同时还会根据上下文相关性进行压缩。[CAVLC (Context Adaptive Variable Length Coder),以zig-zag顺序用于对变换后的残差块进行编码,效率不如CABAC,但实现简单,是CABAC的替代品]
CABAC采用了高效的算术编码思想,同时充分考虑了视频流相关统计特性,大大提高了编码效率,其有三个主要特点: