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);}
- RR报文解析(二) fraction lost
- RR报文解析(一)
- RR报文解析(三)利用LSR, DLSR计算RTT
- RR报文解析(四)根据丢包率估计发送码率
- HTTP请求报文解析(二)
- wireshark 二 报文解析
- ISO8583报文(二)
- OSPF(二)【报文】
- rr
- rr
- rr
- rr
- rr
- rr
- rr
- 报文解析
- 报文解析
- 报文解析
- 【官方解说】Visual Studio 2017(VS 2017)各个版本有什么区别
- 文章标题
- Java 习题4 答案及解析
- PhP功能模块扩展——ImageMagick
- C++ Primer Plus(第六版)—— 第四章 复合类型 笔记和答案
- RR报文解析(二) fraction lost
- Material Design之TabLayout的用法(标题栏滑动+ViewPager)
- Win2008系统创建WEB服务器
- Codeforces 416
- magento开发必备插件列表汇总
- 简述如何搭建Java开发环境
- 让MFC的控件跟随当前windows风格
- Material Design之NavigationView的用法(抽屉式侧边栏)
- iOS UITextView详解 陌生属性解释,添加展示超链接并交互