• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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