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.IsReceived()) {
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 for (const ReceivedPacket& packet : received_packets_) {
74 double time_delta_us =
75 (packet.sent_time - received_packets_[0].sent_time).us();
76 sum_times += time_delta_us;
77 }
78 double sum_squared_scaled_time_deltas = 0;
79 double sum_scaled_time_delta_dot_delay = 0;
80 for (const ReceivedPacket& packet : received_packets_) {
81 double time_delta_us =
82 (packet.sent_time - received_packets_[0].sent_time).us();
83 double delay = packet.delay.us();
84 double scaled_time_delta_us =
85 time_delta_us - sum_times / received_packets_.size();
86 sum_squared_scaled_time_deltas +=
87 scaled_time_delta_us * scaled_time_delta_us;
88 sum_scaled_time_delta_dot_delay += scaled_time_delta_us * delay;
89 }
90 double rtt_gradient =
91 sum_scaled_time_delta_dot_delay / sum_squared_scaled_time_deltas;
92 if (std::abs(rtt_gradient) < delay_gradient_threshold)
93 rtt_gradient = 0;
94 return rtt_gradient;
95 }
96
IsFeedbackCollectionDone() const97 bool PccMonitorInterval::IsFeedbackCollectionDone() const {
98 return feedback_collection_done_;
99 }
100
GetEndTime() const101 Timestamp PccMonitorInterval::GetEndTime() const {
102 return start_time_ + interval_duration_;
103 }
104
GetLossRate() const105 double PccMonitorInterval::GetLossRate() const {
106 size_t packets_lost = lost_packets_sent_time_.size();
107 size_t packets_received = received_packets_.size();
108 if (packets_lost == 0)
109 return 0;
110 return static_cast<double>(packets_lost) / (packets_lost + packets_received);
111 }
112
GetTargetSendingRate() const113 DataRate PccMonitorInterval::GetTargetSendingRate() const {
114 return target_sending_rate_;
115 }
116
GetTransmittedPacketsRate() const117 DataRate PccMonitorInterval::GetTransmittedPacketsRate() const {
118 if (received_packets_.empty()) {
119 return target_sending_rate_;
120 }
121 Timestamp receive_time_of_first_packet =
122 received_packets_.front().sent_time + received_packets_.front().delay;
123 Timestamp receive_time_of_last_packet =
124 received_packets_.back().sent_time + received_packets_.back().delay;
125 if (receive_time_of_first_packet == receive_time_of_last_packet) {
126 RTC_LOG(LS_WARNING)
127 << "All packets in monitor interval were received at the same time.";
128 return target_sending_rate_;
129 }
130 return received_packets_size_ /
131 (receive_time_of_last_packet - receive_time_of_first_packet);
132 }
133
134 } // namespace pcc
135 } // namespace webrtc
136