先附上RR报文的图:
这节我们看下RR报文的fraction lost字段,它占8位,RFC_3550中对他的解释为:
The sender of the receiver report estimates the fraction of the RTP data packets from source SSRC_n that it assumes to be lost since it sent the previous SR or RR packet.
翻译过来大概是:RR报文的发送者估计的,自从上一次发送SR或RR报文后,它从SSRC_n 源端接收到的RTP包的丢包率。
我们注意到它占8位,不难猜出,真实的丢包率是个小数,它由fraction lost字段除以256得到。
下面我们看下,计算平均丢包率的代码:
void RtcpBandwidthObserverImpl::OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
int64_t rtt,
int64_t now_ms) override {
if (report_blocks.empty())
return;
int fraction_lost_aggregate = 0;
int total_number_of_packets = 0;
// Compute the a weighted average of the fraction loss from all report
// blocks.
for (ReportBlockList::const_iterator it = report_blocks.begin();
it != report_blocks.end(); ++it) {
std::map<uint32_t, uint32_t>::iterator seq_num_it =
ssrc_to_last_received_extended_high_seq_num_.find(it->sourceSSRC);
int number_of_packets = 0;
if (seq_num_it != ssrc_to_last_received_extended_high_seq_num_.end())
number_of_packets = it->extendedHighSeqNum - //当前接收到的rtp最高序列号减上一次的最高序列号,得到应该发送的rtp的数量
seq_num_it->second;
fraction_lost_aggregate += number_of_packets * it->fractionLost;
total_number_of_packets += number_of_packets;
// Update last received for this SSRC.
ssrc_to_last_received_extended_high_seq_num_[it->sourceSSRC] =
it->extendedHighSeqNum;
}
if (total_number_of_packets == 0)
fraction_lost_aggregate = 0;
else
fraction_lost_aggregate = (fraction_lost_aggregate + //得到的fraction_lost_aggregate其实是平均丢帧率*256, 为何要加上total_number_of_packets / 2,至今不是很明白
total_number_of_packets / 2) / total_number_of_packets;
if (fraction_lost_aggregate > 255)
return;
owner_->OnReceivedRtcpReceiverReport(fraction_lost_aggregate, rtt,
total_number_of_packets, now_ms);
}
为了理解,假设先后收到了3个RR报文,每次接收到的number_of_packets为n1, n2, n3, 每次的fractionLost为f1, f2, f3, 则最后计算出来的fraction_lost_aggregate 为:
(n1*f1 + n2*f2 + n3*f3 + (n1 + n2 + n3) / 2) / (n1 + n2 + n3).
其实我不太明白为什么要加上(n1 + n2 + n3) / 2, 正常情况下应该是:
(n1*f1 + n2*f2 + n3*f3) / (n1 + n2 + n3).
可能是为了防止结果被四舍五入吧。
最后结论,可以认为fraction_lost_aggregate 为平均丢包率 * 256, 因为丢包率小于1,所以结果不能大于256.
然后,还没完,得到fraction_lost_aggregate 后,它调用了owner_->OnReceivedRtcpReceiverReport(fraction_lost_aggregate, rtt,
total_number_of_packets, now_ms);
void BitrateControllerImpl::OnReceivedRtcpReceiverReport(
uint8_t fraction_loss,
int64_t rtt,
int number_of_packets,
int64_t now_ms) {
{
rtc::CritScope cs(&critsect_);
bandwidth_estimation_.UpdateReceiverBlock(fraction_loss, rtt,
number_of_packets, now_ms);
}
MaybeTriggerOnNetworkChanged();
}
bandwidth_estimation_是SendSideBandwidthEstimation类,它是估计发送码率的重要类,看下UpdateReceiverBlock函数:
void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss,
int64_t rtt,
int number_of_packets,
int64_t now_ms) {
if (first_report_time_ms_ == -1)
first_report_time_ms_ = now_ms;
// Update RTT.
last_round_trip_time_ms_ = rtt;
// Check sequence number diff and weight loss report
if (number_of_packets > 0) {
// Calculate number of lost packets.
const int num_lost_packets_Q8 = fraction_loss * number_of_packets;
// Accumulate reports.
lost_packets_since_last_loss_update_Q8_ += num_lost_packets_Q8;
expected_packets_since_last_loss_update_ += number_of_packets;
// Don't generate a loss rate until it can be based on enough packets.
if (expected_packets_since_last_loss_update_ < kLimitNumPackets)
return;
has_decreased_since_last_fraction_loss_ = false;
last_fraction_loss_ = lost_packets_since_last_loss_update_Q8_ / //主要在这里,得出last_fraction_loss_
expected_packets_since_last_loss_update_;
// Reset accumulators.
lost_packets_since_last_loss_update_Q8_ = 0;
expected_packets_since_last_loss_update_ = 0;
}
time_last_receiver_block_ms_ = now_ms;
UpdateEstimate(now_ms); //估算码率!!!
UpdateUmaStats(now_ms, rtt, (fraction_loss * number_of_packets) >> 8);
}