码迷,mamicode.com
首页 > 其他好文 > 详细

H264 NAL RTP打包

时间:2015-04-15 00:56:27      阅读:306      评论:0      收藏:0      [点我收藏+]

标签:

1. 网络抽象层单元类型 (NALU)

        NALU是H264用于网络传输的单元类型,一个完整的NALU单元一般是以0x000001或者0x00000001开始,其后跟的则是NALU头和NALU的数据;我们在网络传输的时候,会去掉开始的0x000001或者0x00000001的标志;一般需要将这些标志替换为RTP payload的头部(1个字节);

其中NALU数据就是RBSP数据;

技术分享

NALU 头由一个字节组成, 它的语法如下:

     +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+

F: 1 个比特.        forbidden_zero_bit. 在 H.264 规范中规定了这一位必须为 0.

NRI: 2 个比特.        nal_ref_idc. 重要性指示,标志该NAL单元的重要性,值越大,越重要,解码器在解码处理不过来的时候,可以丢掉重要性为0的NALU,取 00 ~ 11。

nal_ref_idc.  0值和非零值的语义与H.264规范保持一致。换句话,00值指示NAL单元的内容不用于重建影响图像的帧间图像预测。这样的NAL单元可以被丢弃而不用冒影响图像完整性的风险。大于00的值指示NAL单元的解码要求维护引用图像的完整性。       除了上面指定的外, 根据本RTP荷载规范, 大于00的NRI值指示相对传输优先级, 象编码器决定的一样。 MANE可以使用本信息保护更重要的NAL单元。最高的传输优先级是11, 依次是 10, 01;00 最低。(注释: 任何非零的NRI在H.264 解码器的处理是相同的。因此,接收者在传送NAL单元给解码器时不必操作NRI的值)

      H.264编码器必须根据H.264规范设置NRI值。当nal_unit_type 范围的是1到12. 特别是, H.264规范要求对于nal_unit_type为6,9,10,11,12的NAL单元的NRI的值应该为0; 对于nal_unit_type等于7,8 (指示顺序参数集或图像参数集)的NAL单元,H.264编码器应该设置NRI为11 (二进制格式);对于nal_unit_type等于5的主编码图像的编码片NAL单元(指示编码片属于一个IDR图像), H.264编码器应设置NRI为11; 对于映射其他的nal_unit_types到NRI值,下图可以使用,并且在某些环境有效,其它的映射也可以,依赖于应用以及使用的H.264/AVC Annex A profile。(注释: 在某些profile中数据分区不可用,即在Main或Baseline profiles. 因此, nal单元类型2, 3,4 只出现在视频流符合数据分区被允许的profile情况下,不会出现在符合MAIN/Baseline profile的流中)     

 Table 2.  编码片和主编码参考图像数据分区的编码片的NRI值的例子

      NAL Unit Type     Content of NAL unit              NRI (binary)       ----------------------------------------------------------------        1              non-IDR coded slice                           10        2              Coded slice data partition A                10        3              Coded slice data partition B                01        4              Coded slice data partition C                01

         (注释: 非参考图像NRI值是00)

      H.264编码器应该设置冗余编码参考图像的编码片和编码片分区NAL单元的NRI值为01 (二进制格式);对于NAL单元类型24~29的NRI的定义在下面第二个图给出;对于nal_unit_type范围在13到23的NAL单元的NRI值没有推荐的值,因为这些值保留给ITU-T,ISO/IEC. 对于nal_unit_type为0或30,31的NAL单元的NRI值也没有推荐的值,因为这些值的语义本文没有指定。

技术分享

Type: 5 个比特.         nal_unit_type. 这个 NALU 单元的类型. 简述如下:

  0     没有定义   1-23  NAL单元  单个 NAL 单元包.   24    STAP-A   单一时间的组合包   25    STAP-B   单一时间的组合包   26    MTAP16   多个时间的组合包   27    MTAP24   多个时间的组合包   28    FU-A     分片的单元   29    FU-B     分片的单元   30-31 没有定义

技术分享

(C表示重要性)

2. 打包模式

         下面是 RFC 3550 中规定的 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
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |V=2|P|X|  CC   |M|     PT      |       sequence number         |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |                           timestamp                           |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      |           synchronization source (SSRC) identifier            |
      +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
      |            contributing source (CSRC) identifiers             |
      |                             ....                              |
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

  负载类型 Payload type (PT): 7 bits   序列号 Sequence number (SN): 16 bits   时间戳 Timestamp: 32 bits   H.264 Payload 格式定义了三种不同的基本的负载(Payload)结构. 接收端可能通过 RTP Payload   的第一个字节来识别它们. 这一个字节类似 NALU 头的格式, 而这个头结构的 NAL 单元类型字段   则指出了代表的是哪一种结构,

  这个字节的结构如下, 可以看出它和 H.264 的 NALU 头结构是一样的.

       +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |F|NRI|  Type   |
      +---------------+

