|  | /* | 
|  | *  Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. | 
|  | * | 
|  | *  Use of this source code is governed by a BSD-style license | 
|  | *  that can be found in the LICENSE file in the root of the source | 
|  | *  tree. An additional intellectual property rights grant can be found | 
|  | *  in the file PATENTS.  All contributing project authors may | 
|  | *  be found in the AUTHORS file in the root of the source tree. | 
|  | */ | 
|  |  | 
|  | #include "modules/congestion_controller/pcc/monitor_interval.h" | 
|  | #include "rtc_base/logging.h" | 
|  |  | 
|  | namespace webrtc { | 
|  | namespace pcc { | 
|  |  | 
|  | PccMonitorInterval::PccMonitorInterval(DataRate target_sending_rate, | 
|  | Timestamp start_time, | 
|  | TimeDelta duration) | 
|  | : target_sending_rate_(target_sending_rate), | 
|  | start_time_(start_time), | 
|  | interval_duration_(duration), | 
|  | received_packets_size_(DataSize::Zero()), | 
|  | feedback_collection_done_(false) {} | 
|  |  | 
|  | PccMonitorInterval::~PccMonitorInterval() = default; | 
|  |  | 
|  | PccMonitorInterval::PccMonitorInterval(const PccMonitorInterval& other) = | 
|  | default; | 
|  |  | 
|  | void PccMonitorInterval::OnPacketsFeedback( | 
|  | const std::vector<PacketResult>& packets_results) { | 
|  | for (const PacketResult& packet_result : packets_results) { | 
|  | if (packet_result.sent_packet.send_time <= start_time_) { | 
|  | continue; | 
|  | } | 
|  | // Here we assume that if some packets are reordered with packets sent | 
|  | // after the end of the monitor interval, then they are lost. (Otherwise | 
|  | // it is not clear how long should we wait for packets feedback to arrive). | 
|  | if (packet_result.sent_packet.send_time > | 
|  | start_time_ + interval_duration_) { | 
|  | feedback_collection_done_ = true; | 
|  | return; | 
|  | } | 
|  | if (packet_result.receive_time.IsInfinite()) { | 
|  | lost_packets_sent_time_.push_back(packet_result.sent_packet.send_time); | 
|  | } else { | 
|  | received_packets_.push_back( | 
|  | {packet_result.receive_time - packet_result.sent_packet.send_time, | 
|  | packet_result.sent_packet.send_time}); | 
|  | received_packets_size_ += packet_result.sent_packet.size; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // For the formula used in computations see formula for "slope" in the second | 
|  | // method: | 
|  | // https://www.johndcook.com/blog/2008/10/20/comparing-two-ways-to-fit-a-line-to-data/ | 
|  | double PccMonitorInterval::ComputeDelayGradient( | 
|  | double delay_gradient_threshold) const { | 
|  | // Early return to prevent division by 0 in case all packets are sent at the | 
|  | // same time. | 
|  | if (received_packets_.empty() || received_packets_.front().sent_time == | 
|  | received_packets_.back().sent_time) { | 
|  | return 0; | 
|  | } | 
|  | double sum_times = 0; | 
|  | double sum_delays = 0; | 
|  | for (const ReceivedPacket& packet : received_packets_) { | 
|  | double time_delta_us = | 
|  | (packet.sent_time - received_packets_[0].sent_time).us(); | 
|  | double delay = packet.delay.us(); | 
|  | sum_times += time_delta_us; | 
|  | sum_delays += delay; | 
|  | } | 
|  | double sum_squared_scaled_time_deltas = 0; | 
|  | double sum_scaled_time_delta_dot_delay = 0; | 
|  | for (const ReceivedPacket& packet : received_packets_) { | 
|  | double time_delta_us = | 
|  | (packet.sent_time - received_packets_[0].sent_time).us(); | 
|  | double delay = packet.delay.us(); | 
|  | double scaled_time_delta_us = | 
|  | time_delta_us - sum_times / received_packets_.size(); | 
|  | sum_squared_scaled_time_deltas += | 
|  | scaled_time_delta_us * scaled_time_delta_us; | 
|  | sum_scaled_time_delta_dot_delay += scaled_time_delta_us * delay; | 
|  | } | 
|  | double rtt_gradient = | 
|  | sum_scaled_time_delta_dot_delay / sum_squared_scaled_time_deltas; | 
|  | if (std::abs(rtt_gradient) < delay_gradient_threshold) | 
|  | rtt_gradient = 0; | 
|  | return rtt_gradient; | 
|  | } | 
|  |  | 
|  | bool PccMonitorInterval::IsFeedbackCollectionDone() const { | 
|  | return feedback_collection_done_; | 
|  | } | 
|  |  | 
|  | Timestamp PccMonitorInterval::GetEndTime() const { | 
|  | return start_time_ + interval_duration_; | 
|  | } | 
|  |  | 
|  | double PccMonitorInterval::GetLossRate() const { | 
|  | size_t packets_lost = lost_packets_sent_time_.size(); | 
|  | size_t packets_received = received_packets_.size(); | 
|  | if (packets_lost == 0) | 
|  | return 0; | 
|  | return static_cast<double>(packets_lost) / (packets_lost + packets_received); | 
|  | } | 
|  |  | 
|  | DataRate PccMonitorInterval::GetTargetSendingRate() const { | 
|  | return target_sending_rate_; | 
|  | } | 
|  |  | 
|  | DataRate PccMonitorInterval::GetTransmittedPacketsRate() const { | 
|  | if (received_packets_.empty()) { | 
|  | return target_sending_rate_; | 
|  | } | 
|  | Timestamp receive_time_of_first_packet = | 
|  | received_packets_.front().sent_time + received_packets_.front().delay; | 
|  | Timestamp receive_time_of_last_packet = | 
|  | received_packets_.back().sent_time + received_packets_.back().delay; | 
|  | if (receive_time_of_first_packet == receive_time_of_last_packet) { | 
|  | RTC_LOG(LS_WARNING) | 
|  | << "All packets in monitor interval were received at the same time."; | 
|  | return target_sending_rate_; | 
|  | } | 
|  | return received_packets_size_ / | 
|  | (receive_time_of_last_packet - receive_time_of_first_packet); | 
|  | } | 
|  |  | 
|  | }  // namespace pcc | 
|  | }  // namespace webrtc |