一、引言
会话描述协议(Session Description Protocol,简称SDP)描述了流媒体的初始化参数,包含音视频的编解码器、源地址和时间信息。SDP协议从不会被单独使用,而依赖于RTP和RTSP等协议。SDP也作为WebRTC的组件之一,用于描述一个会话。
二、SDP官方文档下载
SDP的官方文档为《RFC 4566》(该文档替换了《RFC 2327》与《RFC 3266》),可以从RFC官网下载:» RFC Editor
然后由于SDP依赖于RTP等协议,所以还需要下载《音视频入门基础:RTP专题(1)——RTP官方文档下载》中提供的RTP官方文档,比如《RFC 6184》。
《RFC 4566》总共有49页。本文下面所说的“页数”是指在pdf阅读器中显示的页数:
三、SDP的格式
根据《RFC 4566》第8页,一个SDP会话描述由若干行文本组成,每行的格式如下:
<type>=<value>
其中,<type> 必须恰好是一个区分大小写的字符,而 <value> 是结构化文本,其格式取决于 <type>。一般来说 <value> 是由单个空格字符分隔的字段或自由格式的字符串,且区分大小写,除非特定字段另有规定。不得在“=”符号两侧使用空格:
根据《RFC 4566》第9页,SDP的整体结构如下:
其中,常见的 <type>类型如下:
v:“v=”字段给出了会话描述协议的版本,目前SDP仅有一个正式版本,即v=0:
o:“o=”字段给出了会话的发起者(用户名和用户主机地址)以及会话标识符和版本。格式为:
o=<username> <sess-id> <sess-version> <nettype> <addrtype><unicast-address>
其中:
<username>:用户在源主机上的登录名,如果源主机不支持用户ID概念,则为“-”。 <username> 不得包含空格。
<sess-id>:一个数字字符串,会话的全局唯一标识符。分配<sess-id>的方法由创建工具决定,建议使用网络时间协议(Network Time Protocol,NTP)格式的时间戳以确保唯一性。
<sess-version>:会话描述的版本号。其使用由创建工具决定。只要在修改会话数据时增加, <sess-version>的值就会增加。建议使用 NTP 格式的时间戳。
<nettype>:一个文本字符串,表示网络类型。值一般为“IN”,表示“Internet”。
<addrtype>:一个文本字符串,表示后面的地址类型。值一般为IP4或IP6,表明后续地址使用的是IPv4还是IPv6。
<unicast-address>:创建会话的机器地址。
s:文本会话名称。每个会话描述必须有且仅有一个“s=”字段。s="字段不得为空,必须包含 ISO 10646 字符。如果会话没有有意义的名称,则值“s=”(即用一个空格作为会话名称):
c:包含连接数据信息。会话描述必须在每个媒体描述中至少包含一个 “c=”字段,或在会话级别包含一个 “c=”字段。格式为:
c=<nettype> <addrtype> <connection-address>
其中:
<nettype>:一个文本字符串,表示网络类型。值一般为“IN”,表示“Internet”。
<addrtype>:一个文本字符串,表示后面的地址类型。值一般为IP4或IP6,表明后续地址使用的是IPv4还是IPv6。
<connection-address>:连接地址,即要连接到的服务器的ip地址。根据 <addrtype> 字段的值,可在连接地址后添加可选子字段,具体取决于 <addrtype> 字段的值。
b:带宽。格式为:b=<bwtype>:<bandwidth>
其中:
<bwtype>:值可以为AS(应用层信号,Application-Specific),表示总体带宽需求,或者是CT(会议总带宽,Conference Total)等特定类型。
<bandwidth>:带宽值,单位为kpbs。
t:指定会话的开始和停止时间。如果会话在不规则间隔的多个时间段启动,可以使用多个 “t=”行。每增加一个 “t=”行,就多指定一段会话的活动时间。格式为:
t=<start-time> <stop-time>
其中:
<start-time>:会话的开始时间。值用网络时间协议(NTP)时间值的十进制表示,单位是自 1900 年以来的秒数。
<stop-time>:会话的停止时间。值用网络时间协议(NTP)时间值的十进制表示,单位是自 1900 年以来的秒数。
a:该字段是扩展 SDP 的主要手段。用于添加有关媒体流的信息,或传递适用于整个会议而非单个媒体的附加信息:
m:会话描述可包含多个媒体描述。每个媒体描述都以 “m=”字段开始,以下一个 “m=”字段或会话描述的结尾结束。格式为:
m=<media> <port> <proto> <fmt> ...
其中:
<media>:媒体类型。目前定义的媒体有 "audio"、"video"、"text"、"application"和"message",但该列表将来可能会扩展。
<port>:发送媒体流的传输端口。传输端口的含义取决于相关 “c=”字段中指定的网络和传输端口。如果音视频数据为RTP,那<port>为接收端需要创建的UDP服务器的端口号,该端口用于接收推流段发送的基于UDP的RTP数据。
<proto>:传输协议。含义取决于相关 “c=”字段中的地址类型字段。因此,“c=”字段中的 IP4表示传输协议通过 IP4 运行。以下是已定义的传输协议,但可通过向 IANA 注册新协议进行扩展:
udp:表示通过 UDP 运行的未指定协议。
RTP/AVP: 表示在 RTP Profile for Audio and Video Conferences with Minimal Control下使用的基于UDP的RTP。
RTP/SAVP:表示通过 UDP 运行的安全实时传输协议通过 UDP 运行。
<fmt>:媒体格式描述。取决于 <proto> 子字段的值。如果 <proto> 子字段为 “RTP/AVP ”或 “RTP/SAVP”,则 <fmt> 子字段包含 RTP 有效载荷类型编号:
a=rtpmap:该属性将 RTP 有效载荷类型编号(如 “m=”行中使用的)映射到表示有效载荷格式的编码名称。它还提供有关时钟速率和编码参数的信息。格式为:
a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>]
a=fmtp:该属性允许以 SDP 所不具备的方式传递特定格式的参数。格式为:
a=fmtp:<format> <format specific parameters>
对于H.264视频,格式一般为:a=fmtp:XX packetization-mode=X; sprop-parameter-sets=XXX,XXX; profile-level-id=XXX。
其中:
packetization-mode:根据《RFC 6184》第51页,该参数表示 RTP有效载荷类型的属性或接收器实现的功能。只能指示一个配置点;因此,当声明支持一种以上数据包化模式的功能时,必须使用多个配置点(RTP 有效载荷类型)。当packetization-mode值等于0或不存在packetization-mode时,表示必须使用Single NAL unit mode(单一的NAL模式)。当packetization-mode的值等于1时,表示必须使用Non-interleaved mode(非交错模式)。当 packetization-mode的值等于 2 时,表示必须使用Interleaved mode(交错模式)。packetization-mode的值必须0至2(含 2)范围内的整数:
profile-level-id:根据《RFC 6184》第39页,该参数基base16(十六进制)表示法在序列参数集 的NAL单元中指定以下三个字节: (1)profile_idc;(2)此处称为 profile-iop 的字节,由 constraint_set0_flag、constraint_set1_flag、constraint_set2_flag、constraint_set3_flag、constraint_set4_flag、constraint_set5_flag 和 reserved_zero_2bits 的值按位重要性顺序(从最重要的位开始)组成;(3)level_idc。更多关于SPS(Sequence parameter set,序列参数集)的内容可以参考:《音视频入门基础:H.264专题(9)——SPS简介》:
sprop-parameter-sets:根据《RFC 6184》第48到第49页,该参数包含SPS和PPS这两个参数集,它们是解码视频流所必需的额外参数。sprop-parameter-sets之后携带以BASE64编码和逗号分隔的SPS和PPS。 执行《音视频入门基础:RTP专题(2)——使用FFmpeg命令生成RTP流》中的“媒体文件转推RTP的FFmpeg命令”生成的RTP流中不包含SPS和PPS,SPS和PPS在SDP文件的sprop-parameter-sets参数中携带。
四、SDP实例分析
执行《音视频入门基础:RTP专题(2)——使用FFmpeg命令生成RTP流》中的“媒体文件转推RTP的FFmpeg命令”会生成一个SDP文件,该文件内容如下:
v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
t=0 0
a=tool:libavformat 61.7.100
m=video 6005 RTP/AVP 96
c=IN IP4 192.168.0.102
b=AS:1327
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAH6zZgFAFuwFqAgICgAAAAwCAAAAZB4wYzQ==,aOl7LIs=; profile-level-id=64001F
m=audio 7005 RTP/AVP 97
c=IN IP4 192.168.0.102
b=AS:160
a=rtpmap:97 MPEG4-GENERIC/48000/2
a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=1190
下面进行逐行的分析。
v=0:表示SDP遵循版本0的规范。
o=- 0 0 IN IP4 127.0.0.1:用户名为-,此处服务器未填写实际用户名。会话标识符和会话描述的版本均为NTP时间戳,值都为0。网络类型为IN,表示Internet。地址类型为IP4,表示IPv4地址。服务器的IP地址为127.0.0.1。
s=No Name:文本会话的名称为No Name。
t=0 0:表示持久会话。即会话没有固定的开始和结束时间(无限期有效)
a=tool:libavformat 61.7.100:工具名称和版本,表明使用libavformat工具,版本为61.7.100。
m=video 6005 RTP/AVP 96:媒体类型为video,表示这是一个视频媒体流。端口为6005。传输协议为RTP/AVP,表示使用基于UDP的RTP传输,并允许在会话中协商负载类型。负载类型为96,表示视频流使用编号为96的负载类型。
c=IN IP4 192.168.0.102:网络类型为IN,表示Internet。地址类型为IP4,表示IPv4地址。连接地址为192.168.0.102。
b=AS:1327:指定媒体流所需的带宽,此处为1327kbps。
a=rtpmap:96 H264/90000:映射PT为96的负载类型到H.264编码,采样率为90000 Hz。
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAH6zZgFAFuwFqAgICgAAAAwCAAAAZB4wYzQ==,aOl7LIs=; profile-level-id=64001F:
提供PT为96的H.264编码的详细参数。其中:
packetization-mode=1:表示采用Non-interleaved mode(非交错模式)。
profile-level-id=64001F:指定H.264的Profile和Level。
sprop-parameter-sets:可以通过spsparser工具(下载地址:https://download.csdn.net/download/ScarletMeCarzy/12424529)将里面的SPS和PPS信息解析出来。下载该工具后新建sps.txt和pps.txt两个文本文件:
sps.txt中填入示例SDP文件中的以BASE64编码后的SPS的内容:Z2QAH6zZgFAFuwFqAgICgAAAAwCAAAAZB4wYzQ==
pps.txt中填入示例SDP文件中的以BASE64编码后的PPS的内容:aOl7LIs=
Windows控制台输入命令:spsparser.exe sps.txt pps.txt output.txt
执行上述命令后,会生成output.txt这个文件,里面包含解析出来的SPS和PPS的具体信息:
Start dumping SPS:
profile_idc = 100
constrained_set0_flag = 0
constrained_set1_flag = 0
constrained_set2_flag = 0
constrained_set3_flag = 0
level_idc = 31
seq_parameter_set_id = 0
chroma_format_idc = 1
bit_depth_luma_minus8 = 0
bit_depth_chroma_minus8 = 0
seq_scaling_matrix_present_flag = 0
log2_max_frame_num_minus4 = 1
pic_order_cnt_type = 0
log2_max_pic_order_cnt_lsb_minus4 = 0
delta_pic_order_always_zero_flag = 0
offset_for_non_ref_pic = 0
offset_for_top_to_bottom_field = 0
num_ref_frames_in_pic_order_cnt_cycle = 0
num_ref_frames = 5
gaps_in_frame_num_value_allowed_flag = 1
pic_width_in_mbs_minus1 = 0
pic_height_in_mbs_minus1 = 5
frame_mbs_only_flag = 0
mb_adaptive_frame_field_flag = 0
direct_8x8_interence_flag = 0
frame_cropping_flag = 0
frame_cropping_rect_left_offset = 0
frame_cropping_rect_right_offset = 0
frame_cropping_rect_top_offset = 0
frame_cropping_rect_bottom_offset = 0
vui_parameters_present_flag = 0
Start dumping PPS:
pic_parameter_set_id = 0
seq_parameter_set_id = 0
entropy_coding_mode_flag = 1
pic_order_present_flag = 0
num_slice_groups_minus1 = 0
slice_group_map_type = 0
num_ref_idx_l0_active_minus1 = 4
num_ref_idx_l1_active_minus1 = 0
weighted_pref_flag = 1
weighted_bipred_idc = 2
pic_init_qp_minus26 = 0
pic_init_qs_minus26 = 0
chroma_qp_index_offset = -2
deblocking_filter_control_present_flag = 1
constrained_intra_pred_flag = 0
redundant_pic_cnt_present_flag = 0
transform_8x8_mode_flag = 1
pic_scaling_matrix_present_flag = 0
second_chroma_qp_index_offset = -2
五、音频的SDP媒体描述
具体可以参考:《音视频入门基础:RTP专题(17)——音频的SDP媒体描述》