简介
H264码流格式有多种打包格式,包括字节流格式和RTP格式。本文详细介绍这几种码流格式。
字节流格式之AnnexB
AnnexB格式
字节流格式是h264官方协议文档中规定的格式,大部分编译器都支持这种格式的输出。AnnexB格式主要用于实时媒体网络数据传输,会在发送每个关键帧(I 帧)之前发送SPS和PPS数据,接收端可以随机解码并播放。
2.2 协议结构
协议规定,在每个NALU的前面加上起始码:0x000001或0x00000001。
基本格式如下:Start Code + NALU。
- 当起始码是0x00000001时,每个完整数据帧NAL单元或SPS数据NAL单元,或PPS数据NAL单元前都会添加上起始码,即0x00000001是每个NALU之间的间隔码,如下:
- 当起始码是0x000001时,完整数据帧会分片成多个Slice,每个Slice前都会添加上起始码,即0x000001是Slice之间的间隔码,如下:
字节流格式之AVCC
3.1 AVCC格式
AVCC格式相较于AnnexB格式,无需起始码,可以减少资源浪费。通常用于存储媒体文件到硬盘上,如MP4,MKV封装格式。
3.2 协议结构
协议规定,在每个NALU前加上NALU的长度值,长度值的字节可以是1,2,4字节,大端格式,具体长度占用字节数在头部信息里指明。
基本格式如下:NALU Lengh + NALU。
- 当AVCC格式表示前缀信息时,如下所示:
FFmpeg截取MP4文件头部信息,如下所示:
01 64 00 28 FF E1 00 18 67 64 00 28 AC 24 88 07 88 22 7E 58 40 00 00 FA 40 00 3A 98 03 C6 8C AB 01 00 04 68 EE 3C B0
头部信息字段表示如下:
字节序号
值(十六进制)
说明
1
0x01
Configuration version,默认0x01。
2
0x64
这是提取来自SPS的字段值,表示编码级别。
3
0x00
Profile compatibility。
4
0x28
AVC Level Indication,提取来自SPS的字段值,表示编码能力,跟分辨率、帧率、码率有关系。
5
0xFF
字节最后两位表示NALU长度占用字节数,即字节最后两位数值加1,这里是3+1=4字节。
6
0xE1
保留。
7, 8
0x00, 0x18
SPS数据长度,这里长度是24字节。
9-32
0x67-0xAB
SPS NALU数据。
33
0x01
PPS个数。
33, 34
0x00, 0x04
PPS数据长度,这里长度是4字节。
35-38
0x68-0xB0
PPS NALU数据。
- 当AVCC格式表示媒体数据时,如下所示:
RTP格式
4.1 RTP格式
实时流协议RTSP主要是对流媒体提供诸如播放、暂停、快进等操作,本身不具备传输媒体数据,需要RTP数据协议负责对流媒体数据进行封包并实现媒体流的实时传输,需要RTCP协议实时监控数据传输质量,为系统提供拥塞控制和流控制,使得实时流媒体数据的受控和点播变得可能。
4.2 协议结构
协议规定,在每个RTP数据报由头部信息和负载数据组成,其中头部前12个字节的含义是固定的,而负载则可以是音频或者视频数据。
基本格式如下:RTSP Header + RTP Header + Payload。
- RTP 头部字段表示如下:
字节序号
值(字符)
位宽
说明
1
V
2bit
RTP协议的版本号。
P
1bit
填充标志,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。
X
1bit
扩展标志,如果X=1,则在RTP报头后跟有一个扩展报头。
CC
4bit
CSRC计数器。
2
M
1bit
不同的有效载荷有不同的含义。对于视频,标记一帧的结束;对于音频,标记会话的开始。
PT
7bit
有效荷载类型,0x60表示视频数据类型,0x61表示音频数据类型。
3,4
Sequence
2Byte
用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。
5,6,7,8
Timestamp
4Byte
时间戳
9,10,11,12
SSRC
4Byte
用于标识同步信源。该标识符是随机选择的,参加同一视频会议的两个同步信源不能有相同的SSRC。
RTSP头部字段表示如下:
字节序号
位宽
说明
1
1Byte
固定字符为'$'。
2
1Byte
RTP的通道号,0x00表示视频数据,0x01表示音频数据。
3,4
2Byte
RTP长度,包括RTP头字节和负载数据,大端格式。
- 当负载数据不分片时,如下所示:
Payload数据如果有起始码(00 00 00 01),需要先去掉。Payload首字节即可为RTP负载的首字节,所以RTSP Header里字节长度为12字节的RTP 头部和Payload数据长度。
- 当负载数据分片时,如下所示:
FU Indicator 分片指示器字段表示如下:
字节序号
字段名
位宽
说明
1
F
1bit
禁止位,协议规定为0。
NRI
2bit
重要性指示位,取值范围0~3。值越大,代表NALU越重要,就需要优先被保护。
Type
5bit
分片指示,默认为28。
FU header 分片单元头字段表示如下:
字节序号
字段名
位宽
说明
1
S
1bit
当设置成 1, 开始位指示分片 NAL 单元的开始。当跟随的荷载不是分片 NAL 单元荷载的开始,开始位设为 0。
E
1bit
当设置成 1, 结束位指示分片 NAL 单元的结束,即, 荷载的最后字节也是分片 NAL 单元的最后一个字节。当跟随的荷载不是分片 NAL 单元的最后分片, 结束位设置为 0。
R
1bit
保留位必须设置为 0。
NAL Type
5bit
取NALU的nal_unit_type。
由于分片头需要用到负载数据首字节的类型数据,所以Payload首字节提取出来,后面的数据用于分片。RTSP Header里字节长度为12字节的RTP 头部,2字节的分片头长度,和Payload数据分片长度。