针对H264码流格式说明,网上已经有很多介绍了,最近也在看这个,这里根据自己理解,做个记录。
1、H264的功能分为两层:视频编码层(VLC,Video Coding Layer)和网络提取层(NAL, Network Abstraction Layer)。VLC数据即
编码处理的输出,它表示被压缩编码后的视频数据序列。在VCL数据传输或存储之前,这些编码的VCL数据先被映射或封装进NAL单
元。每个NAL单元包括一个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)、一组对应于视频编码的NAL头信息。
这里说明下RBSP,EBSP,SODB。
SODB:(String of Data Bits)最原始的编码数据,无任何附加数据。
RBSP:在SODB的基础上增加了rbsp_stop_ont_bit(bit值为1)并用0按字节补位对齐。
EBSP:(Encapsulation Byte Sequence Packets)在RBSP的基础上增加了防止伪起始码字节(0x03)。
RBSP的基本结构是在原始编码数据的后面添加了结尾比特。一个bit”1”,若干比特”0”,以便字节对齐。
NAL单元序列如下:
图1
每个NAL单元包括NAL头+RBSP。
典型的RBSP单元如下:
现在来具体的说明下NAL头和RBSP。
NAL头结构为:
+—————+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+—————+
NAL头说明:
针对Type的说明为:
然后我们根据一个实际的H264文件内容看下:
我们可以看到NAL的单元有SPS、PPS、SEI、IDR_SLICE等。NAL单元里面的头也显示了,头结构里面的nal_unit_type表示了RBSP是什么类型。这里要说明一点NAL_Size的大小是不包括startcode大小的。
接下来说明下起始码即刚刚上面提到的startcode。
起始码:如果NALU对应的Slice为一帧的开始,则用4字节表示,即0x00000001;否则用3个字节表示,即0x000001。
另外这里要用到上面提到的EBSP。为了使NALU的主体不包括起始码,在编码的时候每遇到两个字节(连续)的0,就插入一个字节0x03,以便和起始码相区别,解码时,则将相应的0x03删除掉。所以有时候NAL单元有可能是NAL头+EBSP组成。
NALU主体 编码时插入0x03
0x000000 >>>>>> 0x00000300
0x000001 >>>>>> 0x00000301
0x000002 >>>>>> 0x00000302
0x000003 >>>>>> 0x00000303
接下来对应刚刚的H264,其文件数据表示如下:
前面两个0x00000001对应PPS和SPS,第三个0x000001对应SEI。
2、接下来说说SPS、PPS和SEI。
SPS和PPS是用来初始化解码器的,没这些数据,视频数据是无法解析出来的。另外如果我们分析单独的H264文件,可以发现有的文件每个IDR帧前面都有PPS和SPS,有的只是开头才有。针对SPS和PPS,一般来说:
1)、如果是在直播的话,每个IDR帧前面都应该加上SPS和PPS,因为有的观众会中途进来观看。
2)、如果是本地稳定文件,可以在开头加上SPS和PPS,或者都加上,这个根据具体需要来。
另外说明下SEI,有的H264文件有SEI,有的则没有,这说明SEI对文件的播放并无太大影响。
SEI(Supplemental Enhancement Information):辅助增强信息。这里面可以存放一些影片简介,版权信息或者作者自己添加的一些信息。