转自:http://www.cnblogs.com/ghw-NO1/archive/2012/08/28/2660848.html
一、概述 本文讲述的是对H264编码且封装成MP4格式的视频流进行RTP打包过程时需要了解的一些基本知识。 二、H264的基础知识 1.H264的编码格式 H.263 定义的码流结构是分级结构,共四层。自上而下分别为:图像层(picturelayer)、块组层(GOB layer)、宏块层(macroblock layer)和块层(block layer)。而与H.263 相比,H.264的码流结构和H.263 的有很大的区别,它采用的不再是严格的分级结构。H.264 支持4:2:0 的连续或隔行视频的编码和解码。H.264 压缩与H.263、MPEG-4 相比,视频压缩比提高了一倍。 H.264 的功能分为两层:视频编码层(VCL, Video Coding Layer)和网络提取层(NAL,Network Abstraction Layer)。VCL 数据即编码处理的输出,它表示被压缩编码后的视频数据序列。在VCL 数据传输或存储之前,这些编码的VCL 数据,先被映射或封装进NAL 单元中。每个NAL 单元包括一个原始字节序列负荷(RBSP, Raw Byte Sequence Payload)、一组对应于视频编码的NAL 头信息。RBSP 的基本结构是:在原始编码数据的后面填加了结尾比特。一个bit“1”若干比特“0”,以便字节对齐。 2.H264的传输 H.264 的编码视频序列包括一系列的NAL 单元,每个NAL 单元包含一个RBSP,见表1。编码片(包括数据分割片IDR 片)和序列RBSP 结束符被定义为VCL NAL 单元,其余
3.H264的码流结构
起始码:如果NALU 对应的Slice 为一帧的开始,则用4 字节表示,即0x00000001;否则用3 字节表示,0x000001。 一个frame是可以分割成多个Slice来编码的,而一个Slice编码之后被打包进一个NAL单元,不过NAL单元除了容纳Slice编码的码流外,还可以容纳其他数据,比如序列参数集SPS。 三、MP4封装的H264数据 MP4文件中所有数据都封装在box中,它是由若干个子box组成,每个box还可以包含另外的子box,且每个box都有长度和类型。“ftyp”(66 74 79 70)box:作为MP4格式的标志并包含关于文件的一些信息,有且仅有一个;“moov”(6D 6F 6F 76)box:包含了媒体的metadata信息(特别是avcC中的sps和pps),有且仅有一个;“mdat”(6D 64 61 74)box:包含了MP4的媒体数据,可以有多个,也可以没有。但是媒体数据的结构由metadata进行描述。MP4中box存储方式为大端模式。一般,标准的box开头会有四个字节的box size。 在MP4格式文件中,H264 slice并不是以00 00 00 01来作分割,而是存储在mdat box中。H264基本码流由一些列的NALU组成。原始的NALU单元组成:[start code] + [NALU header] + [NALU payload]. MP4数据格式:|"ftyp"box|"moov"box(及其子box)|"mdat"box|....|。 "mdat"box的格式:|box的length(4字节)|box类型(4字节)mdat-6D 64 61 74|NALU的length(4字节)|NALU的header(1字节)|payload|; MP4封装结构图: box结构图:
用MP4info分析的实例分析图:
四、H264视频流的RTP封包 1.RTP打包原则 RTP的包长度必须要小于MTU(最大传输单元),IP协议中MTU的最大长度为1500字节。除去IP报头(20字节)、UDP报头(8字节)、RTP头(12字节),所有RTP有效载荷(即NALU内容)的长度不得超过1460字节。
2.RTP协议的报文结构
开始12个八进制出现在每个RTP包中,而CSRC标识列表仅出现在混合器插入时。各段含义如下: 或M:标示位,1 位。如果当前 NALU为一个接入单元最后的那个NALU,那么将M位置 1;或者当前RTP 数据包为一个NALU 的最后的那个分片时(NALU 的分片在后面讲述),M位置 1。其余情况下M 位保持为 0。
由上图可知,如果只有系列号,并不能完整按照顺序的将data播放出来,因为如果data中间有一段是没有资料的,只有系列号的话会造成错误,需搭配上让它知道在哪个时间将data正确播放出来,如此我们才能播放出正确无误的信息。 3.NALU header结构图 NALU header由一个字节组成, 它的语法如下:
F: 1 个比特.forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0. NRI: 2 个比特.nal_ref_idc. 取 00 ~ 11, 似乎指示这个 NALU 的重要性, 如00的NALU解码器可以丢弃它而不影响图像的回放. 不过一般情况下不太关心这个属性. Type: 5 个比特.nal_unit_type. 这个 NALU 单元的类型. 但是在h264中只有 1~23 是有效的值.而其他的24~29在RTP封包采用”组合封包模式“和”分片封包模式“时所用的type类型,而非“单一NAL单元模式”时。 简述如下: 0 没有定义 4.RTP打包模式 主要分为三种模式:单一NALU模式、分片模式、组合模式,实际中前两种用的比较多。 (1)单一NALU模式 一个RTP包仅由一个完整的NALU组成。这种情况下RTP NAL头类型字段和原始的H.264的NALU头类型字段是一样的。适合条件是当NALU的长度小于RTP包长减去12时。
特别NALU type 值为 7 和 8 的NALU分别为序列参数集(sps)和图像参数集(pps)。 (2)组合封包模式 即可能是由多个 NAL 单元组成一个 RTP 包. 分别有4种组合方式: STAP-A, STAP-B, MTAP16, MTAP24.那么这里的类型值分别是 24, 25, 26 以及 27.适合条件当 NALU 的长度特别小时, 可以把几个 NALU 单元封在一个 RTP 包中.
(3)分片封包模式Fragmentation Units (FUs) 用于把一个 NALU 单元封装成多个 RTP 包. 存在两种类型 FU-A 和 FU-B. 类型值分别是 28 和 29。适合条件当 NALU 的长度超过 MTU 时, 就必须对 NALU 单元进行分片封包.
FU indicator 结构
FU Header 结构:
S:当设置成1,开始位指示分片NAL单元的开始。当跟随的FU荷载不是分片NAL单元荷载的开始,开始位设为0。 Type:与NALU的header中的Type类型一致。 |
|