H.264码流结构及码流封装成RTP包分析

最近在研究H.264码流文件的结构,现在总结整理一下。

H.264码流基本说明

MP4和H.264的关系

首先H.264/MPEG-4 AVC应该是一种视频编码格式,而MP4则是一个容器。
MP4用于封装H.264码流,为其提供一些额外的媒体数据,如记录码流的帧数之类的。
具体可以参考文章最后的参考文章。

格式名 描述 文件后缀名
MP4 用于封装媒体数据的容器 .mp4
H.264 一种视频编码方式,或者是H.264的码流文件 .264

基本结构

H.264的码流文件分为两层,视频编码层(VCL)和网络提取层(NAL)

VCL 视频编码层 进行视频编解码
NAL 网络提取层 采用适当的格式对视频数据进行封装打包

VCL数据:
即被压缩编码后的视频数据序列。在VCL数据要封装到NAL单元中之后,才可以用来传输或存储。
所以我们只需要研究NAL单元即可。

NAL单元(NALU)

NALU由【起始码】【NAL头】【一个不定长编码段(Payload)】组成

H.264码流结构及码流封装成RTP包分析_第1张图片

如有一个 H.264 的 NALU 是这样的:

[00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]
  • [00 00 00 01] 是四个字节的开始码
  • [67] 是 NAL头
  • [42 …] 开始的数据是 NAL内容(Payload)

NAL头(NAL Header)

NALU 头由一个字节组成
语法:NALU类型(5bit)、重要性位(2bit)、禁止位(1bit)
如下表:

0 1-2 3-7
简称 F NRI TYPE
全称 forbidden_zero_bit nal_ref_idc nal_unit_type
中文 禁止位 重要性指示位 NALU类型
作用 网络发现NAL单元有比特错误时可设置该比特为1,以便接收方丢掉该单元 标志该NAL单元用于重建时的重要性,值越大,越重要。取 00 ~ 11 1 ~ 23表示单个NAL包,24 ~ 31需要分包或者组合发送,具体含义需要参考下面的表格

下面是NALU类型取值含义:

nal_unit_type取值含义
0 没有定义
1-23 NAL单元,单个 NAL 单元包
1 不分区,非IDR图像的片
2 片分区A
3 片分区B
4 片分区C
5 IDR图像中的片
6 补充增强信息单元(SEI)
7 SPS
8 PPS
9 序列结束
10 序列结束
11 码流借宿
12 填充
13-23 保留
24 STAP-A 单一时间的组合包
25 STAP-B 单一时间的组合包
26 MTAP16 多个时间的组合包
27 MTAP24 多个时间的组合包
28 FU-A 分片的单元
29 FU-B 分片的单元
30-31 没有定义

假设是NALU 头如下:

[67]

则67转换成二进制为

[0110 0111]

则它代表:

  • 禁止位为[0]
  • NAL重要性为[11],即3,表示最重要
  • NALU类型为[0 0111],即7,从上面的表格可以看出,这个NALU是SPS

RTP封包模式

要把H.264码流封装成RTP包发送出去,一共有三种模式,分别是

  • 单一NALU模式
  • 组合封包模式
  • 分片封包模式

RTP包的结构:

[RTP Header][RTP Payload]

其中RTP Payload的第一个字节结构和NALU头一样,NALU的类型决定RTP包的封包模式,其中1-23表示单一NALU模式,24-31可以参考上述表格。

单一NALU模式

单一NAL单元模式即一个 RTP 包仅由一个完整的 NALU 组成。

例如下面一个H.264码流:

H264码流 起始码 NAL Header NAL Payload
内容 00 00 00 01 67 42 A0 1E 23 56 0E 2F…

删除起始码,添加RTP Header后即为RTP包:

RTP包 RTP Header RTP Payload
内容 67 42 A0 1E 23 56 0E 2F…

一句话,这个模式下:RTP Payload = [NAL Header] + [NAL Payload]

组合封包模式

由多个 NAL 单元组成一个 RTP 包。

分别有4种组合方式: STAP-A, STAP-B, MTAP16, MTAP24.那么这里的类型值分别是 24, 25, 26 以及 27。

这种情况我没有研究过,可以参考参考文章中的说明。

分片封包模式

用于把一个 NALU封装成多个 RTP 包。
存在两种类型 FU-A 和 FU-B,类型值分别是 28 和 29。

当 NALU 的长度超过 MTU (最大传输单元,一般是1500个字节)时,就必须对 NALU 进行分片封包。

每个被分割的数据包称为Fragmentation Unit (FU),结构如下:

Fragmentation Unit = [FU Indicator] + [FU Header] + [FU Payload]
FU Indicator FU Header FU Payload
1字节 1字节

这个模式下:RTP Payload = [Fragmentation Unit]

FU Indicator 结构

这个结构和NAL Header也是一样的,但注意类型表示不是NALU的Header中的类型

0 1-2 3-7
内容 F NRI TYPE
  • F:当网络识别此单元存在比特错误时,可将其设为 1,以便接收方丢掉该单元。
  • NRI:NALU的重要性,取00-11
  • TYPE:28表示FU-A,29表示FU-B

FU Header 结构

由于NALU被拆分多个分片(按顺序发送),必须要有一个标示表明FUs的第一个分片和最后一个分片,
这个头主要用于表示FU的位置,结构如下

0 1 2 3-7
内容 S E R TYPE
  • S:1表示NALU开始分片,0表示非开始NALU分片
  • E:1表示NALU结束分片,0表示非结束NALU分片
  • R:保留位必须设置为0,接收者必须忽略该位。
  • Type:与NALU的Header中的Type类型一致。(注意不是FU Indicator中的类型)

后记

由于时间关系(此博文花了2天时间),下一篇再讲解H.264码流整个RTP封包过程和如果转换出H.264码流文件。

声明

原创文章,欢迎转载,请保留出处。
有任何错误、疑问或者建议,欢迎指出。
我的邮箱:[email protected]

参考文章

MP4和H264的区别参考文章:
http://www.cnblogs.com/skyseraph/archive/2012/04/01/2429384.html

nal_unit_type取值含义参考文章:
http://blog.csdn.net/evsqiezi/article/details/8492593

组合封包模式参考文章:
http://blog.chinaunix.net/uid-24372973-id-293642.html

你可能感兴趣的:(RTP,h.264,封包,码流,NALU)