RFC3984是H.264的baseline码流在RTP方式下传输的规范,这里只讨论FU-A分包方式。
1、单个NAL包单元
一个封装单个
NAL
单元包到
RTP
的
NAL
单元流的
RTP
序号必须符合
NAL
单元的解码顺序。单个
NAL
单元包的结构显示在图
1
。
注
: NAL
单元的第一字节和
RTP
荷载头第一个字节重合。
0
1
2
3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|NRI|
type |
|
+-+-+-+-+-+-+
|
|
|
|
Bytes 2..n of a Single NAL unit
|
|
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
|
:...OPTIONAL RTP padding
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
图
1.
单个
NAL
单元包的
RTP
荷载格式。
2、FU-A的分片格式
如图2 所 示, FU-A 的 RTP 荷载格式。 FU-A 由 1 字节的分片单元指示, 1 字节的分片单元头,和分片单元荷载组成。
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FU indicator| FU header | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-++-++-++-++-++-++-++-++-++-++-+|
| |
| FU payload |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
图 2. FU-A 的 RTP 荷载格式
FU indicator 有以下格式:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+
FU 指示字节的类型域 ,28 表示 FU-A 。。 NRI 域的值必须根据分片 NAL 单元的 NRI 域的值设置。
FU header 的格式如下:
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R| Type |
+---------------+
S: 1 bit
当设置成 1, 开始位指示分片 NAL 单元的开始。当跟随的 FU 荷载不是分片 NAL 单元荷载的开始,开始位设为 0 。
E: 1 bit
当设置成 1, 结束位指示分片 NAL 单元的结束,即 , 荷载的最后字节也是分片 NAL 单元的最后一个字节。当跟随的 FU 荷载不是分片 NAL 单元的最后分片 , 结束位设置为 0 。
R: 1 bit
保留位必须设置为 0 ,接收者必须忽略该位。
Type: 5 bits
NAL 单元荷载类型定义见下表
表
1.
单元类型以及荷载结构总结
Type
Packet
Type name
---------------------------------------------------------
0
undefined
-
1-23
NAL unit
Single NAL unit packet per H.264
24
STAP-A
Single-time aggregation packet
25
STAP-B
Single-time aggregation packet
26
MTAP16
Multi-time aggregation packet
27
MTAP24
Multi-time aggregation packet
28
FU-A
Fragmentation unit
29
FU-B
Fragmentation unit
30-31
undefined
-
3、拆包和解包
拆包:当编码器在编码时需要将原有一个 NAL 按照 FU-A 进行分片,原有的 NAL 的单元头与分片后的 FU-A 的单元头有如下关系:
原始的 NAL 头的前三位为 FU indicator 的前三位,原始的 NAL 头的后五位为 FU header 的后五位, FU indicator 与 FU header 的剩余位数根据实际情况决定。
解包:当接收端收到 FU-A 的分片数据,需要将所有的分片包组合还原成原始的 NAl 包时, FU-A 的单元头与还原后的 NAL 的关系如下:
还原后的 NAL 头的八位是由 FU indicator 的前三位加 FU header 的后五位组成,即:
nal_unit_type = (fu_indicator & 0xe0) | (fu_header & 0x1f)
4、代码实现
void CVAUClientSource::AnalyzeHeader(unsigned char * src, int len)
{
unsigned char head1 = *src;//
获取第一个字节
unsigned char head2 = *(src+1);//
获取第二个字节
unsigned char type = head1 & 0x1f;//
获取
FU indicator
的类型域,
if (type==0x1c)//
判断
NAL
的类型为
0x1c=28
,说明是
FU-A
分片
{//fu-a
unsigned char flag = head2 & 0xe0;//
获取
FU header
的前三位,判断当前是分包的开始、中间或结束
if (flag==0x80)
{//
开始
/*
进行处理
*/
}
else (flag==0x40)
{//
结束
/*
进行处理
*/
}
else
{//
中间
/*
进行处理
*/
}
}
else
{//
单包数据
/*
进行处理
*/
}
return;
}