1 /*
2  *  Copyright (c) 2015 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 "webrtc/modules/congestion_controller/transport_feedback_adapter.h"
12 
13 #include <algorithm>
14 #include <limits>
15 
16 #include "webrtc/base/checks.h"
17 #include "webrtc/base/logging.h"
18 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
19 #include "webrtc/modules/congestion_controller/delay_based_bwe.h"
20 #include "webrtc/modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
21 #include "webrtc/modules/utility/include/process_thread.h"
22 #include "webrtc/system_wrappers/include/field_trial.h"
23 
24 namespace webrtc {
25 
26 const int64_t kNoTimestamp = -1;
27 const int64_t kSendTimeHistoryWindowMs = 10000;
28 const int64_t kBaseTimestampScaleFactor =
29     rtcp::TransportFeedback::kDeltaScaleFactor * (1 << 8);
30 const int64_t kBaseTimestampRangeSizeUs = kBaseTimestampScaleFactor * (1 << 24);
31 
32 class PacketInfoComparator {
33  public:
operator ()(const PacketInfo & lhs,const PacketInfo & rhs)34   inline bool operator()(const PacketInfo& lhs, const PacketInfo& rhs) {
35     if (lhs.arrival_time_ms != rhs.arrival_time_ms)
36       return lhs.arrival_time_ms < rhs.arrival_time_ms;
37     if (lhs.send_time_ms != rhs.send_time_ms)
38       return lhs.send_time_ms < rhs.send_time_ms;
39     return lhs.sequence_number < rhs.sequence_number;
40   }
41 };
42 
TransportFeedbackAdapter(Clock * clock,BitrateController * bitrate_controller)43 TransportFeedbackAdapter::TransportFeedbackAdapter(
44     Clock* clock,
45     BitrateController* bitrate_controller)
46     : transport_overhead_bytes_per_packet_(0),
47       send_time_history_(clock, kSendTimeHistoryWindowMs),
48       clock_(clock),
49       current_offset_ms_(kNoTimestamp),
50       last_timestamp_us_(kNoTimestamp),
51       bitrate_controller_(bitrate_controller) {}
52 
~TransportFeedbackAdapter()53 TransportFeedbackAdapter::~TransportFeedbackAdapter() {}
54 
InitBwe()55 void TransportFeedbackAdapter::InitBwe() {
56   rtc::CritScope cs(&bwe_lock_);
57   delay_based_bwe_.reset(new DelayBasedBwe(clock_));
58 }
59 
AddPacket(uint16_t sequence_number,size_t length,int probe_cluster_id)60 void TransportFeedbackAdapter::AddPacket(uint16_t sequence_number,
61                                          size_t length,
62                                          int probe_cluster_id) {
63   rtc::CritScope cs(&lock_);
64   if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe-WithOverhead") ==
65       "Enabled") {
66     length += transport_overhead_bytes_per_packet_;
67   }
68   send_time_history_.AddAndRemoveOld(sequence_number, length, probe_cluster_id);
69 }
70 
OnSentPacket(uint16_t sequence_number,int64_t send_time_ms)71 void TransportFeedbackAdapter::OnSentPacket(uint16_t sequence_number,
72                                             int64_t send_time_ms) {
73   rtc::CritScope cs(&lock_);
74   send_time_history_.OnSentPacket(sequence_number, send_time_ms);
75 }
76 
SetMinBitrate(int min_bitrate_bps)77 void TransportFeedbackAdapter::SetMinBitrate(int min_bitrate_bps) {
78   rtc::CritScope cs(&bwe_lock_);
79   delay_based_bwe_->SetMinBitrate(min_bitrate_bps);
80 }
81 
SetTransportOverhead(int transport_overhead_bytes_per_packet)82 void TransportFeedbackAdapter::SetTransportOverhead(
83     int transport_overhead_bytes_per_packet) {
84   rtc::CritScope cs(&lock_);
85   transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
86 }
87 
GetProbingIntervalMs() const88 int64_t TransportFeedbackAdapter::GetProbingIntervalMs() const {
89   rtc::CritScope cs(&bwe_lock_);
90   return delay_based_bwe_->GetProbingIntervalMs();
91 }
92 
GetPacketFeedbackVector(const rtcp::TransportFeedback & feedback)93 std::vector<PacketInfo> TransportFeedbackAdapter::GetPacketFeedbackVector(
94     const rtcp::TransportFeedback& feedback) {
95   int64_t timestamp_us = feedback.GetBaseTimeUs();
96   // Add timestamp deltas to a local time base selected on first packet arrival.
97   // This won't be the true time base, but makes it easier to manually inspect
98   // time stamps.
99   if (last_timestamp_us_ == kNoTimestamp) {
100     current_offset_ms_ = clock_->TimeInMilliseconds();
101   } else {
102     int64_t delta = timestamp_us - last_timestamp_us_;
103 
104     // Detect and compensate for wrap-arounds in base time.
105     if (std::abs(delta - kBaseTimestampRangeSizeUs) < std::abs(delta)) {
106       delta -= kBaseTimestampRangeSizeUs;  // Wrap backwards.
107     } else if (std::abs(delta + kBaseTimestampRangeSizeUs) < std::abs(delta)) {
108       delta += kBaseTimestampRangeSizeUs;  // Wrap forwards.
109     }
110 
111     current_offset_ms_ += delta / 1000;
112   }
113   last_timestamp_us_ = timestamp_us;
114 
115   uint16_t sequence_number = feedback.GetBaseSequence();
116   std::vector<int64_t> delta_vec = feedback.GetReceiveDeltasUs();
117   auto delta_it = delta_vec.begin();
118   std::vector<PacketInfo> packet_feedback_vector;
119   packet_feedback_vector.reserve(delta_vec.size());
120 
121   {
122     rtc::CritScope cs(&lock_);
123     size_t failed_lookups = 0;
124     int64_t offset_us = 0;
125     for (auto symbol : feedback.GetStatusVector()) {
126       if (symbol != rtcp::TransportFeedback::StatusSymbol::kNotReceived) {
127         RTC_DCHECK(delta_it != delta_vec.end());
128         offset_us += *(delta_it++);
129         int64_t timestamp_ms = current_offset_ms_ + (offset_us / 1000);
130         PacketInfo info(timestamp_ms, sequence_number);
131         if (send_time_history_.GetInfo(&info, true) && info.send_time_ms >= 0) {
132           packet_feedback_vector.push_back(info);
133         } else {
134           ++failed_lookups;
135         }
136       }
137       ++sequence_number;
138     }
139     std::sort(packet_feedback_vector.begin(), packet_feedback_vector.end(),
140               PacketInfoComparator());
141     RTC_DCHECK(delta_it == delta_vec.end());
142     if (failed_lookups > 0) {
143       LOG(LS_WARNING) << "Failed to lookup send time for " << failed_lookups
144                       << " packet" << (failed_lookups > 1 ? "s" : "")
145                       << ". Send time history too small?";
146     }
147   }
148   return packet_feedback_vector;
149 }
150 
OnTransportFeedback(const rtcp::TransportFeedback & feedback)151 void TransportFeedbackAdapter::OnTransportFeedback(
152     const rtcp::TransportFeedback& feedback) {
153   last_packet_feedback_vector_ = GetPacketFeedbackVector(feedback);
154   DelayBasedBwe::Result result;
155   {
156     rtc::CritScope cs(&bwe_lock_);
157     result = delay_based_bwe_->IncomingPacketFeedbackVector(
158         last_packet_feedback_vector_);
159   }
160   if (result.updated)
161     bitrate_controller_->OnDelayBasedBweResult(result);
162 }
163 
GetTransportFeedbackVector() const164 std::vector<PacketInfo> TransportFeedbackAdapter::GetTransportFeedbackVector()
165     const {
166   return last_packet_feedback_vector_;
167 }
168 
OnRttUpdate(int64_t avg_rtt_ms,int64_t max_rtt_ms)169 void TransportFeedbackAdapter::OnRttUpdate(int64_t avg_rtt_ms,
170                                            int64_t max_rtt_ms) {
171   rtc::CritScope cs(&bwe_lock_);
172   delay_based_bwe_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
173 }
174 
175 }  // namespace webrtc
176