WebRTC研究:如何判定当前 RTP 包是新的数据包,而不是重传或者乱序包

RTP 包的序列号范围:[0, 2 ^ 16-1],当序列号达到最大值时,会出现所谓的回绕。例如,序列号到了 2 ^ 16-1,下个包序列号就是0。所以在判定一个包是新的数据包,还是重传或者乱序包时,不能直接根据数学意义上的大小值进行序列号比较。

WebRTC 使用如下算法来解决数字回绕问题:

inline bool IsNewerSequenceNumber(uint16_t sequence_number,
                                  uint16_t prev_sequence_number) {
  // Distinguish between elements that are exactly 0x8000 apart.
  // If s1>s2 and |s1-s2| = 0x8000: IsNewer(s1,s2)=true, IsNewer(s2,s1)=false
  // rather than having IsNewer(s1,s2) = IsNewer(s2,s1) = false.
  if (static_cast<uint16_t>(sequence_number - prev_sequence_number) == 0x8000) {
    return sequence_number > prev_sequence_number;
  }
  return sequence_number != prev_sequence_number &&
         static_cast<uint16_t>(sequence_number - prev_sequence_number) < 0x8000;
}

其原理是:

  • 定义两个 uint16 变量:sequence_number(当前收到的包的序列号),prev_sequence_number(上一个包的序列号);

  • 定义一个常量:Breakpoint,值为 uint16 类型取值范围的一半,即为 0x8000 = 8*16^3 = 32768;

  • 若 |sequence_number - prev_sequence_number| = Breakpoint,则以 sequence_number 与 prev_sequence_number 的大小作为判断依据;

  • 若 sequence_number != prev_sequence_number 且 |sequence_number - prev_sequence_number| < Breakpoint,则当前包为新包;

  • 若为其他情况,则当前包为重传或者乱序包。

发布了112 篇原创文章 · 获赞 22 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/u010601662/article/details/105074258
RTP