3.2 SDP 协商深度剖析


文档摘要

3.2 SDP 协商深度剖析 上一节的骨架里,最核心的驱动事件是"设置描述",本节就打开这份被设置的文本本身。会话描述协议诞生于组播会议时代,文本格式老派,但它是两端引擎之间唯一的正式合同——读懂它,协商问题就再无黑箱。 一份提议文本的逐行解剖 下面是一段精简后的视频媒体段落,来自真实提议文本,注释写明每行的职责。完整提议由一个会话级头部与若干媒体段落组成,音视频各一段,数据通道也是一段特殊媒体。 逐行读完,协商要解决什么就清楚了:载荷列表是"我会什么"的牌面,方向是"我想怎么玩",指纹与握手角色是"安全条款",同步源标识是"我的流的身份号"。应答方逐段回应,把牌面交集、方向交集写回,合同即告成立。

3.2 SDP 协商深度剖析

上一节的骨架里,最核心的驱动事件是"设置描述",本节就打开这份被设置的文本本身。会话描述协议诞生于组播会议时代,文本格式老派,但它是两端引擎之间唯一的正式合同——读懂它,协商问题就再无黑箱。

一份提议文本的逐行解剖

下面是一段精简后的视频媒体段落,来自真实提议文本,注释写明每行的职责。完整提议由一个会话级头部与若干媒体段落组成,音视频各一段,数据通道也是一段特殊媒体。

m=video 9 UDP/TLS/RTP/SAVPF 96 98 100 :: 媒体类型 端口 传输协议 载荷类型列表(此例三个) c=IN IP4 0.0.0.0 :: 连接信息,BUNDLE 复用时统一占位 a=mid:0 :: 媒体段标识,复用传输时靠它区分流归属 a=sendonly :: 方向声明:只发、只收或双向 a=rtcp-mux :: 媒体与控制报文复用同一端口 a=setup:actpass :: 加密握手角色协商:本端可任,由对端定 a=fingerprint:sha-256 6B:8B:...:A1 :: 本端证书指纹,供对端核对加密握手对象 a=rtpmap:96 VP8/90000 :: 载荷 96 是 VP8,时钟频率九万赫兹 a=rtpmap:98 H264/90000 a=fmtp:98 level-asymmetry-allowed=1;packetization-mode=1 :: 载荷 98 的编码参数约束 a=ssrc:12345678 cname:streamLabel :: 本段媒体流的同步源标识与会话名

逐行读完,协商要解决什么就清楚了:载荷列表是"我会什么"的牌面,方向是"我想怎么玩",指纹与握手角色是"安全条款",同步源标识是"我的流的身份号"。应答方逐段回应,把牌面交集、方向交集写回,合同即告成立。理解到这个颗粒度,你就明白为什么协商失败的报错总是指向某一行——合同条款谈不拢,必然是具体条款的问题。

引擎怎么生成与比对这份文本

提议的生成在引擎内部是一次完整事务。入口接到生成请求后,先向编解码工厂索要当前设备真正可用的编码能力——注意是"可编"而不只是"认识",硬件编码器不可用时相应条目会被剔除;随后按收发器列表逐个组装媒体段落,注入方向、传输参数与安全指纹;最后整体序列化为文本。整个过程在信令线程上原子完成,生成失败则整体失败,不留半成品。

应答侧的比对逻辑更有讲究。对每个媒体段落,引擎按编码名与时钟率做主匹配,再核对参数约束:参数能协商取交集就取交集,硬性冲突则该编码整体出局。这里藏着两个高频坑。参数不对等导致的死局:一端声明了参数约束,另一端版本老不认识这个参数,匹配失败,媒体段落直接废弃,表现为"一切正常但没有画面"。方向不匹配的静默降级:两端方向声明交集为空时,合同照样成立,只是这条流收不到数据,应用层如果不检查方向,就成了"连接正常但黑屏"。排查这类问题的标准动作就是把两端文本并排逐行比对。

