今天我们来讲解一些SDP的具体规范,上节我们在端到端视频传输的例子里面做了一些修改,来获取到offer和answer的SDP,通过那个例子那就对SDP有了一个感性的认识,那么我们再来看看具体的SDP的规范是什么样的,其实SDP的规范非常简单,它会将SDP分成两层,

第一层是会话层,会话层就相当于我们写程序时候的一个全局变量,我们写程序的时候有全局变量有局部变量,当局部变量没有设置的时候,那么我们这个全局变量在全局内都是有效的,我们在自己的函数里设置了局部变量,那么局部变量会覆盖全局变量,它也是这样一个层级关系,这个会话层就相当与全局变量的一些东西;

第二层是媒体层,媒体层就相当于我们自己 的一个个函数,或者按照SDP 的理解就是一个个媒体,比如一个音频流一个视频流,每一路视频每一路音频都是一个媒体层,那会话层是全局的,就是一旦设置了以后在全局内有效,在你媒体层没有设置自己的属性之前就可以使用全局层的。但是如果你设置了自己的 特殊的描述,那你就按照你这个媒体自己的描述,它就是这样一个简单的概念。

你可以把它想象成一棵树,那么树根就是会话层那么很多树干就是媒体层。

首先我们看看会话层都包括哪些内容

会话层

会话的名称与目的

会话的存活时间

会话中包括多个媒体信息

会话层包含了基本的名称和目的,另外一个还有个存活时间,这个会话时间作用稍微大些,如果设置了十分钟 ,那么会话就是十分钟,设置二十分钟就是二十分钟,对于我们音视频传输来说呢,一般我们都睡设置成0,表示无限期,表示会话一直存在,不会主动将它结束掉,这两个就是会话层。没有太多的重要信息。

那么重要的信息都包括在媒体层,也就是在一个会话层中,包含了多个媒体信息。

媒体信息 

媒体格式  媒体信息首先有媒体格式,是音频还是视频还是应用数据,

传输协议  是IPV4还是IPV6,TCP还是UDP

传输IP和端口 具体使用的Ip地址和端口,对于webrtc来说,端口和ip并不少SDP这里描述的,它会使用专门的ICE收集到的candidate里面的IP地址和端口,所以在媒体信息中的这个IP地址和端口价值并不是很大,但是对于其他的非webrtc使用SDP就比较有意义。

媒体负载类型  你是VP8还是VP9还是H264还是H265,这些都是媒体的负载类型,那基本上媒体信息就包括这些内容,也非常的简单。

那复杂是对于每一种媒体类型我们可以定义更多的属性,在这些属性里面我们可以给他更细的规范,所以现在你可以看到,其实整个SDP的这个规范并不复杂,非常简单。就是分成了两层,一层是会话层,一层是媒体层,这就是一个总纲性的SDP的规范。那其实还是比较好理解的。

下面我们来看看具体的格式

SDP格式

由多个<type>=<value>组成

SDP都是由多个类型和值组成的,另外一个是会话层只要一个会话层,每个SDP描述的都是一个会话,但是这个会话中是包含了多个媒体的描述信息,那么会话描述的具体内容我们看看

v = (protocol version) // 版本,一般是0,这里是说我们SDP使用的版本

o = (owner/create and session identifier) // 这个是创建的session的一个id标识

s = (session name) // session name可以不写,当不想写的时候写一个-,它就代表一个session name

c = *(conn info - optional if included at session-leve) // 连接相关的一些信息,我们整个会话的IP地址和端口号,以及这个地址类型是IPv4还是IPv6,还有这个网络类型,是互联网还是其他网络,这些都通过c可以设置,但这个其实在每个媒体中都会自己设置,所以会话层这个c意义也不大

a=*(zero or name session attribute lines) // 这个a代表设置一些全局的属性,这个其实 用处也不大,这个就是整个会话层的描述,所以大家对这个有一个基本的了解就可以了。

一提到v、o、s、c、a能够知道他们在会话层具体的含义是什么就够了。

在有就是时间,

Time Description

t = (time the session is active) // 表示存活的时间

r = *(zero or more repeat times) // 表示重复的次数

我们再来看媒体层

m = (media name  and transport address) // 媒体层就表示媒体的名字和传输地址

c = *(conn info - optional if included at session-leve)  // 媒体层也包括了传输相关的信息

b = *(bandwidth information) // 表示传输里的带宽信息是什么,多大 带宽可以设置

a = *(zero or name session attribute lines) // 还有一堆的属性,就是对m具体的解释,SDP复杂就在a的类型特别多,我们后期会对a作一个详细的介绍,对于整个媒体来说也非常简单,我们怎么来记忆,既然是媒体,它肯定和传输有关,传输要作一个限制,那么主要是对带宽的限制。那么另外的对这个媒体还有很大进一步的解释,通过这个a来解释

那么下面我们就来具体看看我们上面所讲的内体

字段含义(一)

Version必选

v=0 SDP的版本好,不包括次版本

Session Name必选

s = <session name> 会话名,s = - 表达忽略会话名

字段含义(二)

Origion/Owner必选

o = <username><session id><version><network type><address type><address>

例子: o=- 7017624586836067756 2 IN IP4 127.0.0.1

字段含义(三)

连接相关的包括

Connection Data可选

c=<network type><address type><connection address>

例子:c=IN IP4 0.0.0.0

字段含义(四)

媒体相关的比较重要

Media Announcements必选

m = <media><port><transport><fmt/payload type list> // 具体媒体类型、端口、传输地址、负载类型

例子:m=audio 1024  UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126

字段含义(五)

属性

Suggestted Attributes可选

a=<TYPE>或a=<TYPE>:<VALUES>

例子: a=framerate:<帧速率>

字段含义(六)

rtpmap可选

a=rtpmap:<fmt/payload type><encoding name>/<clock rate>[/<encodingparameters>]

rtpmap修饰的是payload type,对于不同的payload type,比如说vp8,它的这个编码名称、采样率是多少,包括一些编码的参数,都可以在这里设置

例子: a=rtpmap:103 ISAC/16000 // 就说明它的编解码器103对应的ISAC,使用频率是每秒钟采样16000次

字段含义(七)

fmtp也比较重要,这个是对rtpmap的参数作进一步的说明

fmtp可选

a=fmtp:<format/payload type> parameters

例子:a = fmtp:103 apt=106 // 比如它这里是103的ISAC,那它这个是需要关联的,它与106这个payload type进行关联,也就是103与106进行关联

那么以上就是SDP的一个大体的规范,从我们刚刚描述的规范来看,其实蛮简单的,就是它将整个描述分成两层,会话层和媒体层,会话层是全局唯一的,描述的一些基本信息,意义不大,最重要的是媒体层,媒体层中描述了媒体的类型是音频还是视频,那么你的传输相关的地址类型是IPV4还是IPV6还有端口以及payload类型也就是媒体都支持哪些编解码器,对于每一种编解码器可以作进一步指定,通过Attribute属性来指定,那么在属性里有两个重要的类型,一个是rtpmap,在这里可以定义payload和编解码器的对应关系以及它的采样率等基本信息。那如果还需要进一步说明的话,我们就可以利用Attribute的fmtp作进一步说明。

那么以上就是整个SDP的规范。