天天看点

H264视频码流格式浅析

针对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对文件的播放并无太大影响。

继续阅读