高频坑 文本特征 典型后果
参数不匹配 参数键值一端有一端无 编码出局、无画面
方向无交集 只发对只发 连接正常但无数据
指纹不符 指纹与握手证书不一致 加密握手失败、断连
标识缺失 复用场景下缺媒体段标识 流归属错乱

高频问答

协商环节的问题高度重复,把实际工单里出现最多的几个问答沉淀在此。

为什么双方都支持的编码却没有被选中

九成情况是参数交集为空。编码名与时钟率对上只是入场券,参数约束还要逐项过;任何一项硬冲突都会让整个编码出局。解法是比对双方文本里该编码的参数行,放宽过严的一侧。

提议里为什么有我用不到的媒体段落

引擎按收发器列表组装段落,曾经添加过的轨道即便已经移除,其收发器可能仍以只收方向存在。这是协议兼容的设计而非缺陷;确实需要清理时,走移除收发器的接口而不是移除轨道了事。

应答可以修改提议里的载荷编号吗

不可以。载荷编号是提议方的命名权,应答只能引用,这是协商能对上的前提。自作主张重编号的应答会在远端解析时直接失败,报错形如"未知的载荷类型"。

协商成功后还会重新协商吗

会。新增或移除轨道、改变方向、开关数据通道都会触发新一轮提议应答。重新协商走同样的状态机,上一节讲的"稳定态之外作废提议"规则同样适用,应用层的信令实现必须能承载多轮协商。

会话描述的文本会被引擎原样保存吗

不会。文本在设置时就被解析成内部结构,之后你从接口取回的"本地描述"是引擎重新序列化的产物。绝大多数字段会原样往返,但个别引擎不认识的属性行可能被丢弃。因此"把自定义属性行塞进文本指望原样带回"的做法不可靠,应用自定义数据应走数据通道或专门的元数据接口。

两端同时生成提议会发生什么

双方同时进入有本地提议状态,协商胶着,这就是经典的协商碰撞。协议为此设计了"从容处理"与"急切处理"两种消解策略,引擎内部实现了自动消解:一方把自己的提议回滚改发应答。应用层通常无须干预,但高并发场景(如抢答类业务)仍应避免无节制的双方同时提议——自动消解的代价是额外的往返。

案例:两引擎文本比对定位无画面

背景。一套方案里网页端与原生端互通,测试反馈原生端看网页端正常,反向则网页端画面时有时无,且只有部分机型出问题。

操作。分别在两台问题机型上导出双方提议与应答文本并排比对。很快在视频段落找到差异:问题机型的原生端在编码参数里声明了特定的档次约束,网页端应答按参数交集规则剔除了该编码,段落里只剩另一套双方都认的编码;而少数无问题的机型支持面更宽,两套编码都保留,画面自然正常。

结果。原生端放宽参数约束、允许应答侧自主降档后,问题机型画面恢复稳定。

解读。这个案例的价值在于把"部分机型出问题"这类玄学表象还原成合同条款问题:能力声明越苛刻,交集越小,容错越差。协商文本的比对应当成为互通测试的标准动作,两段文本的 diff 比任何猜测都诚实。顺带一提,比对时优先看三处:载荷列表的差集、参数键值的不对称、方向声明,绝大多数互通问题落在这三处。

变式。屏幕共享场景下,内容是低帧率高分辨率的静态画面为主,编码选择与摄像头完全不同。工程上常用协商的扩展能力为同一轨道附加多条不同配置的流描述,按内容特征选择——这已经触到多流与分层编码的门槛,第五章与第七章会接着展开。

要点回顾

本节要点:会话描述是两端的正式合同,逐行可查;提议生成是编解码能力枚举加段落组装的原子事务;应答按名字、时钟、参数三级匹配,取交集、去死项;无画面先查参数与方向的交集,黑屏不查引擎先查合同;互通问题用文本 diff 说话。下一节进入线路实测:候选怎么搜、成对怎么试、最优怎么选。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U