1 /*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include "modules/congestion_controller/pcc/monitor_interval.h"
12
13 #include <stddef.h>
14
15 #include <cmath>
16
17 #include "rtc_base/logging.h"
18
19 namespace webrtc {
20 namespace pcc {
21
PccMonitorInterval(DataRate target_sending_rate,Timestamp start_time,TimeDelta duration)22 PccMonitorInterval::PccMonitorInterval(DataRate target_sending_rate,
23 Timestamp start_time,
24 TimeDelta duration)
25 : target_sending_rate_(target_sending_rate),
26 start_time_(start_time),
27 interval_duration_(duration),
28 received_packets_size_(DataSize::Zero()),
29 feedback_collection_done_(false) {}
30
31 PccMonitorInterval::~PccMonitorInterval() = default;
32
33 PccMonitorInterval::PccMonitorInterval(const PccMonitorInterval& other) =
34 default;
35
OnPacketsFeedback(const std::vector<PacketResult> & packets_results)36 void PccMonitorInterval::OnPacketsFeedback(
37 const std::vector<PacketResult>& packets_results) {
38 for (const PacketResult& packet_result : packets_results) {
39 if (packet_result.sent_packet.send_time <= start_time_) {
40 continue;
41 }
42 // Here we assume that if some packets are reordered with packets sent
43 // after the end of the monitor interval, then they are lost. (Otherwise
44 // it is not clear how long should we wait for packets feedback to arrive).
45 if (packet_result.sent_packet.send_time >
46 start_time_ + interval_duration_) {
47 feedback_collection_done_ = true;
48 return;
49 }
50 if (packet_result.receive_time.IsInfinite()) {
51 lost_packets_sent_time_.push_back(packet_result.sent_packet.send_time);
52 } else {
53 received_packets_.push_back(
54 {packet_result.receive_time - packet_result.sent_packet.send_time,
55 packet_result.sent_packet.send_time});
56 received_packets_size_ += packet_result.sent_packet.size;
57 }
58 }
59 }
60
61 // For the formula used in computations see formula for "slope" in the second
62 // method:
63 // https://www.johndcook.com/blog/2008/10/20/comparing-two-ways-to-fit-a-line-to-data/
ComputeDelayGradient(double delay_gradient_threshold) const64 double PccMonitorInterval::ComputeDelayGradient(
65 double delay_gradient_threshold) const {
66 // Early return to prevent division by 0 in case all packets are sent at the
67 // same time.
68 if (received_packets_.empty() || received_packets_.front().sent_time ==
69 received_packets_.back().sent_time) {
70 return 0;
71 }
72 double sum_times = 0;
73 double sum_delays = 0;
74 for (const ReceivedPacket& packet : received_packets_) {
75 double time_delta_us =
76 (packet.sent_time - received_packets_[0].sent_time).us();
77 double delay = packet.delay.us();
78 sum_times += time_delta_us;
79 sum_delays += delay;
80 }
81 double sum_squared_scaled_time_deltas = 0;
82 double sum_scaled_time_delta_dot_delay = 0;
83 for (const ReceivedPacket& packet : received_packets_) {
84 double time_delta_us =
85 (packet.sent_time - received_packets_[0].sent_time).us();
86 double delay = packet.delay.us();
87 double scaled_time_delta_us =
88 time_delta_us - sum_times / received_packets_.size();
89 sum_squared_scaled_time_deltas +=
90 scaled_time_delta_us * scaled_time_delta_us;
91 sum_scaled_time_delta_dot_delay += scaled_time_delta_us * delay;
92 }
93 double rtt_gradient =
94 sum_scaled_time_delta_dot_delay / sum_squared_scaled_time_deltas;
95 if (std::abs(rtt_gradient) < delay_gradient_threshold)
96 rtt_gradient = 0;
97 return rtt_gradient;
98 }
99
IsFeedbackCollectionDone() const100 bool PccMonitorInterval::IsFeedbackCollectionDone() const {
101 return feedback_collection_done_;
102 }
103
GetEndTime() const104 Timestamp PccMonitorInterval::GetEndTime() const {
105 return start_time_ + interval_duration_;
106 }
107
GetLossRate() const108 double PccMonitorInterval::GetLossRate() const {
109 size_t packets_lost = lost_packets_sent_time_.size();
110 size_t packets_received = received_packets_.size();
111 if (packets_lost == 0)
112 return 0;
113 return static_cast<double>(packets_lost) / (packets_lost + packets_received);
114 }
115
GetTargetSendingRate() const116 DataRate PccMonitorInterval::GetTargetSendingRate() const {
117 return target_sending_rate_;
118 }
119
GetTransmittedPacketsRate() const120 DataRate PccMonitorInterval::GetTransmittedPacketsRate() const {
121 if (received_packets_.empty()) {
122 return target_sending_rate_;
123 }
124 Timestamp receive_time_of_first_packet =
125 received_packets_.front().sent_time + received_packets_.front().delay;
126 Timestamp receive_time_of_last_packet =
127 received_packets_.back().sent_time + received_packets_.back().delay;
128 if (receive_time_of_first_packet == receive_time_of_last_packet) {
129 RTC_LOG(LS_WARNING)
130 << "All packets in monitor interval were received at the same time.";
131 return target_sending_rate_;
132 }
133 return received_packets_size_ /
134 (receive_time_of_last_packet - receive_time_of_first_packet);
135 }
136
137 } // namespace pcc
138 } // namespace webrtc
139