RR报文解析(二) fraction lost

来源:互联网 发布:农村淘宝的现状分析 编辑:程序博客网 时间:2024/04/26 22:14

先附上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);}