• H264 NAL RTP打包


    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)

  • 相关阅读:
    BZOJ 2957: 楼房重建
    那些年犯下的逗比错误
    BZOJ 2165: 大楼
    BZOJ 2115: [Wc2011] Xor
    bzoj 2006 [NOI2010]超级钢琴——ST表+堆
    bzoj 4571 [Scoi2016]美味——主席树
    bzoj 1014 [JSOI2008]火星人prefix——splay+哈希
    bzoj 2962 序列操作——线段树(卷积?)
    CF 809D Hitchhiking in the Baltic States——splay+dp
    bzoj 3489 A simple rmq problem——主席树套线段树
  • 原文地址:https://www.cnblogs.com/kimiway/p/4427310.html
Copyright © 2020-2023  润新知