RTP H264组包之单个NAL包和FU-A方式解析
为了在HI3615上调试RTSP,在网络上搜索整理的资料,因为调试时只用到了单个NAL包和FU-A方式,所以只摘抄了这两种方式的说明。特此分享。
1.RTP Header 解析
图1
1)V: RTP 协议的版本号,占 2 位,当前协议版本号为 2
2)P: 填充标志, 占 1 位, 如果 P=1, 则在该报文的尾部填充一个或多个额外的八位组, 它们不是有效载荷的一部分。
3)X:扩展标志,占 1 位,如果 X=1,则在 RTP 报头后跟有一个扩展报头
4)CC: CSRC 计数器,占 4 位,指示 CSRC 标识符的个数
5)M: 标记,占 1 位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。
6)PT: 有效荷载类型,占 7 位,用于说明 RTP 报文中有效载荷的类型,如 GSM 音频、 JPEM 图像等, 在流媒体中大部分是用来区分音频流和视频流的,这样便于客户端进行解析。
7) 序列号: 占 16 位, 用于标识发送者所发送的 RTP 报文的序列号, 每发送一个报文, 序列号增 1。 这个字段当下层的承载协议用 UDP 的时候, 网络状况不好的时候可以用来检查丢包。 同时出现网络抖动的情况可以用来对数据进行重新排序,序列号的初始值是随机的,同时音频包和视频包的 sequence是分别记数的。
8) 时戳(Timestamp) :占 32 位,必须使用 90 kHz 时钟频率。时戳反映了该 RTP 报文的第一个八位组的采样时刻。接收者使用时戳来计算延迟和延迟抖动,并进行同步控制。
9) 同步信源(SSRC) 标识符:占 32 位,用于标识同步信源。该标识符是随机选择的,参加同一视频会议的两个同步信源不能有相同的 SSRC。
10) 特约信源(CSRC) 标识符: 每个 CSRC 标识符占 32 位, 可以有 0~15 个。 每个 CSRC 标识了包含在该
RTP 报文有效载荷中的所有特约信源。
注:基本的 RTP 说明并不定义任何头扩展本身,如果遇到 X=1,需要特殊处理
取一段码流如下:
80 e0 00 1e 00 00 d2 f0 00 00 00 00 41 9b 6b 49 € ?....??....A?kI
e1 0f 26 53 02 1a ff06 59 97 1d d2 2e 8c 50 01 ?.&S....Y?.?.?P.
cc 13 ec 52 77 4e e50e 7b fd 16 11 66 27 7c b4 ?.?RwN?.{?..f'|?
f6 e1 29 d5 d6 a4 ef3e 12 d8 fd 6c 97 51 e7 e9 ??)????>.??l?Q??
cfc7 5e c8 a9 51 f6 82 65 d6 48 5a 86 b0 e0 8c ??^??Q??e?HZ????
其中,
80 是 V_P_X_CC
e0 是 M_PT
00 1e 是 SequenceNum
00 00 d2 f0 是 Timestamp
00 00 00 00 是 SSRC
把前两字节换成二进制如下
1000 0000 1110 0000
按顺序解释如下:
10 是 V;
0 是 P;
0 是 X;
0000 是 CC;
1 是 M;
110 0000 是 PT;
2.RTP 荷载 H264 码流
图2
荷载格式定义三个不同的基本荷载结构, 接收者可以通过 RTP 荷载的第一个字节后 5 位(如上图)识别荷载结构。
1) 单个 NAL 单元包:荷载中只包含一个 NAL 单元。 NAL 头类型域等于原始 NAL 单元类型, 即在范围 1到 23 之间;
2) 聚合包:本类型用于聚合多个 NAL 单元到单个 RTP 荷载中。本包有四种版本, 单时间聚合包类型 A(STAP-A) ,单时间聚合包类型 B (STAP-B) ,多时间聚合包类型(MTAP)16 位位移(MTAP16), 多时间聚合包类型(MTAP)24 位位移(MTAP24) 。赋予 STAP-A, STAP-B, MTAP16, MTAP24 的 NAL 单元类型号分别是 24,25, 26, 27;
3) 分片单元: 用于分片单个 NAL 单元到多个 RTP 包。 现存两个版本 FU-A, FU-B, 用 NAL 单元类型 28,29 标识;
常用的打包时的分包规则是:如果小于 MTU 采用单个 NAL 单元包,如果大于 MTU 就采用 FUs 分片方式。
因为常用的打包方式就是单个 NAL 包和 FU-A 方式,所以我们只解析这两种。
2.1.单个 NAL 单元包
图3
定义在此的 NAL 单元包必须只包含一个。这意味聚合包和分片单元不可以用在单个 NAL 单元包中。并且 RTP 序号必须符合 NAL 单元的解码顺序。 NAL 单元的第一字节和 RTP 荷载头第一个字节重合。如图 3。打包 H264 码流时,只需在帧前面加上 12 字节的 RTP 头即可。
2.2.分片单元(FU-A)
图4
分片只定义于单个 NAL 单元不用于任何聚合包。 NAL 单元的一个分片由整数个连续 NAL 单元字节组成。 每个 NAL 单元字节必须正好是该 NAL 单元一个分片的一部分。 相同 NAL 单元的分片必须使用递增的 RTP 序号连续顺序发送(第一和最后分片之间没有其他的 RTP 包) 。 相似, NAL 单元必须按照 RTP顺序号的顺序装配。
当一个 NAL 单元被分片运送在分片单元(FUs) 中时,被引用为分片 NAL 单元。 STAPs,MTAPs 不可以被分片。 FUs 不可以嵌套。 即, 一个 FU 不可以包含另一个 FU。 运送 FU 的 RTP 时戳被设置成分片NAL 单元的 NALU 时刻。
图 4 表示 FU-A 的 RTP 荷载格式。 FU-A 由 1 字节的分片单元指示(如图 5) , 1 字节的分片单元头(如图 6),和分片单元荷载组成。
图5 图6
S: 1 bit 当设置成 1, 开始位指示分片 NAL 单元的开始。当跟随的 FU 荷载不是分片 NAL 单元荷载的开始,开始位设为 0。
E: 1 bit 当设置成 1, 结束位指示分片 NAL 单元的结束,即, 荷载的最后字节也是分片 NAL 单元的最后一个字节。当跟随的 FU 荷载不是分片 NAL 单元的最后分片, 结束位设置为 0。
R: 1 bit 保留位必须设置为 0,接收者必须忽略该位打包时,原始的 NAL 头的前三位为 FU indicator 的前三位,原始的 NAL 头的后五位为 FU header 的后五位。
取一段码流分析如下:
80 60 01 0f 00 0e 10 00 00 0000 00 7c 85 88 82 € `..........|???
00 0a 7f ca 94 05 3b7f 3e 7f fe 14 2b 27 26 f8 ...??.;.>.?.+'&?
89 88 dd 85 62 e1 6dfc 33 01 38 1a 10 35 f2 14 ????b?m?3.8..5?.
84 6e 21 24 8f 72 62f0 51 7e 10 5f 0d 42 71 12 ?n!$?rb?Q~._.Bq.
17 65 62 a1 f1 44 dc df 4b 4a 38 aa 96 b7 dd 24 .eb??D??KJ8????$ 前 12 字节是 RTP Header
7c 是 FU indicator
85 是 FU Header
FU indicator(0x7C)和 FU Header(0x85)换成二进制如下
0111 1100 1000 0101
按顺序解析如下:
0 是 F
11 是 NRI
11100 是 FU Type,这里是 28,即 FU-A
1 是 S, Start,说明是分片的第一包
0 是 E, End,如果是分片的最后一包,设置为 1,这里不是
0 是 R, Remain,保留位,总是 0
00101 是 NAl Type,这里是 5,说明是关键帧(不知道为什么是关键帧请自行谷歌)
打包时, FUindicator 的 F、 NRI 是 NAL Header 中的 F、 NRI, Type 是 28; FU Header 的 S、 E、 R
分别按照分片起始位置设置, Type 是 NAL Header 中的 Type。
解包时,取 FU indicator 的前三位和 FU Header 的后五位,即 0110 0101(0x65)为 NAL 类型。
原内容出处:http://blog.csdn.net/chen495810242/article/details/39207305
凯特网版权声明:以上内容允许转载,但请注明出处,谢谢!