H264的RTP载荷格式

时间:2019-12-11
本文章向大家介绍H264的RTP载荷格式,主要包括H264的RTP载荷格式使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

H264中对于数据的存储分为两层,分别是

  • VCL: video coding layer 视频编码层
    这是h264中block, macro block 以及 slice级别的定义,目的是为了独立网络传输,进行高效的编解码

  • NAL: network abstraction layer 网络提取层
    NAL层的不同是为了根据不同的网络把VCL数据进行打包成不同的格式,进行传输

NAL

H264中的数据分组有头部(譬如: pkt->data),解码器可以很方便的检测到NAL的分界,依次去除NAL进行解码,但为了节省码流,NAL没有在数据头部设立特定元素,如果编码数据存储在介质上,NAL依次紧密相连(这时就无法通过对象取读取一个nal数据了),就无法区分出不同的nal单元,为了解决该问题,存储的时候会在每一个nal前添加0x000001或0x000000。
但数据内部也可能出现0x000001或0x000000,为此nal中规定不能出现0x000001或0x000000,源数据需要进行如下变换:
原数据 | 替换数据
-|-|
0X000000 | 0X00000300 |
0X000001 | 0X00000301 |
0X000002 |0X00000302 |
0X000003 | 0X00000303 |

在网络传输过程中, NAL中的数据被分成NALU(nal unit)单元,然后由RTP进行封装传输

如上图所示,VCL的数据经过上图所示

  • 在SODB的后面添加了结尾若干比特"0",以用字节对齐成了RBSP
  • 在RBSP的基础上,对数据进行循环检测替换上述的0x000000 ~ 0x000002,避免nal单元边界被破坏,成了EBSP
  • 在EBSP上添加一个字节的header后成了 NALU,

NALU

上述EBSP添加的一个字节的header的结构如下所示:

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

F:0表示payload 内容没有错误,1表示payload中的内容可能有错误内容或语法错误。
NRI:用来表示当前NALU单元的重要性(从00 ~11),00最低,表示这不是一个用于帧间预测的参考帧,可以丢弃。
Type:表示当前NALU的类型,这些类型如下表所示


      Table 1.  Summary of NAL unit types and the corresponding packet
                types
 
      NAL Unit  Packet    Packet Type Name               Section
      Type      Type
      -------------------------------------------------------------
      0        reserved                                     -
      1-23     NAL unit  Single NAL unit packet             5.6
      24       STAP-A    Single-time aggregation packet     5.7.1
      25       STAP-B    Single-time aggregation packet     5.7.1
      26       MTAP16    Multi-time aggregation packet      5.7.2
      27       MTAP24    Multi-time aggregation packet      5.7.2
      28       FU-A      Fragmentation unit                 5.8
      29       FU-B      Fragmentation unit                 5.8
      30-31    reserved 

再具体一点如下所示:

nal_unit_type   NAL类型
1   非IDR图像中不采用数据划分的片段
2   非IDR图像中A类数据划分片段
3   非IDR图像中B类数据划分片段
4   非IDR图像中C类数据划分片段
5   IDR图像的片
6   补充增强信息单元(SEI)
7   序列参数集
8   图像参数集
9   分界符
10  序列结束
11  码流结束
12  填充
13…23   保留
24…31   不保留(RTP打包时会用到)

比较重要的是
nal_unit_type = 7 RTP 负载的是序列参数集
nal_unit_type = 8 RTP 负载的是图像参数集
nal_unit_type = 5 IDR图像的片 (立即刷新图像,I帧给P帧和B帧作为参考)
23之前说明nalu中的数据类型,而超过23的时候RTP打包开始用到,决定NALU 如何打包进 RTP。因为NALU 大小有可能远远小于RTP payload,也有可能正好等于RTP payload,或者远大于RTP payload ,那么NALU 就需要再次拆分包,即一帧拆开发送,拆开发送时,rtp的markbit就可以用上来判断当前这个单元是否为一帧的结束,nalu被拆分的时候,timestamp是不变的

 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             |
|                             ....                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|NRI|  type   |                                               |
+-+-+-+-+-+-+-+-+                                               |
|                                                               |
|               Bytes 2..n of a Single NAL unit                 |
|                                                               |
|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               :...OPTIONAL RTP padding        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

聚合包 nal_unit_type = 24~27
本类型用于聚合多个NAL单元到单个RTP荷载中。本包有四种版本,单时间聚合包类型A (STAP-A),单时间聚合包类型B (STAP-B),多时间聚合包类型(MTAP)16位位移(MTAP16), 多时间聚合包类型(MTAP)24位位移(MTAP24)。赋予STAP-A, STAP-B, MTAP16, MTAP24的NAL单元类型号分别是 24,25, 26, 27;
下图的单时间聚合包

     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 7.  An example of an RTP packet including an STAP-A
               containing two single-time aggregation units

分片单元 nal_unit_type = 28 或者 29
将NALU 单元拆分到多个RTP包中发送 典型的就是FU-A或者FU-B

     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 14.  RTP payload format for FU-A

其中FU indicator的格式如下

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

    S:1表示第一包
    E:1表示是最后一个包
    R:1表示中间
    Type:类型

RTP负载PS


H264还有另一种数据组织和传输方式, 如上图,其中:

  • ES流(Elementary Stream原始流),是音、视频信号经过编码器之后或数据信号的基本码流。只包含一种内容。每个ES都由若  干个存取单元(AU)组成,每个视频或音频AU都是由头部和编码数据两部分组成,1个AU相当于编码的1幅视频图像或1个  音频帧  也可以说,每个AU实际上是编码数据流的显示单元,即相当于解码的1幅视频图像或1个音频帧的取样。
  • PES(Paketized Elementary Stream)是ES经过打包后的码流,长度可变。视频一般一帧一个包,音频一般不超过64KB. 
  • PTS--(presentation time stamp)显示时间戳,表示显示单元出现在系统目标解码器(H.264、MJPEG等)的时间。
  • DTS--(Decoding Time Stamp)解码时间戳,表示将存取单元全部字节从解码缓存器移走的时间。
  • PTS和DTS打在PES包头内,是解决音视频同步,防止解码器输入缓存上溢或下溢的关键。每一个pes header都包含pts和dts,是相对SCR(系统参考)的时间戳,以90000为单位,系统时钟频率(H264采样频率)

    最后由rtp将ps包传输出去,RFC2250中建议96 表示PS 封装,建议97 为MPEG-4,建议98 为H264

REF

H264 NALunit
RTP包 NALU FU-A等之间的关系
WEBRTC 接收H264 RTP数据流小结
RTP PS PES ES H264协议学习

原文地址:https://www.cnblogs.com/ishen/p/12021043.html