SDP

协议汇总

webrtc依赖的服务有如下几种

  1. signaling信令服务器,交换房间和会议的媒体信息,以及会议期间的消息,媒体描述使用的是SDP协议
  2. ICE服务器,STUN和TURN,ICE的信息叫Candidate,可以通过SDP交换,或者通过Trickle
  3. SFU和MCU服务器

SDP协议:

1998-RFC2327

2006-RFC4566

例子(https://webrtchacks.com/sdp-anatomy/?spm=ata.13261165.0.0.41035c8c9sVCVD

SDP关键属性

  1. 会话级别描述
    1. v=
    2. o=
    3. s=
    4. t=
    5. b=
  2. 网络描述
    1. c=
    2. a=candidate
  3. 媒体描述
    1. m=
    2. a=rtpmap
    3. a=fmtp
    4. a=extmap
    5. a=sendrecv
    6. a=ssrc
  4. 安全描述
    1. a=crypto
    2. a=ice-ufrag
    3. a=ice-pwd
    4. a=fingerprint
  5. DTLS角色
    1. a=setup
  6. ICE策略
    1. a=ice-options:trickle
    2. a=ice-llte
    3. a=ice-option:renomination
  7. Qos, Grouping传输描述
    1. a=rtcp-fb
    2. a=group
    3. a=rtcp-mux

SDP是通过offer和answer来交互的

SDP的例子

type: offer, sdp: v=0
o=- 2397106153131073818 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE video
a=msid-semantic: WMS gLzQPGuagv3xXolwPiiGAULOwOLNItvl8LyS
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 123 127 122 125 107 108 109 124
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:l5KU
a=ice-pwd:+Sxmm3PoJUERpeHYL0HW4/T9
a=ice-options:trickle
a=fingerprint:sha-256 7C:93:85:40:01:07:91:BE:DA:64:A0:37:7E:61:CB:9D:91:9B:44:F6:C9:AC:3B:37:1C:00:15:4C:5A:B5:67:74
a=setup:actpass
a=mid:video
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 urn:3gpp:video-orientation
a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=sendrecv
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:100 H264/90000
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=fmtp:100 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtpmap:102 H264/90000
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 transport-cc
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:123 rtx/90000
a=fmtp:123 apt=102
a=rtpmap:127 H264/90000
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d0032
a=rtpmap:122 rtx/90000
a=fmtp:122 apt=127
a=rtpmap:125 H264/90000
a=rtcp-fb:125 goog-remb
a=rtcp-fb:125 transport-cc
a=rtcp-fb:125 ccm fir
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032
a=rtpmap:107 rtx/90000
a=fmtp:107 apt=125
a=rtpmap:108 red/90000
a=rtpmap:109 rtx/90000
a=fmtp:109 apt=108
a=rtpmap:124 ulpfec/90000
a=ssrc-group:FID 2527104241 4186960130
a=ssrc:2527104241 cname:JPmKBgFHH5YVFyaJ
a=ssrc:2527104241 msid:gLzQPGuagv3xXolwPiiGAULOwOLNItvl8LyS c7072509-df47-4828-ad03-7d0274585a56
a=ssrc:2527104241 mslabel:gLzQPGuagv3xXolwPiiGAULOwOLNItvl8LyS
a=ssrc:2527104241 label:c7072509-df47-4828-ad03-7d0274585a56
a=ssrc:4186960130 cname:JPmKBgFHH5YVFyaJ
a=ssrc:4186960130 msid:gLzQPGuagv3xXolwPiiGAULOwOLNItvl8LyS c7072509-df47-4828-ad03-7d0274585a56
a=ssrc:4186960130 mslabel:gLzQPGuagv3xXolwPiiGAULOwOLNItvl8LyS
a=ssrc:4186960130 label:c7072509-df47-4828-ad03-7d0274585a56
type: answer, sdp: v=0
o=- 5443219974135798586 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE video
a=msid-semantic: WMS uiZ7cB0hsFDRGgTIMNp6TajUK9dOoHi43HVs
m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 123 127 122 125 107 108 109 124
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:MUZf
a=ice-pwd:4QhikLcmGXnCfAzHDB++ZjM5
a=ice-options:trickle
a=fingerprint:sha-256 2A:5A:B8:43:66:05:B3:6A:E9:46:36:DF:DF:20:11:6A:F6:11:EA:D9:4E:26:E3:CE:5A:3A:C6:8D:03:49:7B:DE
a=setup:active
a=mid:video
a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:4 urn:3gpp:video-orientation
a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=sendrecv
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 goog-remb
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack
a=rtcp-fb:96 nack pli
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=96
a=rtpmap:98 VP9/90000
a=rtcp-fb:98 goog-remb
a=rtcp-fb:98 transport-cc
a=rtcp-fb:98 ccm fir
a=rtcp-fb:98 nack
a=rtcp-fb:98 nack pli
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=98
a=rtpmap:100 H264/90000
a=rtcp-fb:100 goog-remb
a=rtcp-fb:100 transport-cc
a=rtcp-fb:100 ccm fir
a=rtcp-fb:100 nack
a=rtcp-fb:100 nack pli
a=fmtp:100 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:101 rtx/90000
a=fmtp:101 apt=100
a=rtpmap:102 H264/90000
a=rtcp-fb:102 goog-remb
a=rtcp-fb:102 transport-cc
a=rtcp-fb:102 ccm fir
a=rtcp-fb:102 nack
a=rtcp-fb:102 nack pli
a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
a=rtpmap:123 rtx/90000
a=fmtp:123 apt=102
a=rtpmap:127 H264/90000
a=rtcp-fb:127 goog-remb
a=rtcp-fb:127 transport-cc
a=rtcp-fb:127 ccm fir
a=rtcp-fb:127 nack
a=rtcp-fb:127 nack pli
a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d0032
a=rtpmap:122 rtx/90000
a=fmtp:122 apt=127
a=rtpmap:125 H264/90000
a=rtcp-fb:125 goog-remb
a=rtcp-fb:125 transport-cc
a=rtcp-fb:125 ccm fir
a=rtcp-fb:125 nack
a=rtcp-fb:125 nack pli
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=640032
a=rtpmap:107 rtx/90000
a=fmtp:107 apt=125
a=rtpmap:108 red/90000
a=rtpmap:109 rtx/90000
a=fmtp:109 apt=108
a=rtpmap:124 ulpfec/90000
a=ssrc-group:FID 3587783331 4235118392
a=ssrc:3587783331 cname:INxZnBV2Sty1zlmN
a=ssrc:3587783331 msid:uiZ7cB0hsFDRGgTIMNp6TajUK9dOoHi43HVs a3b297e7-cdbe-464e-a32c-347465ace055
a=ssrc:3587783331 mslabel:uiZ7cB0hsFDRGgTIMNp6TajUK9dOoHi43HVs
a=ssrc:3587783331 label:a3b297e7-cdbe-464e-a32c-347465ace055
a=ssrc:4235118392 cname:INxZnBV2Sty1zlmN
a=ssrc:4235118392 msid:uiZ7cB0hsFDRGgTIMNp6TajUK9dOoHi43HVs a3b297e7-cdbe-464e-a32c-347465ace055
a=ssrc:4235118392 mslabel:uiZ7cB0hsFDRGgTIMNp6TajUK9dOoHi43HVs
a=ssrc:4235118392 label:a3b297e7-cdbe-464e-a32c-347465ace055

一般来说,推流方先发起offer,接收方给Answer。比如客户端推流到SFU,客户端发起Offer推流,SFU给客户端回Answer,客户端将流推到SFU,SFU再转发给其它客户端。Licode和Janus都是这种做法,这种方式下,如果客户端需要拉取其它的客户端的流,一般需要使用另外的PeerConnection,接收SFU的Offer,生成Answer后回应给SFU。

不过推流方发起Offer不是必须的,接收方也可以给Offer,推流方给Answer。比如MediaSoup这种SFU,客户端先给一个Offer给SFU,SFU只是检查这个Offer中的媒体特性,然后SFU会生成Offer(包含会议中的其它客户端的流,如果没有人则没有SSRC)给客户端,客户端发送Answer给SFU。这种方式的好处是其它客户端加入,以及流的变更(比如关闭视频打开视频时),都可以使用Reoffer,也就是统一由SFU发起新的Offer,客户端响应,SFU和客户端的交互模式只有一种。

SDP结构

SDP描述分为两部分,分别是会话级别的描述(session level)和媒体界别的描述(media level),其具体的组成可参考RFC4566

Session description
         v=  (protocol version)
         o=  (originator and session identifier)
         s=  (session name)
         i=* (session information)
         u=* (URI of description)
         e=* (email address)
         p=* (phone number)
         c=* (connection information -- not required if included in
              all media)
         b=* (zero or more bandwidth information lines)
         One or more time descriptions ("t=" and "r=" lines; see below)
         z=* (time zone adjustments)
         k=* (encryption key)
         a=* (zero or more session attribute lines)
         Zero or more media descriptions

      Time description
         t=  (time the session is active)
         r=* (zero or more repeat times)

      Media description, if present
         m=  (media name and transport address)
         i=* (media title)
         c=* (connection information -- optional if included at
              session level)
         b=* (zero or more bandwidth information lines)
         k=* (encryption key)
         a=* (zero or more media attribute lines)

SDP Line是顺序相关的,比如a=rtpmap:96后面的都是和它相关的设置,直到下一行是a=rtpmap或者其他属性。

会话级别的描述

会话级别的描述包括:v、o、s、c、b、t

v:版本号,固定为0

o:代表会话的发起者

s:会话的名称,每个SDP中有且仅有一个s描述,其值不能为空

c:携带了会话的连接信息,其实就是IP地址。SDP的会话级别描述可以包含该字段,每一个媒体级别的描述也可以包含该字段,如果会话级别和媒体级别都有c line,那么以媒体级别的c line为准,因为WebRTC使用ICE candidate交换地址信息,所以不会用到c line,不过这并不代表c line没有用,在SIP视频会议场景中,c line就必不可少,文末会再次介绍该字段。

b:表示会话或媒体使用的建议带宽。

t:制定了会话和结束时间,如果开始和结束时间都为0,那么意味着这次会话是永久的。

媒体级别描述

会话级别描述完成后,后面会跟着0个或多个媒体级别的描述。

m line的类型不只有audio和video,还有application、text等媒体类型

a=mid属性可以认为是每个M描述的唯一ID。比如a=mid:audio,那么audio这个字符串就是这个M描述的ID。有时候mid属性值也可以用数字表示,比如a=mid:0,那么就是这个M描述的ID。mid值一般和grouping传输属性的bundle策略结合来使用,比如a=group:BUNDLE audio video,代表本次会话将mid为audio和video的M描述进行复用传输。

m line的数字9代表媒体类型的传输端口,在RTC场景下都是使用ICE candidate的地址信息进行数据传输,所以m line的port没有用到。不过在sip的场景下是需要的

rtx代表重传

ssrc,一共有多少媒体流,通过ssrc指定。ssrc包含了需要发送的媒体流,另外offer和answer中都可以包含ssrc。比如客户端和mediaSoup通信时,mediaSoup总是给客户端发offer,mediaSoup的offer包含了MediaSoup要发送(转发其它客户端的流给客户端)的媒体流ssrc,同时客户端的answer中也包含了自己要推送的ssrc流,他们的类型都是sendrecv

PlanB and unifiedPlan

上面的SDP的例子,没有规定如何指定多条流。实际上audio和video都可有有多个ssrc,每个ssrc的编解码可能相同但也可能不相同。如果ssrc编解码不相同,那么将这些ssrc放在同一个M中描述就会有问题,这就是PlanB和unifiedPlan的关键所在。对于PlayB只能有一个M(audio)和M(video),如果有多个ssrc,他们的编解码也必须相同。unifiedPlan则可以多个M(audio)和M(video),每路流都有自己的M描述,这样就可以支持不同的编码。

PlanB和unifiedPlan其实就是WebRTC在多路媒体源场景下的两种不同的SDP协商方式。如果引入stream和track的概念,那么一个stream可能包含audio track和video track,当有多路stream时,就会有更多的track,如果每个track唯一对应一个自己的M描述,那么就是unifiedplan,如果每个M描述多个track,那么就是playB。

Candidate

candidate就是传输的候选人,客户端会生成多个candidate,比如有host类型的,relay类型的,有udp和tcp的。两端都会通过SDP交换自己的多个candidate,然后通过ICE connectivity check,形成candidate pair也就是传输通道了。

bundle and rtcp-mux

a=rtcp-mux

===

a=group:BUNDLE audio video
m=....
a=mid:audio

m=....
a=mid:video

rtcp-mux将rtp和rtcp复用到单一的端口进行传输,BUNDLE将多路媒体流复用到同一个端口进行传输,这可以简化nat协商。

rtcp-mux的sdp协商原则为:

  1. offer携带了rtcp-mux属性,如果answer端也希望复用rtp和rtcp,那么answer必须携带rtcp-mux
  2. 如果offer没携带rtcp-mux属性,那么answer也一定不能携带rtcp-mux属性
  3. rtcp-mux协商一定是双向的

rtcp-mux更详细协商细节参见rfc 8035,rtcp-mux场景下如何通过头部字段区分rtp和rtcp,参考rfc5761

ICE connectivity

m=xxx
a=ice-ufrag:kce9
a=ice-pwd:xxxxx
a=ice-options:trickle

ufrag和pwd就是ICE short-term认证算法用到的用户名和密码。而trickle说明SDP中没有包含candidate信息,candidate信息是通过信令单独交换的,这样可以做到connectivity checks和candidate harvesting并行处理,提高会话建立的速度。

DTLS

m=audio xxx
a=setup:actpass

m=video xxx
a=fingerprint:sha-256 B1:ff:......
a=setup:active

其中fingerprint是DTLS过程中的certificate证书的签名,防止客户端和服务器的证书被篡改。

另外,setup指的是DTLS的角色,active表示DTLS client,passive表示DTLS server,如果自己两个都是就是actpass。都是有client端发起DTLS clientHello开始DTLS过程。

Stream Direction

媒体流的方向包括,sendonly,recvonly,sendrecv,inactive。

  • sendonly表示仅发送,客户端推流到SFU,会在自己的offer或answer中携带sendonly
  • recvonly表示仅接收,客户端向SFU订阅流,会在自己的offer或answer中携带recvonly
  • sendrecv表示发送+接收,比如客户端加入视频会议,既要订阅别人也要发布自己的流
  • inactive表示禁止发送数据,比如在基于RTP的视频会议中,主持人暂时禁掉用户A的语音,那么用户A的关于音频的媒体级别描述应该携带inactive属性,表示不再发送音频数据

RTCP FeedBack

m=video 9 UDP/TLS/RTP/SAVPF 96
a=mid:video
a=rtpmap:96 VP8/90000
a=rtcp-fb:96 transport-cc
a=rtcp-fb:96 ccm fir
a=rtcp-fb:96 nack pli

rtcp-fb这个是媒体级别的SDP属性,它能告诉我们媒体会话能够对哪些RTCP消息进行反馈,是一个和QoS相关的重要的SDP属性,如上面SDP信息,这是一个视频M描述,VP8编码,payload type是96。最后3个rtcp-fb属性则说明关于96这个media codec来讲在网络拥塞控制方面的支持twcc;在ARQ方面支持nack处理,能够重传丢失的RTP包;在关键帧方面支持fir和pli处理,有能力进行关键帧的发送。

rtcp-fb不能用于会话级别的描述,只能用于媒体级别的描述,而且M描述的proto字段一定要指定AVPF。

存在这种格式a=rtcp-fb:* ccm fir,*是一个通配符,表示该M描述下的所有类型的media codec都支持fir的处理和关键帧的反馈。

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值