网上相关的文章应该很多了,这里我只对其中的一些疑惑做记录,以防忘记。
h264的裸流文件是由一个一个的nalu单元(nalu头+RBSP)构成,一般都以SPS+PPS开头,类似如下:
每个nalu头均以0x00000001 或者 0x000001 开头用以区分不用的nalu单元,如下是一个h264文件的二进制格式:
可以看到以00000001开始,67就是nal头了;
nal头结构如下:
长度:1byte
格式:frobidden_bit(1bit)+ nal_reference_bit(1bit)+ nal_unit_type(5bit)
forbidden_bit: 禁止位,初始为0,当网络发现NAL单元有比特错误时可设置该比特为1,以便接收方纠错或丢掉该单元。
nal_reference_bit: nal重要性指示,标志该NAL单元的重要性,值越大,越重要,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU。
nal_unit_type : 根据值表示不同的含义:比如0x07表示sps、0x08表示pps、0x05表示I帧。以67为例,二进制格式为:0x0110 0111,后5为7(type)表示该帧为sps单元。
同时要注意的是,根据H264的nal起始码防竞争机制,会在非起始码(0x000001或0x00000001)的00 00 后面插入 03 以区分(比如上图中的第二行)。
而RTP打包H264数据时,关于nalu会有多种打包方式,这里不概述,只说明流行的二种方式(单一打包、FU-A):
当nalu数据长度小于MTU大小时,一般采用单一nal单元模式。即单个nalu打包为一个MTU包。此时RTP NAL头类型与原始的H.264的nalu头类型字段完全一致,所以简单打包为如下格式即可:
RTP头(12byte+?)+ nal头(1byte)+ RBSP
当nalu数据长度大于MTU大小时,就需要对nalu进行分片分包。一共二种FU-A、FU-B,大多情况下采用前者。所以这里只针对FU-A打包说明:
FU-A的打包方式为:
RTP头(12byte+?)+ FU indicator + FU header + RBSP
可以看到没有了nal头,其实nal头的frobidden_bit 、nal_reference_bit、 nal_unit_type分别装在了 FU indicator与FU header中;
FU indicator的格式:
长度:1byte
格式:F(1bit)+ NRI(2bit)+ Type (5bit)
F: 即nal头的frobidden_bit
NRI: 即nal头的nal_reference_bit
Type: 为固定值28表示分片方式为FU-A(FU-B为29)
FU header的格式为:
长度:1byte
格式:S(1bit) + E (1bit) + R(1bit) + Type(5bit)
S: 是否是起始包,分包时,第一个分包置为1,否则为0;
E: 是否是结束包,分包时,最后一个分包置为1,否则为0;
R: 保留字段,必须为0且忽略该字段;
Type: nal头的nal_unit_type;
相关文章:
RTP打包H264实现:
http://blog.csdn.net/dengzikun/article/details/5807694
http://blog.csdn.net/chenchong_219/article/details/37996161
RTP协议解析:http://blog.csdn.net/chen495810242/article/details/39207305
H264 nalu格式分析 :http://blog.csdn.net/newthinker_wei/article/details/8748442
RTMP打包发送H264、aac音视频,里面对一些需要注意的内容有详细说明:http://www.codeman.net/2014/01/439.html