1 SDP 是什么
见名知意,SDP是session description protocol,会话描述协议。即SDP是一个描述一次会话的协议。一般SDP用于多媒体通信中,由于视频和音频数据的复杂性,不同编码类型的音视频流需要对应的专门的编解码器进行编解码操作,经过编解码器的处理后音视频方能够传输或者播放。而对应的编解码器的初始化必须要知道响应的音视频信息,故SDP一般用于音视频传输前通信双方交流音视频的属性,便于双方对接下来处理音视频流的工作进行必要的准备。
webrtc通过SDP协商,告知对端支持的音视频编码类型,编码器参数,音频或者视频的路数,以及与音视频相关的采样率,编码等等,双方根据各自的能力情况,协商出待传输音视频流的具体参数。
2 标准SDP规范
标准SDP规范主要包括SDP描述格式和SDP结构,而SDP结构由会话描述和媒体信息描述两个部分组成。媒体信息描述是整个SDP规范中最重要的部分,他主要包括媒体类型、媒体格式、传输协议、传输的IP和端口。
2.1 SDP的格式
SDP是由多个 <type>=<value>
这边的表达式组成的,其中<type>
是一个字符,<value>
是一个字符串。需要特别注意的是,“=”号两边是不能有空格的。
v=0
o=- 5910110687297165449 2 IN IP4 127.0.0.1
s=-
t=0 0
...
上面提到SDP由会话描述和媒体描述两部分组成,并且一个SDP中会话描述只能有一个,但是媒体描述可以有多个。
- 会话级(session level)的作用域是整个会话,即全部SDP。其位置从
v=
行开始,到m=
行之前结束。 - 媒体级(media level)的作用域是单个的媒体流描述,其位置从
m=
开始,到下一个m=
之前结束。
下面是一个简化的SDP样例:
v=0
o=- 5910110687297165449 2 IN IP4 127.0.0.1
s=-
t=0 0
...
//第一个媒体流,音频流
m=audio 54797 UDP/TLS/RTP/SAVPF 8
...
//第2个媒体流,视频流
m=video 9 UDP/TLS/RTP/SAVPF 125
...
//第3个媒体流, 数据通道
m=application 9 UDP/DTLS/SCTP webrtc-datachannel
...
2.2 SDP的结构
从上一节的介绍中,可以知道SDP是结构化布局的,先是会话级描述,然后紧跟媒体级描述。下面逐一介绍个字段的含义
- 会话级描述
这里以一个样例对SDP各字段的含义进行逐一讲解。
v=0
//v=<version> (必选)
//这里的v表示SDP的版本,即version的缩写,其值为SDP的版本号
//SDP版本号,一直为0,rfc4566规定
o=- 5910110687297165449 2 IN IP4 127.0.0.1
//o=<username> <session id> <version> <network type> <address type> <address>(必选)
//o=表示的是对会话发起者的描述, o是session owner的缩写
//<username> 用户名,当不关心用户名的时候,可以用 - 替代
//<session id> 此会话的标识符,一般使用NTP时间戳
//<version> 表示此会话的版本,会话建立后支持实时修改,此版本号就是一般用修改次数来表示
// <network type> 网络类型,一般用“IN”,表示Internet
//<address type> 地址类型,一般为 "IP4"
// <address> IP地址
//7017624586836067756是整个会话的编号,2表明会话版本,
//若是在会话过程当中有改变编码之类的操作,从新生成sdp时,sess-id不变,sess-version加1
s=-
//s=<session name>(必选)
//该行表示此会话的名称,不关心可以用 - 代替。
t=0 0
//t=<start time> <stop time>(必选)
//t代表 time the session is active
//t=0 0 表示此会话是一个永久会话,永不失效
a=group:BUNDLE 0 1 2
// a=<type> 或 a=<type>:<values>
//此行表示属性,用于进一步说明会话信息
//此例子表示将各媒体会话绑定起来创建一个组,用于传输。支持三种媒体流绑定传输
//a表示此行为 attribute line
//需要共用一个传输通道传输的媒体,若是没有这一行,音视频,数据就会分别单独用一个udp端口来发送
a=msid-semantic: WMS
//WMS是WebRTC Media Stream简称,这一行定义了本客户端支持同时传输多个流,
//一个流能够包括多个track,通常定义了这个,后面a=ssrc这一行就会有msid,mslabel等属性
- 媒体级描述
媒体描述的字段很多,这里着重介绍4个。
m=(media name and transport address, 可选)
// m=<media> <port> <stransport> <fmt list>, 表示一个媒体描述
//<media> 媒体类型,比如 audio/video等
//<port> 端口
//<transport> 传输协议,有两种RTP/AVP和UDP
//<fmt list> 媒体格式,即数据负载类型(payload type)列表
a=*(zero or more media attribute lines, 可选)
//表示属性,用于进一步描述媒体信息。
//a=有两个特别的属性类型,即下面要介绍rtpmap和fmtp
a=rtpmap:125 H264/90000
//rtpmap(可选)。
//a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encodingparameters>]
//rtpmap是rtp与map的结合,即RTP参数映射表。
//<payload type> 负载类型,对应RTP包中的音视频数据负载类型
//<encoding name> 编码器名称,如VP8、VP9、OPUS
//<sample rate> 采样率,如音频的采样率频率32000、48000等
//<encodingparameters> 编码参数,如音频是否是双声道,默认是单声道
a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
//a=fmtp:<payload type> <format specific parameters>
//fmtp 格式参数,即format parameters
//<payload type> 负载类型,同样对应RTP包中音视频数据负载类型
//( level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f) H264编码的可选附加参数
3 WebRTC中的SDP
webrtc对标准SDP规范做了一些调整,它将SDP按功能分成几大块:
- Session Metadata,会话元数据
- Network Description 网络描述
- Stream Description, 流描述
- Security Description,安全描述
- Qos Grouping Description,服务质量描述
//=============会话描述====================
v=0
o=- 7017624586836067756 2 IN IP4 127.0.0.1
s=-
t=0 0
...
//================媒体描述=================
//================音频媒体=================
/*
* 音频使用端口1024收发数据
* UDP/TLS/RTP/SAVPF 表示使用 dtls/srtp 协议对数据加密传输
* 111、103 ... 表示本会话音频数据的 Payload Type
*/
m=audio 1024 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126
//==============网络描述==================
//指明接收或者发送音频使用的IP地址,由于WebRTC使用ICE传输,这个被忽略。
c=IN IP4 0.0.0.0
//用来设置rtcp地址和端口,WebRTC不使用
a=rtcp:9 IN IP4 0.0.0.0
...
//==============音频安全描述================
//ICE协商过程中的安全验证信息
a=ice-ufrag:khLS
a=ice-pwd:cxLzteJaJBou3DspNaPsJhlQ
a=fingerprint:sha-256 FA:14:42:3B:C7:97:1B:E8:AE:0C2:71:03:05:05:16:8F:B9:C7:98:E9:60:43:4B:5B:2C:28:EE:5C:8F3:17
...
//==============音频流媒体描述================
a=rtpmap:111 opus/48000/2
//minptime代表最小打包时长是10ms,useinbandfec=1代表使用opus编码内置fec特性
a=fmtp:111 minptime=10;useinbandfec=1
...
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
...
//=================视频媒体=================
m=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116 117 96 97 99 98
...
//=================网络描述=================
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
...
//=================视频安全描述=================
//进入连通性检测的用户名
a=ice-ufrag:khLS
//密码,这两个是用于连通性检查的凭证
a=ice-pwd:cxLzteJaJBou3DspNaPsJhlQ
//DTLS指纹认证,以识别是否是合法用户
a=fingerprint:sha-256 FA:14:42:3B:C7:97:1B:E8:AE:0C2:71:03:05:05:16:8F:B9:C7:98:E9:60:43:4B:5B:2C:28:EE:5C:8F3:17
...
//================视频流描述===============
a=mid:video
...
a=rtpmap:100 VP8/90000
//================服务质量描述===============
a=rtcp-fb:100 ccm fir //解码出错,请求关键帧
a=rtcp-fb:100 nack //支持丢包重传,参考rfc4585
a=rtcp-fb:100 nack pli //与fir类似,
a=rtcp-fb:100 goog-remb //使用google的宽带评估算法
a=rtcp-fb:100 transport-cc //启动防拥塞
...
4 webrtc SDP样例
v=0
//sdp版本号,一直为0,rfc4566规定
o=- 7017624586836067756 2 IN IP4 127.0.0.1
//username如何没有使用-代替,7017624586836067756是整个会话的编号,2表明会话版本
s=-
//会话名,没有的话使用-代替
t=0 0
//两个值分别是会话的起始时间和结束时间,这里都是0表明没有限制
a=group:BUNDLE audio video data
//须要共用一个传输通道传输的媒体,若是没有这一行,音视频,数据就会分别单独用一个udp端口来发送
a=msid-semantic: WMS h1aZ20mbQB0GSsq0YxLfJmiYWE9CBfGch97C
//WMS是WebRTC Media Stream简称,这一行定义了本客户端支持同时传输多个流,一个流能够包括多个
//track,通常定义了这个,后面a=ssrc这一行就会有msid,mslabel等属性
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126
//m=audio说明本会话包含音频,9表明音频使用端口9来传输,在webrtc中通常不使用,
//若是设置为0,表明不传输音频,UDP/TLS/RTP/SAVPF是表示用户来传输音频支持的协议,
//udp、tls、rtp表明使用udp来传输rtp包,并使用tls加密;
//SAVPF表明使用srtcp的反馈机制来控制通讯过程,
//111 103 104 9 0 8 106 105 13 126表示本会话音频支持的编码,后台几行会有详细补充说明
c=IN IP4 0.0.0.0
//这一行表示你要用来接收或者发送音频使用的IP地址,webrtc使用ice传输,不使用这个地址
a=rtcp:9 IN IP4 0.0.0.0
//用来传输rtcp地地址和端口,webrtc中不使用
a=ice-ufrag:khLS
a=ice-pwd:cxLzteJaJBou3DspNaPsJhlQ
//以上两行是ice协商过程当中的安全验证信息
a=fingerprint:sha-256 FA:14:42:3B:C7:97:1B:E8:AE:0C2:71:03:05:05:16:8F:B9:C7:98:E9:60:43:4B:5B:2C:28:EE:5C:8F3:17
//以上这行是dtls协商过程当中须要的认证信息
a=setup:actpass
//以上这行表明本客户端在dtls协商过程当中,能够作客户端也能够作服务端,参考rfc4145 rfc4572
a=mid:audio
//在前面BUNDLE这一行中用到的媒体标识
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
//上一行指出我要在rtp头部中加入音量信息,参考 rfc6464
a=sendrecv
//上一行指出我是双向通讯,另外几种类型是recvonly,sendonly,inactive
a=rtcp-mux
//上一行指出rtp,rtcp包使用同一个端口来传输
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
//上面几行都是对m=audio这一行的媒体编码补充说明,指出了编码采用的编号,采样率,声道等
//以上这行说明opus编码支持使用rtcp来控制拥塞,参考https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=fmtp:111 minptime=10;useinbandfec=1
//对opus编码可选的补充说明,minptime表明最小打包时长是10ms,useinbandfec=1表明使用opus编码内置fec特性
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:126 telephone-event/8000
a=ssrc:18509423 cname:sTjtznXLCNH7nbRw
//cname用来标识一个数据源,ssrc当发生冲突时可能会发生变化,可是cname不会发生变化,也会出现在rtcp包中SDEC中,
//用于音视频同步
a=ssrc:18509423 msid:h1aZ20mbQB0GSsq0YxLfJmiYWE9CBfGch97C 15598a91-caf9-4fff-a28f-3082310b2b7a
//以上这一行定义了ssrc和WebRTC中的MediaStream,AudioTrack之间的关系,msid后面第一个属性是stream-d,第二个是track-id
a=ssrc:18509423 mslabel:h1aZ20mbQB0GSsq0YxLfJmiYWE9CBfGch97C
a=ssrc:18509423 label:15598a91-caf9-4fff-a28f-3082310b2b7a
m=video 9 UDP/TLS/RTP/SAVPF 100 101 107 116 117 96 97 99 98
//参考上面m=audio,含义相似
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:khLS
a=ice-pwd:cxLzteJaJBou3DspNaPsJhlQ
a=fingerprint:sha-256 FA:14:42:3B:C7:97:1B:E8:AE:0C2:71:03:05:05:16:8F:B9:C7:98:E9:60:43:4B:5B:2C:28:EE:5C:8F3:17
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-hol ... de-cc-extensions-01
a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=sendrecv
a=rtcp-mux
a=rtcp-rsize
a=rtpmap:100 VP8/90000
a=rtcp-fb:100 ccm fir
//ccm是codec control using RTCP feedback message简称,意思是支持使用rtcp反馈机制来实现编码控制,
//fir是Full Intra Request简称,意思是接收方通知发送方发送帧过来
a=rtcp-fb:100 nack
//支持丢包重传,参考rfc4585
a=rtcp-fb:100 nack pli
//支持关键帧丢包重传,参考rfc4585
a=rtcp-fb:100 goog-remb
//支持使用rtcp包来控制发送方的码流
a=rtcp-fb:100 transport-cc
//参考上面opus
a=rtpmap:101 VP9/90000
a=rtcp-fb:101 ccm fir
a=rtcp-fb:101 nack
a=rtcp-fb:101 nack pli
a=rtcp-fb:101 goog-remb
a=rtcp-fb:101 transport-cc
a=rtpmap:107 H264/90000
a=rtcp-fb:107 ccm fir
a=rtcp-fb:107 nack
a=rtcp-fb:107 nack pli
a=rtcp-fb:107 goog-remb
a=rtcp-fb:107 transport-cc
a=fmtp:107 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
//h264编码可选的附加说明
a=rtpmap:116 red/90000
//fec冗余编码,通常若是sdp中有这一行的话,rtp头部负载类型就是116,不然就是各编码原生负责类型
a=rtpmap:117 ulpfec/90000
//支持ULP FEC,参考rfc5109
a=rtpmap:96 rtx/90000
a=fmtp:96 apt=100
//以上两行是VP8编码的重传包rtp类型
a=rtpmap:97 rtx/90000
a=fmtp:97 apt=101
a=rtpmap:99 rtx/90000
a=fmtp:99 apt=107
a=rtpmap:98 rtx/90000
a=fmtp:98 apt=116
a=ssrc-group:FID 3463951252 1461041037
//在webrtc中,重传包和正常包ssrc是不一样的,上一行中前一个是正常rtp包的ssrc,后一个是重传包的ssrc
a=ssrc:3463951252 cname:sTjtznXLCNH7nbRw
a=ssrc:3463951252 msid:h1aZ20mbQB0GSsq0YxLfJmiYWE9CBfGch97C ead4b4e9-b650-4ed5-86f8-6f5f5806346d
a=ssrc:3463951252 mslabel:h1aZ20mbQB0GSsq0YxLfJmiYWE9CBfGch97C
a=ssrc:3463951252 label:ead4b4e9-b650-4ed5-86f8-6f5f5806346d
a=ssrc:1461041037 cname:sTjtznXLCNH7nbRw
a=ssrc:1461041037 msid:h1aZ20mbQB0GSsq0YxLfJmiYWE9CBfGch97C ead4b4e9-b650-4ed5-86f8-6f5f5806346d
a=ssrc:1461041037 mslabel:h1aZ20mbQB0GSsq0YxLfJmiYWE9CBfGch97C
a=ssrc:1461041037 label:ead4b4e9-b650-4ed5-86f8-6f5f5806346d
m=application 9 DTLS/SCTP 5000
c=IN IP4 0.0.0.0
a=ice-ufrag:khLS
a=ice-pwd:cxLzteJaJBou3DspNaPsJhlQ
a=fingerprint:sha-256 FA:14:42:3B:C7:97:1B:E8:AE:0C2:71:03:05:05:16:8F:B9:C7:98:E9:60:43:4B:5B:2C:28:EE:5C:8F3:17
a=setup:actpass
a=mid:data
a=sctpmap:5000 webrtc-datachannel 1024