RTP协议解析学习

RTP协议解析学习

目录

编辑信息

作者:chemoontheshy

创建时间:2021/09/17

完成时间:2021/09/17

说明

主要说明是RTP头的解析,阅读RFC3550后的一些注意的点。

RTP Packet

packet组成:

  • RTP Header(下面说明)
  • RTP payload

在RTP报文中的有效荷载,例如音频采样或者压缩的视频数据。(RFC3550定义可以为空。)

RTP Header

1. 结构

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

说明,我猜大概RTP协议,是基于32位的机器开发的标准,每个行以32位bit,位一行,刚好填满32位机器的处理数据的标准位。

2. 每个字段的含义

  • V(version): 2-bit

    • RTP版本标识。(现在基本默认为2)
  • P(padding): 1-bit

    • 如果设置padding,在报文的末端就会包含一个或多个padding字节,这个不属于payload,最后一个字节的padding有一个计数器,标识需要忽略多少个padding字节(包括字节)。一些加密算法可能需要固定块的长度的padding,或者是为了在更底层数据单位中携带一些RTP报文。(如非特殊,不要使用,暂时没有验证)
  • X(extension): 1-bit

    • 如果设定extension位,定长头字段后面会有一个头拓展,这个头拓展(RTPExtensionHeader)
    • defined by profile : 头扩展的前 16-bit 位是用来鉴别 identifier 或是参数的。故又可以直接当成 identifier 用。
    • lenght : 头扩展中包含一个 16-bit 的长度域用来 对扩展中的 32-bit 字个数计数,把 four-octet 的头扩展(有效长度是零)排出 在外。注意这里计数,是按 32-bit 字来计算,比如拓展字段数据是10字节,那计算就是3,故为了,不浪费位置,拓展字段最好能以32-bit (4字节)倍增。
    • 所以当X=1的时候:RTPPacket=RTPHeader+RTPExtensionHeader+EXTPayLoad+PayLoad
//计算 lenght
countExtLength(size_t length)
 {
 
     size_t ex_count;
     ex_count = length / 4;
     if (length % 4) ex_count += 1;
     return ex_count;
//RTPExtensionHeader
  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
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |         defined by profile         |             length             |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                     header extension                             |
  |                             ....                                | 
  • CC (CSRC count) : 4-bit

    • 范围:0-15 。
    • CSRC count 标识了定长头子字段中包含的 CSRC identifier 的数量。
  • M(mark): 1-bit

    • 用来允许标识在像报文流中界定帧界等的事件。
    • 根据其他RFC文档,主要用于标识一帧的结束
    • 在实测过程中,只有分包的时候,结束帧才有,其他帧貌似没有。(需要查看不同的RTP流才能确定)
  • PT( payload type) : 7-bit

    • 负载格式,目前只传送视频流,H264 的 PT=96,96之前是有明文规定的,参考 RFC3551
  • sequence number: 16-bit

    • 每发送一个 RTP 数据报文序列号值加一,接收者也可用来检测丢失的包或者重建报文序列。
    • 初始的值是随机的。
    • 会有回绕机制(部分资料表明当 sequence number达到最高65535时,会回到0)在其他标准文档里,
  • timestamp: 32-bit

    • timestamp 反映的是 RTP 数据报文中的第一个字段的采样时刻的时间瞬时值。
    • timestamp 初始值是随机的。
    • 根据 RFC3984 Timestamp: 32 bits

      • The RTP timestamp is set to the sampling timestamp of the content.A 90 kHz clock rate MUST be used.
      • 即:当负载数据为 H264 时, RTP 时戳设置为内容的采样时戳。必须使用90 kHz 时钟频率。
      • 根据帧数的不同来设置
  • SSRC: 32-bit

    • SSRC 域识别同步源。为了防止在一个会话中有相同的同步源有相同的 SSRC identifier, 这个 identifier 必须随机选取。
    • 所有的 RTP implementation 必须检测和解决冲突。
    • 如果有源改变了它的源传输地址,就必须为它选择一个新的 SSRC identifier 来避免被识别为循环过的源。
    • 实际应用:如果只有单一的RTP 会话传输。只需要以当时时间戳当不同源即可。
  • CSRC list: 0 to 15 items, 32-bits each

    • CSRC 最多16个,序号0-15,每个 CSRC 标识符占 32-bit 即4字节。
    • CSRCSSRC 的区别在于 SSRC 是区别于不同的 RTP 源CSRC 是同一个RTP 源,不同的来源。
    • 此字段暂时没有实验过,在一般用户都默认此字段不使用。默认 RTP Header 只有12个字节。故这里由于不太了解,也不展开描述。

3. 在 C++ 里,RTPHeader 和 RTPExtensionHeader 的结构体。

  • 根据 JRTPLIB 源码

    namespace jrtplib
    {
    
    struct RTPHeader
    {
    #ifdef RTP_BIG_ENDIAN
     uint8_t version:2;
     uint8_t padding:1;
     uint8_t extension:1;
     uint8_t csrccount:4;
     
     uint8_t marker:1;
     uint8_t payloadtype:7;
    #else // little endian
     uint8_t csrccount:4;
     uint8_t extension:1;
     uint8_t padding:1;
     uint8_t version:2;
     
     uint8_t payloadtype:7;
     uint8_t marker:1;
    #endif // RTP_BIG_ENDIAN
     
     uint16_t sequencenumber;
     uint32_t timestamp;
     uint32_t ssrc;
    };
    
    struct RTPExtensionHeader
    {
     uint16_t extid;
     uint16_t length;
    };
    }
  • 注意:根据小端大端的不同的,可能顺序,不同,RTP头的填充没有跨字节,所以按标准修改即可。

参考:

tag(s): RTP
show comments · back · home
Edit with Markdown