SDP协议
SDP协议版本
sdp协议最新链接:rfc8866
历史版本:rfc4566
rfc2327
| 特性 |
RFC 2327 (1998) |
RFC 4566 (2006) |
RFC 8866 (2021) |
| IP 支持 |
仅 IPv4 |
IPv4 + IPv6 |
IPv4 + IPv6 |
| 安全机制 |
无 |
基础(如 k=) |
完善(DTLS-SRTP 等) |
| ICE 支持 |
无 |
初步属性支持 |
完整规范 |
| 扩展性 |
有限 |
新增属性字段 |
明确的扩展规则 |
| 应用场景 |
传统 VoIP |
WebRTC 早期 |
现代 WebRTC/5G |
本次以rfc8866为例学习
sdp 参数解析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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 descriptions)
b=* (zero or more bandwidth information lines)
One or more time descriptions:
("t=", "r=" and "z=" lines; see below)
k=* (obsolete)
a=* (zero or more session attribute lines)
Zero or more media descriptions
|
-
v=0 版本默认是0
-
o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
username: 用户登录的原始host,默认’-'
sess-id: 会话id,具备唯一性
sess-version: 会话版本,可和sess-id一致
nettype: 网络类型,默认为IN
addrtype: 地址类型,默认为IP4 or IP6
unicast-address: ip地址
s=<session name> 必须填写,没有则为’s=’ or ’s=-'
i=<session information> 描述会话信息,可选
u=<uri> 描述会话uri, 可选
e=<email-address> p=<phone number>, 可选
c=<nettype> <addrtype> <connection-address> 连接信息,为’IN IP4 xxxx’, c可以有多个
b=<bwtype>:<bandwidth> 带宽信息,可选
k=<keytype> <key> 加密信息,可选
1
2
3
|
t= (time the session is active)
r=* (zero or more repeat times)
z=* (optional time zone offset line)
|
t=<start-time> <stop-time> 会话开始和结束时间戳,可多个,开始和结束时间都为0,会话视为永久
r=<repeat interval> <active duration> <offsets from start-time> 重复时间间隔和持续时间,可选
z=<adjustment time> <offset> <adjustment time> <offset> ... 时区偏移,可选
1
2
3
4
5
6
7
|
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=* (obsolete)
a=* (zero or more media attribute lines)
|
m=<media> <port>/<numers of ports> <proto> <fmt> ... 媒体描述,必选.
media: audio、video、text、application、message
port: 端口号,0-65535,0表示不指定端口, numbers of ports: rtp 会话数选择
proto: 传输协议,udp,RTP/AVP,RTP/SAVP,RTP/SAVPF
fmt: 媒体格式,如 0、8、9、97、98、99、101、102、103、104、105等
k=<method> k=<method>:<encryption key> 已过时,不要用
a=<aattribute-name> a=<attribute-name>:<aattribute-value> 扩展sdp信息,可多个
rtpmap: 媒体格式的描述, 要和m=里fmt格式一致
详细示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
v=0
o=jdoe 3724394400 3724394405 IN IP4 198.51.100.1
s=Call to John Smith
i=SDP Offer #1
u=http://www.jdoe.example.com/home.html
e=Jane Doe <jane@jdoe.example.com>
p=+1 617 555-6011
c=IN IP4 198.51.100.1
t=0 0
m=audio 49170 RTP/AVP 0
m=audio 49180 RTP/AVP 0
m=video 51372 RTP/AVP 99
c=IN IP6 2001:db8::2
a=rtpmap:99 h263-1998/90000
|
RTP协议
RTP协议连接
协议地址:rfc3550
老协议:rfc1889
RTP协议结构
1
2
3
4
5
6
7
8
9
10
11
12
|
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 |
| .... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
sequence number: 初始值随机不可预测生成,用于标识一个RTP包,每次发送+1
timestamp: 初始值随机时间戳,每次新增采样时钟,比如audio为160
SSRC: 初始值随机,多个源时会有概率冲突,如果一个源修改源地址,那么要使用新SSRC.
CSRC: 标识有效负载的贡献源
SSRC 生成算法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
#include <sys/types.h> /* u_long */
#include <sys/time.h> /* gettimeofday() */
#include <unistd.h> /* get..() */
#include <stdio.h> /* printf() */
#include <time.h> /* clock() */
#include <sys/utsname.h> /* uname() */
#include "global.h" /* from RFC 1321 */
#include "md5.h" /* from RFC 1321 */
#define MD_CTX MD5_CTX
#define MDInit MD5Init
#define MDUpdate MD5Update
#define MDFinal MD5Final
static u_long md_32(char *string, int length)
{
MD_CTX context;
union {
char c[16];
u_long x[4];
} digest;
u_long r;
int i;
MDInit (&context);
MDUpdate (&context, string, length);
MDFinal ((unsigned char *)&digest, &context);
r = 0;
for (i = 0; i < 3; i++) {
r ^= digest.x[i];
}
return r;
} /* md_32 */
/*
* Return random unsigned 32-bit quantity. Use 'type' argument if
* you need to generate several different values in close succession.
*/
u_int32 random32(int type)
{
struct {
int type;
struct timeval tv;
clock_t cpu;
pid_t pid;
u_long hid;
uid_t uid;
gid_t gid;
struct utsname name;
} s;
gettimeofday(&s.tv, 0);
uname(&s.name);
s.type = type;
s.cpu = clock();
s.pid = getpid();
s.hid = gethostid();
s.uid = getuid();
s.gid = getgid();
/* also: system uptime */
return md_32((char *)&s, sizeof(s));
} /* random32 */
|
在实际使用媒体服务中,有部分服务使用了SSRC来区分数据,
业务表现就是媒体服务只用一个端口来接收RTP数据(比如:jitsi-videobridge)。
好处: 当对接时,可以不需要开通太多端口区间。不足: 并发性能不高。
其余大部分的媒体服务都是使用多个端口来接收RTP数据(比如: rtpengine, rtpproxy, freeswitch)。