blob: fcc7ee3449a8b40fa277cb170243db55045e338e [file] [log] [blame]
Stefan Holmere5904162015-03-26 11:11:06 +01001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/pacing/packet_router.h"
Stefan Holmere5904162015-03-26 11:11:06 +010012
danilchap47085372017-08-10 06:03:57 -070013#include <algorithm>
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <cstdint>
danilchap47085372017-08-10 06:03:57 -070015#include <limits>
Per Kjellanderee153c92019-10-10 16:43:46 +020016#include <memory>
Erik Språng58ee1872019-06-18 16:20:11 +020017#include <utility>
danilchap47085372017-08-10 06:03:57 -070018
Yves Gerey988cc082018-10-23 12:03:01 +020019#include "absl/types/optional.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Per Kjellanderee153c92019-10-10 16:43:46 +020021#include "modules/rtp_rtcp/source/rtcp_packet.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +020023#include "modules/rtp_rtcp/source/rtp_rtcp_interface.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "rtc_base/checks.h"
Erik Språng58ee1872019-06-18 16:20:11 +020025#include "rtc_base/logging.h"
Steve Anton10542f22019-01-11 09:11:00 -080026#include "rtc_base/time_utils.h"
Johannes Kron913ea5d2020-06-01 23:28:44 +000027#include "rtc_base/trace_event.h"
Stefan Holmere5904162015-03-26 11:11:06 +010028
29namespace webrtc {
30
Erik Språng5f01bf62019-10-16 17:06:34 +020031PacketRouter::PacketRouter() : PacketRouter(0) {}
32
33PacketRouter::PacketRouter(uint16_t start_transport_seq)
Erik Språng8b7ca4a2018-05-17 13:43:35 +020034 : last_send_module_(nullptr),
eladalon822ff2b2017-08-01 06:30:28 -070035 active_remb_module_(nullptr),
Erik Språnga1888ae2020-07-02 12:02:36 +000036 transport_seq_(start_transport_seq) {}
Stefan Holmere5904162015-03-26 11:11:06 +010037
38PacketRouter::~PacketRouter() {
Erik Språngc06aef22019-10-17 13:02:27 +020039 RTC_DCHECK(send_modules_map_.empty());
40 RTC_DCHECK(send_modules_list_.empty());
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010041 RTC_DCHECK(rtcp_feedback_senders_.empty());
eladalon822ff2b2017-08-01 06:30:28 -070042 RTC_DCHECK(sender_remb_candidates_.empty());
43 RTC_DCHECK(receiver_remb_candidates_.empty());
44 RTC_DCHECK(active_remb_module_ == nullptr);
Stefan Holmere5904162015-03-26 11:11:06 +010045}
46
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +020047void PacketRouter::AddSendRtpModule(RtpRtcpInterface* rtp_module,
48 bool remb_candidate) {
Markus Handell1e79c9b2020-06-10 15:12:15 +020049 MutexLock lock(&modules_mutex_);
Erik Språngc06aef22019-10-17 13:02:27 +020050
51 AddSendRtpModuleToMap(rtp_module, rtp_module->SSRC());
52 if (absl::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) {
53 AddSendRtpModuleToMap(rtp_module, *rtx_ssrc);
54 }
55 if (absl::optional<uint32_t> flexfec_ssrc = rtp_module->FlexfecSsrc()) {
56 AddSendRtpModuleToMap(rtp_module, *flexfec_ssrc);
57 }
58
Erik Språng4208a132019-08-26 08:58:45 +020059 if (rtp_module->SupportsRtxPayloadPadding()) {
Erik Språngc06aef22019-10-17 13:02:27 +020060 last_send_module_ = rtp_module;
stefan16b02212017-01-27 07:12:16 -080061 }
eladalon822ff2b2017-08-01 06:30:28 -070062
63 if (remb_candidate) {
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010064 AddRembModuleCandidate(rtp_module, /* media_sender = */ true);
eladalon822ff2b2017-08-01 06:30:28 -070065 }
Stefan Holmere5904162015-03-26 11:11:06 +010066}
67
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +020068void PacketRouter::AddSendRtpModuleToMap(RtpRtcpInterface* rtp_module,
69 uint32_t ssrc) {
Erik Språngc06aef22019-10-17 13:02:27 +020070 RTC_DCHECK(send_modules_map_.find(ssrc) == send_modules_map_.end());
Erik Språngb6bbdeb2021-08-13 16:12:41 +020071
72 // Signal to module that the pacer thread is attached and can send packets.
73 rtp_module->OnPacketSendingThreadSwitched();
74
Erik Språng1e51a382019-12-11 16:47:09 +010075 // Always keep the audio modules at the back of the list, so that when we
76 // iterate over the modules in order to find one that can send padding we
77 // will prioritize video. This is important to make sure they are counted
78 // into the bandwidth estimate properly.
79 if (rtp_module->IsAudioConfigured()) {
80 send_modules_list_.push_back(rtp_module);
81 } else {
82 send_modules_list_.push_front(rtp_module);
83 }
84 send_modules_map_[ssrc] = rtp_module;
Erik Språngc06aef22019-10-17 13:02:27 +020085}
86
87void PacketRouter::RemoveSendRtpModuleFromMap(uint32_t ssrc) {
88 auto kv = send_modules_map_.find(ssrc);
89 RTC_DCHECK(kv != send_modules_map_.end());
Erik Språng1e51a382019-12-11 16:47:09 +010090 send_modules_list_.remove(kv->second);
Erik Språngc06aef22019-10-17 13:02:27 +020091 send_modules_map_.erase(kv);
92}
93
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +020094void PacketRouter::RemoveSendRtpModule(RtpRtcpInterface* rtp_module) {
Markus Handell1e79c9b2020-06-10 15:12:15 +020095 MutexLock lock(&modules_mutex_);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010096 MaybeRemoveRembModuleCandidate(rtp_module, /* media_sender = */ true);
Erik Språngc06aef22019-10-17 13:02:27 +020097
98 RemoveSendRtpModuleFromMap(rtp_module->SSRC());
99 if (absl::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) {
100 RemoveSendRtpModuleFromMap(*rtx_ssrc);
101 }
102 if (absl::optional<uint32_t> flexfec_ssrc = rtp_module->FlexfecSsrc()) {
103 RemoveSendRtpModuleFromMap(*flexfec_ssrc);
104 }
105
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200106 if (last_send_module_ == rtp_module) {
107 last_send_module_ = nullptr;
108 }
Erik Språngb6bbdeb2021-08-13 16:12:41 +0200109 rtp_module->OnPacketSendingThreadSwitched();
nissefdbfdc92017-03-31 05:44:52 -0700110}
111
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100112void PacketRouter::AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender,
eladalon822ff2b2017-08-01 06:30:28 -0700113 bool remb_candidate) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200114 MutexLock lock(&modules_mutex_);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100115 RTC_DCHECK(std::find(rtcp_feedback_senders_.begin(),
116 rtcp_feedback_senders_.end(),
117 rtcp_sender) == rtcp_feedback_senders_.end());
eladalon822ff2b2017-08-01 06:30:28 -0700118
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100119 rtcp_feedback_senders_.push_back(rtcp_sender);
eladalon822ff2b2017-08-01 06:30:28 -0700120
121 if (remb_candidate) {
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100122 AddRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
eladalon822ff2b2017-08-01 06:30:28 -0700123 }
nissefdbfdc92017-03-31 05:44:52 -0700124}
125
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100126void PacketRouter::RemoveReceiveRtpModule(
127 RtcpFeedbackSenderInterface* rtcp_sender) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200128 MutexLock lock(&modules_mutex_);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100129 MaybeRemoveRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
130 auto it = std::find(rtcp_feedback_senders_.begin(),
131 rtcp_feedback_senders_.end(), rtcp_sender);
132 RTC_DCHECK(it != rtcp_feedback_senders_.end());
133 rtcp_feedback_senders_.erase(it);
Stefan Holmere5904162015-03-26 11:11:06 +0100134}
135
Erik Språng58ee1872019-06-18 16:20:11 +0200136void PacketRouter::SendPacket(std::unique_ptr<RtpPacketToSend> packet,
137 const PacedPacketInfo& cluster_info) {
Johannes Kron913ea5d2020-06-01 23:28:44 +0000138 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"), "PacketRouter::SendPacket",
139 "sequence_number", packet->SequenceNumber(), "rtp_timestamp",
140 packet->Timestamp());
141
Markus Handell1e79c9b2020-06-10 15:12:15 +0200142 MutexLock lock(&modules_mutex_);
Erik Språngf6468d22019-07-05 16:53:43 +0200143 // With the new pacer code path, transport sequence numbers are only set here,
144 // on the pacer thread. Therefore we don't need atomics/synchronization.
Danil Chapovalov629de6f2020-01-16 18:59:01 +0100145 if (packet->HasExtension<TransportSequenceNumber>()) {
Erik Språng13a8e162019-10-21 19:39:57 +0200146 packet->SetExtension<TransportSequenceNumber>((++transport_seq_) & 0xFFFF);
Erik Språngf6468d22019-07-05 16:53:43 +0200147 }
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000148
Erik Språngc06aef22019-10-17 13:02:27 +0200149 uint32_t ssrc = packet->Ssrc();
150 auto kv = send_modules_map_.find(ssrc);
151 if (kv == send_modules_map_.end()) {
152 RTC_LOG(LS_WARNING)
153 << "Failed to send packet, matching RTP module not found "
154 "or transport error. SSRC = "
155 << packet->Ssrc() << ", sequence number " << packet->SequenceNumber();
156 return;
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000157 }
158
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +0200159 RtpRtcpInterface* rtp_module = kv->second;
Erik Språngc06aef22019-10-17 13:02:27 +0200160 if (!rtp_module->TrySendPacket(packet.get(), cluster_info)) {
161 RTC_LOG(LS_WARNING) << "Failed to send packet, rejected by RTP module.";
162 return;
Erik Språng58ee1872019-06-18 16:20:11 +0200163 }
164
Erik Språngc06aef22019-10-17 13:02:27 +0200165 if (rtp_module->SupportsRtxPayloadPadding()) {
166 // This is now the last module to send media, and has the desired
167 // properties needed for payload based padding. Cache it for later use.
168 last_send_module_ = rtp_module;
169 }
Erik Språng1d50cb62020-07-02 17:41:32 +0200170
171 for (auto& packet : rtp_module->FetchFecPackets()) {
172 pending_fec_packets_.push_back(std::move(packet));
173 }
174}
175
176std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::FetchFec() {
177 MutexLock lock(&modules_mutex_);
178 std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
179 std::move(pending_fec_packets_);
180 pending_fec_packets_.clear();
181 return fec_packets;
Erik Språng58ee1872019-06-18 16:20:11 +0200182}
183
Erik Språngf6468d22019-07-05 16:53:43 +0200184std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::GeneratePadding(
Erik Språnged1fb192020-06-30 11:53:37 +0000185 DataSize size) {
Johannes Kron913ea5d2020-06-01 23:28:44 +0000186 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("webrtc"),
Erik Språnged1fb192020-06-30 11:53:37 +0000187 "PacketRouter::GeneratePadding", "bytes", size.bytes());
Johannes Kron913ea5d2020-06-01 23:28:44 +0000188
Markus Handell1e79c9b2020-06-10 15:12:15 +0200189 MutexLock lock(&modules_mutex_);
Erik Språng478cb462019-06-26 15:49:27 +0200190 // First try on the last rtp module to have sent media. This increases the
191 // the chance that any payload based padding will be useful as it will be
192 // somewhat distributed over modules according the packet rate, even if it
193 // will be more skewed towards the highest bitrate stream. At the very least
194 // this prevents sending payload padding on a disabled stream where it's
195 // guaranteed not to be useful.
Erik Språngc06aef22019-10-17 13:02:27 +0200196 std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets;
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000197 if (last_send_module_ != nullptr &&
198 last_send_module_->SupportsRtxPayloadPadding()) {
Erik Språnged1fb192020-06-30 11:53:37 +0000199 padding_packets = last_send_module_->GeneratePadding(size.bytes());
Erik Språng478cb462019-06-26 15:49:27 +0200200 }
Erik Språngf6468d22019-07-05 16:53:43 +0200201
Johannes Kron913ea5d2020-06-01 23:28:44 +0000202 if (padding_packets.empty()) {
203 // Iterate over all modules send module. Video modules will be at the front
204 // and so will be prioritized. This is important since audio packets may not
205 // be taken into account by the bandwidth estimator, e.g. in FF.
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +0200206 for (RtpRtcpInterface* rtp_module : send_modules_list_) {
Johannes Kron913ea5d2020-06-01 23:28:44 +0000207 if (rtp_module->SupportsPadding()) {
Erik Språnged1fb192020-06-30 11:53:37 +0000208 padding_packets = rtp_module->GeneratePadding(size.bytes());
Johannes Kron913ea5d2020-06-01 23:28:44 +0000209 if (!padding_packets.empty()) {
210 last_send_module_ = rtp_module;
211 break;
212 }
Casey Fischer45bb7172020-06-01 18:38:55 +0000213 }
214 }
Erik Språngc06aef22019-10-17 13:02:27 +0200215 }
216
Johannes Kron913ea5d2020-06-01 23:28:44 +0000217#if RTC_TRACE_EVENTS_ENABLED
218 for (auto& packet : padding_packets) {
219 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"),
220 "PacketRouter::GeneratePadding::Loop", "sequence_number",
221 packet->SequenceNumber(), "rtp_timestamp",
222 packet->Timestamp());
223 }
224#endif
225
Erik Språngc06aef22019-10-17 13:02:27 +0200226 return padding_packets;
Erik Språng478cb462019-06-26 15:49:27 +0200227}
228
Erik Språng5f01bf62019-10-16 17:06:34 +0200229uint16_t PacketRouter::CurrentTransportSequenceNumber() const {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200230 MutexLock lock(&modules_mutex_);
Erik Språng13a8e162019-10-21 19:39:57 +0200231 return transport_seq_ & 0xFFFF;
sprang867fb522015-08-03 04:38:41 -0700232}
233
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200234void PacketRouter::SendRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200235 MutexLock lock(&modules_mutex_);
eladalon822ff2b2017-08-01 06:30:28 -0700236
237 if (!active_remb_module_) {
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200238 return;
eladalon822ff2b2017-08-01 06:30:28 -0700239 }
240
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200241 // The Add* and Remove* methods above ensure that REMB is disabled on all
242 // other modules, because otherwise, they will send REMB with stale info.
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200243 active_remb_module_->SetRemb(bitrate_bps, std::move(ssrcs));
nisse05843312017-04-18 23:38:35 -0700244}
245
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200246void PacketRouter::SendCombinedRtcpPacket(
Per Kjellanderee153c92019-10-10 16:43:46 +0200247 std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200248 MutexLock lock(&modules_mutex_);
Per Kjellanderee153c92019-10-10 16:43:46 +0200249
nissefdbfdc92017-03-31 05:44:52 -0700250 // Prefer send modules.
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +0200251 for (RtpRtcpInterface* rtp_module : send_modules_list_) {
Per Kjellanderee153c92019-10-10 16:43:46 +0200252 if (rtp_module->RTCP() == RtcpMode::kOff) {
253 continue;
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200254 }
Per Kjellanderee153c92019-10-10 16:43:46 +0200255 rtp_module->SendCombinedRtcpPacket(std::move(packets));
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200256 return;
nissefdbfdc92017-03-31 05:44:52 -0700257 }
sprang233bd872015-09-08 13:25:16 -0700258
Per Kjellanderee153c92019-10-10 16:43:46 +0200259 if (rtcp_feedback_senders_.empty()) {
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200260 return;
Per Kjellander52f7ae72019-09-10 19:28:06 +0200261 }
Per Kjellanderee153c92019-10-10 16:43:46 +0200262 auto* rtcp_sender = rtcp_feedback_senders_[0];
263 rtcp_sender->SendCombinedRtcpPacket(std::move(packets));
Per Kjellander52f7ae72019-09-10 19:28:06 +0200264}
265
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100266void PacketRouter::AddRembModuleCandidate(
267 RtcpFeedbackSenderInterface* candidate_module,
268 bool media_sender) {
eladalon822ff2b2017-08-01 06:30:28 -0700269 RTC_DCHECK(candidate_module);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100270 std::vector<RtcpFeedbackSenderInterface*>& candidates =
271 media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
eladalon822ff2b2017-08-01 06:30:28 -0700272 RTC_DCHECK(std::find(candidates.cbegin(), candidates.cend(),
273 candidate_module) == candidates.cend());
274 candidates.push_back(candidate_module);
275 DetermineActiveRembModule();
276}
277
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100278void PacketRouter::MaybeRemoveRembModuleCandidate(
279 RtcpFeedbackSenderInterface* candidate_module,
280 bool media_sender) {
eladalon822ff2b2017-08-01 06:30:28 -0700281 RTC_DCHECK(candidate_module);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100282 std::vector<RtcpFeedbackSenderInterface*>& candidates =
283 media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
eladalon822ff2b2017-08-01 06:30:28 -0700284 auto it = std::find(candidates.begin(), candidates.end(), candidate_module);
285
286 if (it == candidates.end()) {
287 return; // Function called due to removal of non-REMB-candidate module.
288 }
289
290 if (*it == active_remb_module_) {
291 UnsetActiveRembModule();
292 }
293 candidates.erase(it);
294 DetermineActiveRembModule();
295}
296
297void PacketRouter::UnsetActiveRembModule() {
298 RTC_CHECK(active_remb_module_);
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200299 active_remb_module_->UnsetRemb();
eladalon822ff2b2017-08-01 06:30:28 -0700300 active_remb_module_ = nullptr;
301}
302
303void PacketRouter::DetermineActiveRembModule() {
304 // Sender modules take precedence over receiver modules, because SRs (sender
305 // reports) are sent more frequently than RR (receiver reports).
306 // When adding the first sender module, we should change the active REMB
307 // module to be that. Otherwise, we remain with the current active module.
308
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100309 RtcpFeedbackSenderInterface* new_active_remb_module;
eladalon822ff2b2017-08-01 06:30:28 -0700310
311 if (!sender_remb_candidates_.empty()) {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200312 new_active_remb_module = sender_remb_candidates_.front();
eladalon822ff2b2017-08-01 06:30:28 -0700313 } else if (!receiver_remb_candidates_.empty()) {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200314 new_active_remb_module = receiver_remb_candidates_.front();
eladalon822ff2b2017-08-01 06:30:28 -0700315 } else {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200316 new_active_remb_module = nullptr;
eladalon822ff2b2017-08-01 06:30:28 -0700317 }
318
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200319 if (new_active_remb_module != active_remb_module_ && active_remb_module_) {
320 UnsetActiveRembModule();
eladalon822ff2b2017-08-01 06:30:28 -0700321 }
322
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200323 active_remb_module_ = new_active_remb_module;
eladalon822ff2b2017-08-01 06:30:28 -0700324}
325
Stefan Holmere5904162015-03-26 11:11:06 +0100326} // namespace webrtc