一.VCL和NAL的关系:
1.H.264的功能分两层:
VCL(Video Codeing Layer):视频编码层,负责的是视频内容的处理,重点在编解码算法;
NAL(Network Abstraction Layer):网络抽象层,负责将编码后的数据以网络要求的格式进行打包和传输;
2.H.264编码过程中的三种不同数据格式:
(1)SODB(String of Data Bits)数据比特串:
最原始的编码数据,即VCL数据,没有任何附加数据;
(2)RBSP(Raw Byte Sequence Payload)原始字节序列载荷:
在SODB数据后面加了结尾比特(rbsp_trailing_bits),一个bit的”1″,若干比特的”0″,目的是为了字节对齐;
RBSP = SODB + rbsp_trailing_bits
(3)EBSP(Encapsulated Byte Sequence Packets)扩展字节序列载荷:
在 RBSP 数据的基础上添加了防止竞争的一个字节“0x03”;
原因是:
H264中NALU的起始码为0x000001或0x00000001,
同时H264规定,当检测到0x000000时也可以表示当前NALU的结束,
但是如果在NALU的内部出现了0x000001或0x00000001时该怎么办?
所以H264就提出了“防止竞争”这样一种机制,当编码器编完一个NALU时,
应该检测NALU内部是否出现了如下左侧的数据,如果检测到它们的存在,
编码器就在最后一个字节前,插入一个新字节“0x03”:
0x000000 –> 0x00000300
0x000001 –> 0x00000301
0x000002 –> 0x00000302
0x000003 –> 0x00000303
注:
NALU的头是0x000001或0x00000001,都按上面的方式处理,
对于0x000001就是在第2个字节后插入0x03,
对于0x00000001就是在第3个字节后插入0x03。
当解码器解码时,将0x03去掉即可,也称为脱壳操作。
注:在H264的文档中,并没有EBSP这一名词出现,但是在H264的官方参考软件JM里,却使用了EBSP。
EBSP = RBSP + “0x03”
(4)NALU(Network Abstraction Layer Units)网络抽象层:
每个NAL单元是一个一定语法元素的可变长字节字符串,包括一个字节的头信息(用来表示数据类型),
以及若干整数字节的原始字节序列负荷(RBSP)。
一个NAL单元可以携带一个编码片,I帧、P帧、B帧、一个序列参数集、或一个图像参数集。
H264采用NAL单元可以适用于多种网络,而且进一步提高其抗误码能力。
序列号的设置可以发现丢失的是哪一个VLC单元,
冗余编码图像使得基本编码图像丢失仍可得到较粗糙的图像。
NALU = NAL header(1 byte) + RBSP
二.NAL的相关概念:
一段H264的码流开始处的十六进制数据:
00 00 00 01 67 42 00 1f 9d a8 14 01 6e 9b 80 80
80 81 00 00 00 01 68 ce 3c 80 00 00 00 01 06 e5
01 d3 80 00 00 00 01 65 b8 00 00 03 03 27 5c 27
ff ff c3 d1 40 00 40 7b c9 c9 c9 c9 c9 c9 c9 c9
c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9
c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9 c9
1.如何判断帧类型(是I帧还是SPS或PPS):
官方文档如下:
表7-1-NAL单元类型码
nal_unit_type NAL单元和RBSP语法结构的内容
0 未指定
1 一个非 IDR 图像的编码条带
2 编码条带数据分割块 A
3 编码条带数据分割块 B
4 编码条带数据分割块 C
5 IDR 图像的编码条带
6 辅助增强信息 (SEI)
7 序列参数集
8 图像参数集
9 访问单元分隔符
10 序列结尾
11 流结尾
12 填充数据
13 序列参数集扩展
14..18 保留
19 未分割的辅助编码图像的编码条带
20..23 保留
24..31 未指定
我们看码流数据,用分隔符“00 00 00 01”分割后的下一个字节就是NAL单元类型码,其中:
bit7: 禁止位,值为1表示语法出错;
bit5-6: 为参考级别;
bit0-4: 是NAL的单元类型:
上边码流分隔符后依次是:0x67、0x68、0x65
0x67—0b0110 0111,bit0-4转为十进制是7,对应的是序列参数集
0x68—0b0110 1000,bit0-4转为十进制是8,对应的是图像参数集
0x65—0b0110 0101,bit0-4转为十进制是5,对应的是IDR图像的编码条带
所以判断NAL单元是否为I帧的方式可以为:(nal_unit_type & 0x1f) == 5
2.序列:
一般来说,编码器编出来的首帧数据是PPS,然后是SPS,接下来是I帧,P帧、B帧等;
一个序列 == 一个SPS + 1个PPS + 一个I帧 + 若干P帧 + 若干B帧
3.分隔符:
分割符就是一段H264码流数据中,用以区分NAL单元的标志,即0x000001或0x00000001,
当遇见这样的分割符,接下来的数据就是一个NAL单元的数据。
4.SPS(Sequence Paramater Set)序列参数集:
SPS中保存了一组视频编码序列(Codec Video Sequence)的全局参数,
序列中每一帧编码后的数据所依赖的参数保存于图像参数集中,
一般情况下SPS和PPS的NAL单元通常位与整个码流的起始位置,但是在某些特殊情况下,
在码流中间也可能出现这两种结构,主要的原因可能为:
*解码器需要在码流中间开始解码;
*编码器在编码的过程中改变了码流的参数(如图像的分辨率);
5.PPS(Picture Paramater Set)图像参数集:
PPS类似于SPS,在H264的码流中单独保存在一个NAL单元中,
只是PPS NAL Unit的nal_unit_type值为8,
而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。
6.SEI辅助增强信息
SEI是H264标准中一个重要的技术,主要起补充和增强的作用。
SEI没有图像数据信息,只是对图像数据信息或者视频流的补充,
有些内容可能对解码有帮助.
图1.码流中的序列
三.reference:
https://www.cnblogs.com/wainiwann/p/7477794.html