在之前的文章:WebRTC研究:rrt 时间计算 之 接收 SR / RR 包 中讲到,sender 在接收到 RR 包后,会根据包体所携带的 DelayLastSR / LastSR 计算出 RRT 时间,但这个 RRT 时间并不能直接应用到重传等功能中,必须经过二次处理。
二次处理在 ModuleRtpRtcpImpl::Process() 中完成,这个函数在之前的文章:WebRTC研究:rrt 时间计算 之 发送 SR / RR 包 中提到过,它的执行间隔为 5 ms。
具体逻辑:
-
若本端是发送端:sending_ = true:
-
判断上一次处理完 RRT 时间之后,本端是否又收到了新的 SR/RR 包,并且距离上一次处理 RRT 时间 已经超过了 1000ms,是的话继续;
-
遍历所有 remoteReceiveBlock,取出 RTCPReceiver 在收到 RR 包时所记录的最新 RRT 时间,即文章:WebRTC研究:rrt 时间计算 之 接收 SR / RR 包 中第四章节所记录的 reportBlock->RTT,并记录所有 remoteReceiveBlock 中最新 RRT 时间的最大值:max_rtt;
-
将 max_rtt 与当前时间存入 CallStats 对象的 reports_ 集合中,后续CallStats.Process() 会每隔 1000ms 对 reports_ 进行统计分析,计算出最新的 avg_rtt_ms_ 与 max_rtt_ms_(计算逻辑请参考文章:WebRTC研究:rrt 时间 之 CallStats);
-
-
若本端不是发送端:sending_ = false:
(XR 协议相关,与 SR 协议实现类似。若 receiver 也是发送端,那么按照上一步,receiver 同样可计算出 RRT 时间,但若 receiver 仅仅是接收端,则需开启 XR 协议,然后按照此部分计算出 RRT 时间。)- 判断距离上一次处理 RRT 时间 已经超过了 1000ms,是的话继续;
- 从 RTCPReceiver 中取出 xr_rr_rtt_ms_(与报文类型 kXrDlrrReportBlock 有关),并与当前时间一起存入 CallStats 对象的 reports_ 集合,交由 CallStats.Process() 后续处理。
-
若距离上一次处理 RRT 时间已经超过了 1000ms,则取出 CallStats.Process() 处理后的 avg_rtt_ms_,这个 RRT 时间就是最终重传等功能所用到的 RRT 时间。
void ModuleRtpRtcpImpl::Process()
{
const int64_t now = clock_->TimeInMilliseconds();
/* 记录本次处理时间 */
last_process_time_ = now;
/* 处理 bitrate */
const int64_t kRtpRtcpBitrateProcessTimeMs = 10;
if (now >= last_bitrate_process_time_ + kRtpRtcpBitrateProcessTimeMs)
{
rtp_sender_.ProcessBitrate();
last_bitrate_process_time_ = now;
}
/* rrt 处理时间间隔为 1000ms */
const int64_t kRtpRtcpRttProcessTimeMs = 1000;
/* 判断处理 rrt 时间是否到了 */
bool process_rtt = now >= last_rtt_process_time_ + kRtpRtcpRttProcessTimeMs;
if (rtcp_sender_.Sending())
{
/*
上一次处理完 RRT 时间之后,本端又收到了新的 SR/RR 包,
并且距离上一次处理 RRT 时间 已经超过了 1000ms
*/
if (rtcp_receiver_.LastReceivedReceiverReport() > last_rtt_process_time_ && process_rtt)
{
/*
遍历 std::map<uint32_t, std::map<uint32_t, RTCPHelp::RTCPReportBlockInformation*> > _receivedReportBlockMap,
收集内层 value:RTCPReportBlockInformation 中的 remoteReceiveBlock 值
*/
std::vector<RTCPReportBlock> receive_blocks;
rtcp_receiver_.StatisticsReceived(&receive_blocks);
/* 遍历 remoteReceiveBlock,获取最大 RRT */
int64_t max_rtt = 0;
for (std::vector<RTCPReportBlock>::iterator it = receive_blocks.begin(); it != receive_blocks.end(); ++it)
{
/*
取出 RTCPReceiver 在收到 RR 包时所记录的 最新/平均/最小/最大 RRT 时间,
本别对应函数的第2~第5个参数,参数为NULL,表示不需要获取对应的值
*/
int64_t rtt = 0;
rtcp_receiver_.RTT(it->remoteSSRC, &rtt, NULL, NULL, NULL);
max_rtt = (rtt > max_rtt) ? rtt : max_rtt;
}
/*
将 max_rtt 与 当前时间 存入 list:reports_,
后续 CallStats.Process() 会每隔 1000ms 对 reports_ 进行统计分析,计算出最新的 avg_rtt_ms_ 与 max_rtt_ms_
*/
if (rtt_stats_ && max_rtt != 0)
rtt_stats_->OnRttUpdate(max_rtt);
}
// Verify receiver reports are delivered and the reported sequence number
// is increasing.
/* 时间间隔,audio:5000ms */
int64_t rtcp_interval = RtcpReportInterval();
/*
判断接收 RR包 是否超时,
超时时间:距离上一次接收到 RR包 超过 3*5000 ms
*/
if (rtcp_receiver_.RtcpRrTimeout(rtcp_interval))
{
LOG_F(LS_WARNING) << "Timeout: No RTCP RR received.";
}
else if (rtcp_receiver_.RtcpRrSequenceNumberTimeout(rtcp_interval))
{
LOG_F(LS_WARNING) <<
"Timeout: No increase in RTCP RR extended highest sequence number.";
}
if (remote_bitrate_ && rtcp_sender_.TMMBR())
{
unsigned int target_bitrate = 0;
std::vector<unsigned int> ssrcs;
if (remote_bitrate_->LatestEstimate(&ssrcs, &target_bitrate))
{
if (!ssrcs.empty())
{
target_bitrate = target_bitrate / ssrcs.size();
}
rtcp_sender_.SetTargetBitrate(target_bitrate);
}
}
}
else
{
// Report rtt from receiver.
if (process_rtt)
{
/* 取出 xr_rr_rtt_ms_ 并将其重置为0,同时更新 list:reports_ */
int64_t rtt_ms;
if (rtt_stats_ && rtcp_receiver_.GetAndResetXrRrRtt(&rtt_ms))
{
/* 将 rrt时间 与 当前时间 存入 list:reports_ */
rtt_stats_->OnRttUpdate(rtt_ms);
}
}
}
// Get processed rtt.
if (process_rtt)
{
/* 基本本次处理 rrt 时间 */
last_rtt_process_time_ = now;
if (rtt_stats_)
{
// 从 CallStats 对象中取出 avg_rtt_ms_
int64_t last_rtt = rtt_stats_->LastProcessedRtt();
/* 保存 avg_rtt_ms_,后续重传 RTP 包等都需要用到 */
if (last_rtt >= 0)
set_rtt_ms(last_rtt);
}
}
/*
判断发送 RTP 包的时间是否到达
对于 audio,RTP 包的发送间隔是 5000ms
*/
if (rtcp_sender_.TimeToSendRTCPReport())
{
/*
获取 上一次收到的 SR 包中所携带的 NTP 时间戳、收到 SR 包时本地时间戳等信息
*/
RTCPSender::FeedbackState state = GetFeedbackState();
// Prevent sending streams to send SR before any media has been sent.
if (!rtcp_sender_.Sending() || state.packets_sent > 0)
rtcp_sender_.SendRTCP(state, kRtcpReport); /* 发送RTP包 并计算下一次发送 RTP包的时间 */
}
if (UpdateRTCPReceiveInformationTimers())
{
// A receiver has timed out
rtcp_receiver_.UpdateTMMBR();
}
}
一、获取最近接收到 SR/RR 包时间:
int64_t RTCPReceiver::LastReceivedReceiverReport() const
{
rtc::CritScope lock(&_criticalSectionRTCPReceiver);
int64_t last_received_rr = -1;
for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin(); it != _receivedInfoMap.end(); ++it)
{
if (it->second->lastTimeReceived > last_received_rr)
{
last_received_rr = it->second->lastTimeReceived;
}
}
return last_received_rr;
}
二、取出 RTCPReceiver 在收到 RR 包时所记录的 最新/平均/最小/最大 RRT 时间:
int32_t RTCPReceiver::RTT(uint32_t remoteSSRC,
int64_t* RTT,
int64_t* avgRTT,
int64_t* minRTT,
int64_t* maxRTT) const
{
rtc::CritScope lock(&_criticalSectionRTCPReceiver);
RTCPReportBlockInformation* reportBlock = GetReportBlockInformation(remoteSSRC, main_ssrc_);
if (reportBlock == NULL)
{
return -1;
}
if (RTT)
{
*RTT = reportBlock->RTT;
}
if (avgRTT)
{
*avgRTT = reportBlock->avgRTT;
}
if (minRTT)
{
*minRTT = reportBlock->minRTT;
}
if (maxRTT)
{
*maxRTT = reportBlock->maxRTT;
}
return 0;
}
三、更新 CallStats 对象的 reports_ 集合:
virtual void OnRttUpdate(int64_t rtt)
{
owner_->OnRttUpdate(rtt);
}
void CallStats::OnRttUpdate(int64_t rtt)
{
rtc::CritScope cs(&crit_);
int64_t now_ms = clock_->TimeInMilliseconds();
/* 将 rrt时间 与 当前时间 存入 list:reports_ */
reports_.push_back(RttTime(rtt, now_ms));
if (time_of_first_rtt_ms_ == -1)
time_of_first_rtt_ms_ = now_ms;
}
四、取出 CallStats 对象中的 avg_rtt_ms_:
virtual int64_t LastProcessedRtt() const
{
return owner_->avg_rtt_ms();
}
五、保存 avg_rtt_ms_,后续重传 RTP 包等都需要用到:
void ModuleRtpRtcpImpl::set_rtt_ms(int64_t rtt_ms)
{
rtc::CritScope cs(&critical_section_rtt_);
rtt_ms_ = rtt_ms;
}