RTP Header
RTP协议中,RTP Header(报头)包括固定报头(Fixed Header)与报头扩展(Header extension,可选)。
RTP Fixed Header结构如下,其中前12字节是每个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 |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
但是这Fixed Header携带的信息满足不了更复杂的需求。所以引入了RTP Header Extension,可以携带更多的信息。
RTP Header Extension
如果RTP Fixed Header中,X字段为1,说明后面跟着RTP Header Extension。RTP Header Extension结构如下:
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 |
| .... |
defined by profile:决定使用哪种Header Extension:one-byte或者two-byte header
length:表示Header Extension的长度:length x 4字节
One-Byte Header
对于One-Byte Header,"defined by profile"字段为固定的0xBEDE。接着后面的结构如下:
0
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
| ID | len |
+-+-+-+-+-+-+-+-+
ID:4-bit长度的ID表示本地标识符
len:表示extension data长度,范围:0~15,为0表示长度为1字节,15表示16字节
如下是一个One-Byte Header的示例:
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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
首先是0xBEDE固定字段开头,接着length长度为3,说明后面跟着3x4字节长度的header extension 。对于第一个header extension:L=0,表示data长度为1字节。对于第二个header extension:L=1,表示data长度为2字节。由于按4字节对齐,所以接着是值为0的填充数据。最后一个header extension:L=3,表示data长度为4字节。
WireShark抓包分析
如下是WireShark抓包WebRTC视频流解析的一个RTP包结构:
Defined by profile字段为0xBEDE,表示One-Byte Header,Extension length为1,表示Header Extension长度为1x4字节,对于Header Extension:ID为3,Lengh为2。
相关代码Review
构造相关代码位于RtpPacket::AllocateRawExtension中
解析相关代码位于RtpPacket::ParseBuffer中
大家可以对着WebRTC相关代码熟悉下协议。
Two-Byte Header
"defined by profile"字段结构如下:
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x100 |appbits|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
接着后面跟着的每个扩展元素结构如下:
0 1
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| ID | length |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
ID:本地标识符
length:表示extension data长度,范围1~255
如下是一个Two-Byte Header示例:
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 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
首先"defined by profile"字段为0x1000,length为3,后面跟着3x4字节长度扩展,对于第一个header extension:L=0,数据长度为0,对于第二个header extension:L=1,data长度为1,接着是填充数据,对于第三个header extension:L=4,后面跟着4字节长度数据。
由于WebRTC中默认都是One-Byte Header,所以就不抓包分析了,具体构造解析代码跟One-Byte Header位于同一地方。
常见RTP Header Extension
在WebRTC中定义了很多RTP Header Extension,最常见的要数用于带宽估计的Transport-CC扩展, 记录一个传输层的序列号:TransportSequenceNumber,默认每个RTP包都带有此扩展。
当然还有记录音量的AudioLevel扩展,记录发送时间的AbsoluteSendTime扩展等等。
看下目前WebRTC支持的几种Header Extension:
enum RTPExtensionType : int {
kRtpExtensionNone,
kRtpExtensionTransmissionTimeOffset,
kRtpExtensionAudioLevel,
kRtpExtensionInbandComfortNoise,
kRtpExtensionAbsoluteSendTime,
kRtpExtensionAbsoluteCaptureTime,
kRtpExtensionVideoRotation,
kRtpExtensionTransportSequenceNumber,
kRtpExtensionTransportSequenceNumber02,
kRtpExtensionPlayoutDelay,
kRtpExtensionVideoContentType,
kRtpExtensionVideoLayersAllocation,
kRtpExtensionVideoTiming,
kRtpExtensionRtpStreamId,
kRtpExtensionRepairedRtpStreamId,
kRtpExtensionMid,
kRtpExtensionGenericFrameDescriptor00,
kRtpExtensionGenericFrameDescriptor = kRtpExtensionGenericFrameDescriptor00,
kRtpExtensionGenericFrameDescriptor02,
kRtpExtensionColorSpace,
kRtpExtensionVideoFrameTrackingId,
kRtpExtensionNumberOfExtensions
};
SDP
如下是某个示例SDP内容:
m=video 9 UDP/TLS/RTP/SAVPF 127 97 98 99 100 101 125 121 124 120 123
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:XQ5X
a=ice-pwd:ROZxiR4lwF7PvysKHFDcEYdq
a=ice-options:trickle
a=fingerprint:sha-256 FE:D2:E8:F9:2B:CD:7C:03:12:2E:91:40:E4:F2:D1:32:79:76:98:5D:36:4F:3A:9F:47:BD:15:23:36:80:F4:89
a=setup:actpass
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:13 urn:3gpp:video-orientation
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendrecv
a=msid:stream_id video_label
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:127 VP8/90000
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
SDP中,a=extmap开头即为RTP Header Extension。
对于RFC中定义的RTP Header Extension,SDP格式如下:
a=extmap:
对于WebRTC中自定义的RTP Header Extension,SDP格式如下:
a=extmap: