一、RTP Header扩充
在RFC3550中, 一个通用的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 |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
其中X位如果为1,就表示CSRC后面还有一些额外的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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| defined by profile | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| header extension |
| .... |
但是这种形式只能够附加一个扩展头,为了支持多个扩展头,RFC5285以defined by profile进行了扩展
One-Byte Header
扩展头为one-byte的情况下,一个例子如下:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0xBE | 0xDE | length =3 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID | L=0 | data | ID | L=1 | data...
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
...data | 0 (pad) | 0 (pad) | ID | L=3 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
RTP头后的第一个 16 为固定为 0XBEDE 标志,意味着这是一个 one-byte 扩展,length = 3 说明 header extension 的总长度为 3 * 32bit = 96bit = 12byte,每个扩展头首先以一个 byte 开始,前 4 位是这个扩展头的 ID, 后四位是 data 的长度 -1,譬如说 L=0 意味着后面有1个 byte 的 data,同理第二个扩展头的 L=1 说明后面还有 2 个 byte 的 data,但是注意,其后没有紧跟第三个扩展头,而是添加了 2 个byte大小的全 0 的 data,这是为了作填充对齐,因为扩展头是以为 32bit 作填充对齐的.
Two-Byte Header
扩展头为two-byte的情况下, RTP头后的第一个16 bit 如下所示, 一个0x100 + appbits, appbits 可以用来填充应用层级别的数据
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x100 |appbits|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
一个例子如下, 可以看到开头为 0x100 + 0x0, 接下来的为 length=3 表示接下来有 3 个 32bit 长度,接下来的就是扩展头和数据,扩展头除了 ID 和 L 相对于 one-byte header 从 4bits 变成了 8bits ,参考 rfc8285 4.3 节 two-byte 中 L 表示了真是的长度,不同于 one-byte 中需要进行 +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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x10 | 0x00 | length=3 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID | L=0 | ID | L=1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data | 0 (pad) | ID | L=4 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
二、WebRTC 支持的 RTP Header Extension 说明
① urn:ietf:params:rtp-hdrext:sdes:mid
MID: This is a media description identifier that matches the value of the SDP [RFC4566] a=mid attribute [RFC5888], to associate RTP streams multiplexed on the same transport with their respective SDP media description.
在 unified SDP 描述中 ‘a=mid’ 是每个 audio/video line 的必要元素,这个 header extension 将 SDP 中 ‘a=mid’ 后信息保存,用于标识一个 RTP packet 的 media 信息,可以作为一个 media 的唯一标识
② urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
在 RFC7656 中定义了两个概念 ‘Media Source’ 和 ‘RTP Stream’ 。其中:
1、Media Source 可以等同于 WebRTC 中 Track 的概念,在 SDP 描述中可以使用 mid 作为唯一标识;
2、RTP Stream 是 RTP 流传输的最小流单位,例如在 Simulcast 或 SVC 场景中,一个 Media Source 中包含多个 RTP Stream,这时的SDP中 使用 ‘a=rid’ 来描述每个 RTP Stream
③ urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
同 ②,用于声明重传时使用的 rid 标识。
④ http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
Wire format: 1-byte extension, 3 bytes of data. total 4 bytes extra per packet (plus shared 4 bytes for all extensions present: 2 byte magic word 0xBEDE, 2 byte # of extensions). Will in practice replace the “toffset” extension so we should see no long term increase in traffic as a result.
Encoding: Timestamp is in seconds, 24 bit 6.18 fixed point, yielding 64s wraparound and 3.8us resolution (one increment for each 477 bytes going out on a 1Gbps interface).
Relation to NTP timestamps: abs_send_time_24 = (ntp_timestamp_64 >> 14) & 0x00ffffff ; NTP timestamp is 32 bits for whole seconds, 32 bits fraction of second.
abs-send-time 为 一个 3 bytes 的时间数据。
mediasoup 中 将 毫秒转换为 abs-send-time 的方法为:
static uint32_t TimeMsToAbsSendTime(uint64_t ms)
{
return static_cast<uint32_t>(((ms << 18) + 500) / 1000) & 0x00FFFFFF;
}
GCC模块的 REMB 计算需要 RTP 报文扩展头部 abs-send-time 的支持,用以记录 RTP 数据包在发送端的绝对发送时间
⑤ http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
IETF成立了RMCAT(RTP Media Congestion Avoidance Techniques)工作组,制定在RTP协议之上的拥塞控制机制。
下图为 holmer-rmcat-transport-wide-cc-extensions 的数据组成:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0xBE | 0xDE | length=1 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID | L=1 |transport-wide sequence number | zero padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
可以看出,有效数据只有 16 bit,它记录了一个 sequence number,称为 transport-wide sequence number。
发送端在发送RTP数据包时,在RTP头部扩展中设置传输层序列号TransportSequenceNumber;数据包到达接收端后记录该序列号和包到达时间,然后接收端基于此构造TransportCC报文返回到发送端;发送端解析该报文,并执行Sendside-BWE算法,计算得到基于延迟的码率;最终Ar和基于丢包率的码率进行比较得到最终目标码率。
⑥ urn:ietf:params:rtp-hdrext:framemarking
WebRTC 中 RTP payload 部分通过 SRTP 进行加密,这样导致 RTP packet 在经过交换节点或转发节点时,有些场景下需要知道当前 RTP packet 的编码信息,例如传输优先级的优化,这时 urn:ietf:params:rtp-hdrext:framemarking 可以帮助转发或交换节点解决这个问题,因为 RTP header 部分在 SRTP 中不被加密。
不同的编码通常定义不同的标识信息,以 H.264 为例,数据结构定义为:
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID=2 | L=2 |S|E|I|D|B| TID |0|0|0|0|0|0|0|0| TL0PICIDX |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
⑦ urn:ietf:params:rtp-hdrext:ssrc-audio-level
结构比较简单,使用RFC6464定义的针对audio的扩展首部,用来调节音量,比如在大型会议中有多个音频流就可以用它来调整音频混流的策略
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID | len=0 |V| level |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
⑧ urn:3gpp:video-orientation
标记拍摄该视频流的摄像机的方向,可以是后置摄像头或前置摄像头;标记有无视频翻转操作
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID | len=0 |R0R1F C |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
⑨ urn:ietf:params:rtp-hdrext:toffset
传输时间偏移 (Transmission Time Offset),offset 为 RTP packet 中 timestamp 与 实际发送时间的偏移。一些前向编码 packet 所携带的 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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID | len=2 | transmission offset |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
三、参考标准
RFC 3550 - RTP: A Transport Protocol for Real-Time Applications
RFC 8285 - A General Mechanism for RTP Header Extensions
RFC 7941 - RTP Header Extension for the RTP Control Protocol (RTCP) Source Description Items
RFC 7656 - A Taxonomy of Semantics and Mechanisms for Real-Time Transport Protocol (RTP) Sources