Line data Source code
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:
34 0 : inline bool operator()(const PacketInfo& lhs, const PacketInfo& rhs) {
35 0 : if (lhs.arrival_time_ms != rhs.arrival_time_ms)
36 0 : return lhs.arrival_time_ms < rhs.arrival_time_ms;
37 0 : if (lhs.send_time_ms != rhs.send_time_ms)
38 0 : return lhs.send_time_ms < rhs.send_time_ms;
39 0 : return lhs.sequence_number < rhs.sequence_number;
40 : }
41 : };
42 :
43 0 : TransportFeedbackAdapter::TransportFeedbackAdapter(
44 : Clock* clock,
45 0 : 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 0 : bitrate_controller_(bitrate_controller) {}
52 :
53 0 : TransportFeedbackAdapter::~TransportFeedbackAdapter() {}
54 :
55 0 : void TransportFeedbackAdapter::InitBwe() {
56 0 : rtc::CritScope cs(&bwe_lock_);
57 0 : delay_based_bwe_.reset(new DelayBasedBwe(clock_));
58 0 : }
59 :
60 0 : void TransportFeedbackAdapter::AddPacket(uint16_t sequence_number,
61 : size_t length,
62 : int probe_cluster_id) {
63 0 : rtc::CritScope cs(&lock_);
64 0 : if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe-WithOverhead") ==
65 : "Enabled") {
66 0 : length += transport_overhead_bytes_per_packet_;
67 : }
68 0 : send_time_history_.AddAndRemoveOld(sequence_number, length, probe_cluster_id);
69 0 : }
70 :
71 0 : void TransportFeedbackAdapter::OnSentPacket(uint16_t sequence_number,
72 : int64_t send_time_ms) {
73 0 : rtc::CritScope cs(&lock_);
74 0 : send_time_history_.OnSentPacket(sequence_number, send_time_ms);
75 0 : }
76 :
77 0 : void TransportFeedbackAdapter::SetMinBitrate(int min_bitrate_bps) {
78 0 : rtc::CritScope cs(&bwe_lock_);
79 0 : delay_based_bwe_->SetMinBitrate(min_bitrate_bps);
80 0 : }
81 :
82 0 : void TransportFeedbackAdapter::SetTransportOverhead(
83 : int transport_overhead_bytes_per_packet) {
84 0 : rtc::CritScope cs(&lock_);
85 0 : transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
86 0 : }
87 :
88 0 : int64_t TransportFeedbackAdapter::GetProbingIntervalMs() const {
89 0 : rtc::CritScope cs(&bwe_lock_);
90 0 : return delay_based_bwe_->GetProbingIntervalMs();
91 : }
92 :
93 0 : std::vector<PacketInfo> TransportFeedbackAdapter::GetPacketFeedbackVector(
94 : const rtcp::TransportFeedback& feedback) {
95 0 : 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 0 : if (last_timestamp_us_ == kNoTimestamp) {
100 0 : current_offset_ms_ = clock_->TimeInMilliseconds();
101 : } else {
102 0 : int64_t delta = timestamp_us - last_timestamp_us_;
103 :
104 : // Detect and compensate for wrap-arounds in base time.
105 0 : if (std::abs(delta - kBaseTimestampRangeSizeUs) < std::abs(delta)) {
106 0 : delta -= kBaseTimestampRangeSizeUs; // Wrap backwards.
107 0 : } else if (std::abs(delta + kBaseTimestampRangeSizeUs) < std::abs(delta)) {
108 0 : delta += kBaseTimestampRangeSizeUs; // Wrap forwards.
109 : }
110 :
111 0 : current_offset_ms_ += delta / 1000;
112 : }
113 0 : last_timestamp_us_ = timestamp_us;
114 :
115 0 : uint16_t sequence_number = feedback.GetBaseSequence();
116 0 : std::vector<int64_t> delta_vec = feedback.GetReceiveDeltasUs();
117 0 : auto delta_it = delta_vec.begin();
118 0 : std::vector<PacketInfo> packet_feedback_vector;
119 0 : packet_feedback_vector.reserve(delta_vec.size());
120 :
121 : {
122 0 : rtc::CritScope cs(&lock_);
123 0 : size_t failed_lookups = 0;
124 0 : int64_t offset_us = 0;
125 0 : for (auto symbol : feedback.GetStatusVector()) {
126 0 : if (symbol != rtcp::TransportFeedback::StatusSymbol::kNotReceived) {
127 0 : RTC_DCHECK(delta_it != delta_vec.end());
128 0 : offset_us += *(delta_it++);
129 0 : int64_t timestamp_ms = current_offset_ms_ + (offset_us / 1000);
130 0 : PacketInfo info(timestamp_ms, sequence_number);
131 0 : if (send_time_history_.GetInfo(&info, true) && info.send_time_ms >= 0) {
132 0 : packet_feedback_vector.push_back(info);
133 : } else {
134 0 : ++failed_lookups;
135 : }
136 : }
137 0 : ++sequence_number;
138 : }
139 0 : std::sort(packet_feedback_vector.begin(), packet_feedback_vector.end(),
140 0 : PacketInfoComparator());
141 0 : RTC_DCHECK(delta_it == delta_vec.end());
142 0 : if (failed_lookups > 0) {
143 0 : LOG(LS_WARNING) << "Failed to lookup send time for " << failed_lookups
144 : << " packet" << (failed_lookups > 1 ? "s" : "")
145 0 : << ". Send time history too small?";
146 : }
147 : }
148 0 : return packet_feedback_vector;
149 : }
150 :
151 0 : void TransportFeedbackAdapter::OnTransportFeedback(
152 : const rtcp::TransportFeedback& feedback) {
153 0 : last_packet_feedback_vector_ = GetPacketFeedbackVector(feedback);
154 0 : DelayBasedBwe::Result result;
155 : {
156 0 : rtc::CritScope cs(&bwe_lock_);
157 : result = delay_based_bwe_->IncomingPacketFeedbackVector(
158 0 : last_packet_feedback_vector_);
159 : }
160 0 : if (result.updated)
161 0 : bitrate_controller_->OnDelayBasedBweResult(result);
162 0 : }
163 :
164 0 : std::vector<PacketInfo> TransportFeedbackAdapter::GetTransportFeedbackVector()
165 : const {
166 0 : return last_packet_feedback_vector_;
167 : }
168 :
169 0 : void TransportFeedbackAdapter::OnRttUpdate(int64_t avg_rtt_ms,
170 : int64_t max_rtt_ms) {
171 0 : rtc::CritScope cs(&bwe_lock_);
172 0 : delay_based_bwe_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
173 0 : }
174 :
175 : } // namespace webrtc
|