一、当 sender / receiver 收到一个 RTCP 包时,会根据包类型调用分别调用不同的处理函数。对于 SR 和 RR 包,都会交由 HandleSenderReceiverReport() 处理:
int32_t ModuleRtpRtcpImpl::IncomingRtcpPacket(const uint8_t* rtcp_packet, const size_t length) --------- rtp_rtcp_impl.cc
int32_t RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation, RTCPUtility::RTCPParserV2* rtcpParser) --------- rtp_rtcp_impl.cc
int32_t
RTCPReceiver::IncomingRTCPPacket(RTCPPacketInformation& rtcpPacketInformation,
RTCPUtility::RTCPParserV2* rtcpParser)
{
...
...
...
while (pktType != RTCPPacketTypes::kInvalid)
{
// Each "case" is responsible for iterate the parser to the
// next top level packet.
switch (pktType)
{
case RTCPPacketTypes::kSr:
case RTCPPacketTypes::kRr:
HandleSenderReceiverReport(*rtcpParser, rtcpPacketInformation);
break;
...
...
...
}
pktType = rtcpParser->PacketType();
}
...
...
...
}
二、对于 SR 包,receiver 会保留包内所携带的 NTP 时间戳,并记录当前 NTP 时间戳:
void
RTCPReceiver::HandleSenderReceiverReport(RTCPUtility::RTCPParserV2& rtcpParser,
RTCPPacketInformation& rtcpPacketInformation)
{
RTCPUtility::RTCPPacketTypes rtcpPacketType = rtcpParser.PacketType();
const RTCPUtility::RTCPPacket& rtcpPacket = rtcpParser.Packet();
// 在 map:_receivedInfoMap 中创建一个 RTCPReceiveInformation 对象,键为 remoteSSRC
RTCPReceiveInformation* ptrReceiveInfo = CreateReceiveInformation(remoteSSRC);
if (!ptrReceiveInfo)
{
rtcpParser.Iterate();
return;
}
...
...
...
/* 接收到 SR 包 */
if (rtcpPacketType == RTCPPacketTypes::kSr)
{
...
...
...
if (_remoteSSRC == remoteSSRC) // have I received RTP packets from this party
{
/* 记录保存在 SR 包中的 NTP 时间戳 */
_remoteSenderInfo.NTPseconds = rtcpPacket.SR.NTPMostSignificant;
_remoteSenderInfo.NTPfraction = rtcpPacket.SR.NTPLeastSignificant;
/* 记录接收到 SR 包的当前 NTP 时间戳 */
_clock->CurrentNtp(_lastReceivedSRNTPsecs, _lastReceivedSRNTPfrac);
...
...
...
}
else
{
rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
}
}
else
{
/* 接收到 RR 包 */
TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "RR",
"remote_ssrc", remoteSSRC, "ssrc", main_ssrc_);
rtcpPacketInformation.rtcpPacketTypeFlags |= kRtcpRr;
}
// 标记 RTCPReceiveInformation.lastTimeReceived 为当前时间,表示对端目前是活动的
UpdateReceiveInformation(*ptrReceiveInfo);
rtcpPacketType = rtcpParser.Iterate();
// 取出 RR 包中 DelayLastSR / LastSR,计算 RRT 时间
while (rtcpPacketType == RTCPPacketTypes::kReportBlockItem)
{
HandleReportBlock(rtcpPacket, rtcpPacketInformation, remoteSSRC);
rtcpPacketType = rtcpParser.Iterate();
}
三、更新最近接收到 SR/RR 包时间:
void RTCPReceiver::UpdateReceiveInformation(RTCPReceiveInformation& receiveInformation)
{
// Update that this remote is alive
receiveInformation.lastTimeReceived = _clock->TimeInMilliseconds();
}
四、对于 RR 包,sender 会取出包体所携带的 DelayLastSR / LastSR,并计算 RRT 时间:
RRT = receive_time - delay - send_time,即:sender接收到RR包的当前时间戳 - receiver从接到SR包到发送RR包之间的延时 - sender发送SR包时的当前时间戳。
void RTCPReceiver::HandleReportBlock(
const RTCPUtility::RTCPPacket& rtcpPacket,
RTCPPacketInformation& rtcpPacketInformation,
uint32_t remoteSSRC)
EXCLUSIVE_LOCKS_REQUIRED(_criticalSectionRTCPReceiver)
{
...
...
...
/*
在 std::map<uint32_t, std::map<uint32_t, RTCPHelp::RTCPReportBlockInformation*> > _receivedReportBlockMap 中创建一个键值对
外层 key:rtcpPacket.ReportBlockItem.SSRC
内层 key:remoteSSRC
*/
RTCPReportBlockInformation* reportBlock = CreateOrGetReportBlockInformation(remoteSSRC, rtcpPacket.ReportBlockItem.SSRC);
if (reportBlock == NULL)
{
LOG(LS_WARNING) << "Failed to CreateReportBlockInformation("
<< remoteSSRC << ")";
return;
}
...
...
...
// 取出 RR 包中携带的 DelayLastSR,即为 receiver(对端)从接到SR包 到发送RR包 之间的延时
reportBlock->remoteReceiveBlock.delaySinceLastSR = rb.DelayLastSR;
// 取出 RR 包中携带的 LastSR,也是 sender(本端)发送 SR 包时的当前时间戳
reportBlock->remoteReceiveBlock.lastSR = rb.LastSR;
...
...
...
int64_t rtt = 0;
// 取出 RR 包中携带的 LastSR,也是 sender(本端)发送 SR 包时的当前时间戳
uint32_t send_time = rtcpPacket.ReportBlockItem.LastSR;
if (!receiver_only_ && send_time != 0)
{
// 取出 RR 包中携带的 DelayLastSR,即为 receiver(对端)从接到SR包 到发送RR包 之间的延时
uint32_t delay = rtcpPacket.ReportBlockItem.DelayLastSR;
// 获取当前时间戳
uint32_t receive_time = CompactNtp(NtpTime(*_clock));
// 计算 RTT,单位是:1/(2^16) = 1 / 65536 s
uint32_t rtt_ntp = receive_time - delay - send_time;
// 将 RTT 的单位转换成 ms
rtt = CompactNtpRttToMs(rtt_ntp);
// 记录最大 RRT 时间
if (rtt > reportBlock->maxRTT)
{
reportBlock->maxRTT = rtt;
}
// 记录最小 RTT 时间
if (reportBlock->minRTT == 0)
{
reportBlock->minRTT = rtt;
}
else if (rtt < reportBlock->minRTT)
{
reportBlock->minRTT = rtt;
}
// 记录最新 RTT 时间
reportBlock->RTT = rtt;
// 记录平均 RTT 时间
if (reportBlock->numAverageCalcs != 0)
{
// 获取平均 RTT 时间计算次数
float ac = static_cast<float>(reportBlock->numAverageCalcs);
/*计算最新平均 RTT 时间,为:
旧平均RTT时间 与 最新RTT 时间的加权和,权重分别为 ac / (ac + 1)、(1 / (ac + 1)
*/
float newAverage = ((ac / (ac + 1)) * reportBlock->avgRTT) + ((1 / (ac + 1)) * rtt);
// 四舍五入
reportBlock->avgRTT = static_cast<int64_t>(newAverage + 0.5f);
}
else
{
// First RTT.
reportBlock->avgRTT = rtt;
}
// 记录平均 RRT 时间计算次数
reportBlock->numAverageCalcs++;
}
...
...
...
}