H.264码流结构
好文章,来自【福优学苑@音视频+流媒体】
1、H264的结构图
2、H264的编码分层
H.264原始码流(裸流)是由一个接一个NALU组成,它的功能分为两层,VCL(视频编码层)和 NAL(网络提取层).
(1)NAL层 (视频数据网络抽象层)
因为H264最终还是要在网络上进行传输,在传输的时候,网络包的最大传输单元是1500字节,一个H264的帧往往是大于1500字节的,所以需要将一个帧拆成多个包进行传输。这些拆包、组包等工作都在NAL层去处理。
(2)VCL层 (视频编码层)
对视频的原始数据进行压缩。
3、码流的基本概念
(1)SODB ,String Of Data Bits 原始数据比特流
因为它是流的形式,所以长度不一定是8倍数,它是由 VLC 层产生的。
由于我们计算机是以8倍数去处理数据所以计算机在处理H264时,就需要 RBSP。
(2)RBSP,SODB + tailing bits (原始字节序列载荷)
由于它是一个压缩流,SODB 不知道是在何处结束,所以算法在SODB最后一位补一个1,没有按字节对齐的则补 0。
(3)EBSP (扩展字节序列载荷)
在生成压缩流之后,在每一帧的开头加一个起始位,这个起始位一般是 00 00 00 01 或者是 00 00 01。
所以在h264码流中规定每有两个连续的00 00,就增加一个0x03。
补充:EBSP 和 RBSP的区别
A、NALU的主体涉及到三个重要的名词,分别为EBSP、RBSP和SODB。
其中EBSP完全等价于NALU主体,而且它们三个的结构关系为:EBSP包含RBSP,RBSP包含SODB。
在h264的文档中,并没有EBSP这一名词出现,但是在h264的官方参考软件JM里,却使用了EBSP。
NALU的组成部分为:
NALU = NALU Header + RBSP
其实严格来说,这个等式是不成立的,因为RBSP并不等于NALU刨去NALU Header。
严格来说,NALU的组成部分应为:
NALU = NALU Header + EBSP
其中的EBSP为扩展字节序列载荷(Encapsulated Byte Sequence Payload),而RBSP为原始字节序列载荷(Raw Byte Sequence Payload)。
B、那为什么要弄一个EBSP呢?
EBSP相较于RBSP,多了防止竞争的一个字节:0x03。
我们知道,NALU的起始码为0x000001或0x00000001,同时H264规定,当检测到0x000000时,也可以表示当前NALU的结束。那这样就会产生一个问题,就是如果在NALU的内部,出现了0x000001或0x000000时该怎么办?
所以H264就提出了“防止竞争”这样一种机制,当编码器编码完一个NAL时,应该检测NALU内部,是否出现如下左侧的四个序列。当检测到它们存在时,编码器就在最后一个字节前,插入一个新的字节:0x03。
这样一来,当我们拿到EBSP时,就需要检测EBSP内是否有序列:0x000003,如果有,则去掉其中的0x03。这样一来,我们就能得到原始字节序列载荷:RBSP。
(4)NALU(NAL Unit)
在EBSP的基础上,加1字节的NAL 头
NAL Header(1B) + EBSP
4、NAL Unit
如上图所示,生成的H264视频帧是由多个切片组成的。
一个H264的帧至少由一个切片组成,不能没有切片,可以是一个到多个不能没有。
在网络传输的时候一个H264帧可能需要切开去传,一个一次传不完,这就按照切片来切。
每一个切片组成一个NAL Unit。
5、切片 与 宏块的关系
在切片数据中,包含若干个宏块。
在一个宏块中,又包含了宏块类型、宏块预测、残差数据。
6、H264码流的分层结构
1帧 = n个片
1片 = n个宏块
1宏块 = 16x16yuv数据
好文章,来自【福优学苑@音视频+流媒体】
***【在线视频教程】***