最近在研究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单元即可。
NALU由【起始码】【NAL头】【一个不定长编码段(Payload)】组成
如有一个 H.264 的 NALU 是这样的:
[00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]
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]
则它代表:
要把H.264码流封装成RTP包发送出去,一共有三种模式,分别是
RTP包的结构:
[RTP Header][RTP Payload]
其中RTP Payload的第一个字节结构和NALU头一样,NALU的类型决定RTP包的封包模式,其中1-23表示单一NALU模式,24-31可以参考上述表格。
单一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]
这个结构和NAL Header也是一样的,但注意类型表示不是NALU的Header中的类型:
位 | 0 | 1-2 | 3-7 |
内容 | F | NRI | TYPE |
由于NALU被拆分多个分片(按顺序发送),必须要有一个标示表明FUs的第一个分片和最后一个分片,
这个头主要用于表示FU的位置,结构如下
位 | 0 | 1 | 2 | 3-7 |
内容 | S | E | R | TYPE |
由于时间关系(此博文花了2天时间),下一篇再讲解H.264码流整个RTP封包过程和如果转换出H.264码流文件。
原创文章,欢迎转载,请保留出处。
有任何错误、疑问或者建议,欢迎指出。
我的邮箱:[email protected]
MP4和H264的区别参考文章:
http://www.cnblogs.com/skyseraph/archive/2012/04/01/2429384.htmlnal_unit_type取值含义参考文章:
http://blog.csdn.net/evsqiezi/article/details/8492593组合封包模式参考文章:
http://blog.chinaunix.net/uid-24372973-id-293642.html