webrtc源码分析-rtp序列号新旧比较
webrtc通过函数AheadOf( )进行rtp序列号的新旧的比较,rtp序列号的比较不能单纯的比较大小,因为会涉及到回环:
template <typename T, T M = 0>
inline bool AheadOf(T a, T b) {
static_assert(std::is_unsigned<T>::value,
"Type must be an unsigned integer.");
return a != b && AheadOrAt<T, M>(a, b);
}
template <typename T, T M>
inline typename std::enable_if<(M == 0), bool>::type AheadOrAt(T a, T b) {
static_assert(std::is_unsigned<T>::value,
"Type must be an unsigned integer.");
const T maxDist = std::numeric_limits<T>::max() / 2 + T(1);
if (a - b == maxDist)
return b < a;
return ForwardDiff(b, a) < maxDist;
}
template <typename T, T M>
inline typename std::enable_if<(M == 0), T>::type ForwardDiff(T a, T b) {
static_assert(std::is_unsigned<T>::value,
"Type must be an unsigned integer.");
return b - a;
}
这里一共涉及到了三个函数AheadOf()、AheadOrAt()、ForwardDiff()
AheadOf(a,b)
的语义就是序列号a是否比序列号新,return中看到比较是否相等,然后就是执行AheadOrAt( )
AheadOrAt(a, b)
是判断a是否比b新的核心,其原理是这样的:rfc1982规定了序列号递增间隔不能超过取值范围的1/2(这是自己理解的),那么要判断a是否比b新,只要判断b到a的递增是否在1/2即可,递增超过1/2,则一定是因为a比b老而导致了回环, b到a的递增就是b到a的前向间距,前向间距怎么求呢,我们知道在向量的世界里,表示b到a的前向间距的话,我们会用 a - b(也就是终点减去起点得到一个向量增量),增量是正数时,就是前向增量,而增量是一个负数的时候,代表这是一个后向增量(b要后退这么才能到a),因无符号系统中因为没有负数,运算出来的负数都被无符号运算系统转变成了正数,相当于被加了一圈成了正数,向后倒变成了向前跑多大半圈,刚好是我们想要的前向间距的值
所以ForwardDiff(b, a) < maxDist;
这句话的意思就是说b到a的前向间距小于maxDist,此时符合协议要求的递增大小,所以a更新;
(注意: ForwardDiff(a, b)
中的内部实现虽然是 b - a
而不是a - b
,这是因为a和b在上一个函数是被反转传过来的。)
最后总结: 如果上一个包到当前包的前向间距在最大取值范围1/2内,那么说明当前包在递增间隔内做了递增,所以它是一个更新的包,当当前包是一个更旧的包的时候,上一个包到当前包的前向间距要绕过超过一个大半圈的间距增量才能到当前包,和序列号的递增间隔所设定的范围矛盾了,所以肯定是一个旧包。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· 字符编码:从基础到乱码解决
· Open-Sora 2.0 重磅开源!