字段 Type: 这个 是RTP payload 中 NAL 单元的类型. 这个字段和 H.264 中类型字段的区别是, 当 type   的值为 24 ~ 31 表示这是一个特别格式的 NAL 单元, 而 H.264 中, 只取 1~23 是有效的值.

  可能的结构类型分别有:

  1. 单一 NAL 单元模式         即一个 RTP 包仅由一个完整的 NALU 组成. 这种情况下 RTP NAL 头类型字段和原始的 H.264的   NALU 头类型字段是一样的.

  2. 组合封包模式        即可能是由多个 NAL 单元组成一个 RTP 包. 分别有4种组合方式: STAP-A, STAP-B, MTAP16, MTAP24.   那么这里的类型值分别是 24, 25, 26 以及 27.

  3. 分片封包模式       用于把一个 NALU 单元封装成多个 RTP 包. 存在两种类型 FU-A 和 FU-B. 类型值分别是 28 和 29.

2.1 单一 NAL 单元模式

      对于 NALU 的长度小于 MTU 大小的包, 一般采用单一 NAL 单元模式。

  对于一个原始的 H.264 NALU 单元常由 [Start Code] [NALU Header] [NALU Payload] 三部分组成, 其中 Start Code 用于标示这是一个

  NALU 单元的开始, 必须是 "00 00 00 01" 或 "00 00 01", NALU 头仅一个字节, 其后都是 NALU 单元内容.   打包时去除 "00 00 01" 或 "00 00 00 01" 的开始码, 把其他数据封包的 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        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Figure 1.  RTP payload format for single NAL unit packet
 这种一般适用于NAL包小于1460字节的情况,但不能太小,太小就需要合包,后面讨论;单个NAL单元包的rtp payload如上;
 也就是说,直接将NAL头部和NAL数据放到rtp payload的位置就行,因为此时的rtp payload的头部和NAL头部是一样的,所以只需要用其中一个;

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

  [00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]

  这是一个序列参数集 NAL 单元. [00 00 00 01] 是四个字节的开始码, 67 是 NALU 头, 42 开始的数据是 NALU 内容.

  封装成 RTP 包将如下:

  [ RTP Header ] [ 67 42 A0 1E 23 56 0E 2F ]

  即只要去掉 4 个字节的开始码就可以了.

2.2 组合封包模式

        其次, 当 NALU 的长度特别小时, 可以把几个 NALU 单元封在一个 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
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                          RTP Header                           |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |STAP-A NAL HDR |         NALU 1 Size           | NALU 1 HDR    |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                         NALU 1 Data                           |
    :                                                               :
    +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |               | NALU 2 Size                   | NALU 2 HDR    |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                         NALU 2 Data                           |
    :                                                               :
    |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                               :...OPTIONAL RTP padding        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 Figure 2.  An example of an RTP packet including an STAP-A
               containing two single-time aggregation units

这种一般是用于多个小的NAL包封装成一个大的NAL包,当然不超过1460字节;这种情况的rtp payload结构大致如上。

Note:

HDR=header 表示头部;

STAP-A NAL HDR其实就是rtp payload的头部的一个字节,值应该是00011000b(STAP-A类型=24,二进制即11000);

NALU size 占用两个字节;NALU 头部一个字节;注意,数据部分不是按32字节对齐的,同时NALU size不包含自身的2个字节;

 

 

2.3 Fragmentation Units (FUs).

 而当 NALU 的长度超过 MTU 时, 就必须对 NALU 单元进行分片封包. 也称为 Fragmentation Units (FUs).       

     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        |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

   Figure 3.  RTP payload format for FU-A

一个NAL包拆分成多个NAL包,这种一般是一个NAL包超过了1460字节的情况,这种情况的payload结构如上。

NOTE:

其中的FU indicator对应rtp payload的头部,此处应该是0x00011100b(FU-A=28,二进制表示即11100) ;

FU indicator定义如下:

        +---------------+
       |0|1|2|3|4|5|6|7|
       +-+-+-+-+-+-+-+-+
       |F|NRI|  Type   |
       +---------------+

FU header定义如下:

        +---------------+
      |0|1|2|3|4|5|6|7|
      +-+-+-+-+-+-+-+-+
      |S|E|R|  Type   |
      +---------------+

对于分片的第一个包,设置S为1;对于分片的最后一个包,设置E为1,R设置为0即可;Type字段对应的是NALU头部中的TYPE,可以用于区分帧类型;

注意,FU payload中并没有传送NALU的头部,NALU的头部由FU indicator(前3位)和FU header(后五位)组成:nal_unit_type = (fu_indicator & 0xe0) | (fu_header & 0x1f);

 

Technorati 标签: ,,,

 

 

 

参考文章:

http://blog.csdn.net/heanyu/article/details/6109957(NRI描述参考)

http://www.cnblogs.com/frkang/p/3352251.html(RTP封包描述较清晰)

https://tools.ietf.org/html/rfc6184(标准,RTP Payload Format for H.264 Video)

http://m.blog.csdn.net/blog/yangguangmeng/25562921(I、P、B帧、SPS、PPS判断)

http://blog.csdn.net/ljzcom/article/details/9834405(杂)

http://www.360doc.com/content/13/0124/08/9008018_262076786.shtml(杂)

http://blog.csdn.net/jwybobo2007/article/details/7054140(组合封包例子貌似有错,STAP-A头不是78应该是24)

http://www.cnblogs.com/likwo/p/3533392.html(实践中需要注意的地方)

http://blog.sina.com.cn/s/blog_3f0f1d3701013mta.html(实例分析H264 RTP payload)

H264 NAL RTP打包

标签:

原文地址:http://www.cnblogs.com/kimiway/p/4427310.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!