blob: a09f191bbd8b6ad887f4f440b712fbd529b32bb3 [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"
Jianhui Daib1ba8532022-05-13 10:40:25 +080026#include "rtc_base/system/unused.h"
Steve Anton10542f22019-01-11 09:11:00 -080027#include "rtc_base/time_utils.h"
Johannes Kron913ea5d2020-06-01 23:28:44 +000028#include "rtc_base/trace_event.h"
Stefan Holmere5904162015-03-26 11:11:06 +010029
30namespace webrtc {
31
Erik Språng5f01bf62019-10-16 17:06:34 +020032PacketRouter::PacketRouter() : PacketRouter(0) {}
33
34PacketRouter::PacketRouter(uint16_t start_transport_seq)
Erik Språng8b7ca4a2018-05-17 13:43:35 +020035 : last_send_module_(nullptr),
eladalon822ff2b2017-08-01 06:30:28 -070036 active_remb_module_(nullptr),
Erik Språnga1888ae2020-07-02 12:02:36 +000037 transport_seq_(start_transport_seq) {}
Stefan Holmere5904162015-03-26 11:11:06 +010038
39PacketRouter::~PacketRouter() {
Erik Språngc06aef22019-10-17 13:02:27 +020040 RTC_DCHECK(send_modules_map_.empty());
41 RTC_DCHECK(send_modules_list_.empty());
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010042 RTC_DCHECK(rtcp_feedback_senders_.empty());
eladalon822ff2b2017-08-01 06:30:28 -070043 RTC_DCHECK(sender_remb_candidates_.empty());
44 RTC_DCHECK(receiver_remb_candidates_.empty());
45 RTC_DCHECK(active_remb_module_ == nullptr);
Stefan Holmere5904162015-03-26 11:11:06 +010046}
47
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +020048void PacketRouter::AddSendRtpModule(RtpRtcpInterface* rtp_module,
49 bool remb_candidate) {
Markus Handell1e79c9b2020-06-10 15:12:15 +020050 MutexLock lock(&modules_mutex_);
Erik Språngc06aef22019-10-17 13:02:27 +020051
52 AddSendRtpModuleToMap(rtp_module, rtp_module->SSRC());
53 if (absl::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) {
54 AddSendRtpModuleToMap(rtp_module, *rtx_ssrc);
55 }
56 if (absl::optional<uint32_t> flexfec_ssrc = rtp_module->FlexfecSsrc()) {
57 AddSendRtpModuleToMap(rtp_module, *flexfec_ssrc);
58 }
59
Erik Språng4208a132019-08-26 08:58:45 +020060 if (rtp_module->SupportsRtxPayloadPadding()) {
Erik Språngc06aef22019-10-17 13:02:27 +020061 last_send_module_ = rtp_module;
stefan16b02212017-01-27 07:12:16 -080062 }
eladalon822ff2b2017-08-01 06:30:28 -070063
64 if (remb_candidate) {
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010065 AddRembModuleCandidate(rtp_module, /* media_sender = */ true);
eladalon822ff2b2017-08-01 06:30:28 -070066 }
Stefan Holmere5904162015-03-26 11:11:06 +010067}
68
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +020069void PacketRouter::AddSendRtpModuleToMap(RtpRtcpInterface* rtp_module,
70 uint32_t ssrc) {
Erik Språngc06aef22019-10-17 13:02:27 +020071 RTC_DCHECK(send_modules_map_.find(ssrc) == send_modules_map_.end());
Erik Språngb6bbdeb2021-08-13 16:12:41 +020072
73 // Signal to module that the pacer thread is attached and can send packets.
74 rtp_module->OnPacketSendingThreadSwitched();
75
Erik Språng1e51a382019-12-11 16:47:09 +010076 // Always keep the audio modules at the back of the list, so that when we
77 // iterate over the modules in order to find one that can send padding we
78 // will prioritize video. This is important to make sure they are counted
79 // into the bandwidth estimate properly.
80 if (rtp_module->IsAudioConfigured()) {
81 send_modules_list_.push_back(rtp_module);
82 } else {
83 send_modules_list_.push_front(rtp_module);
84 }
85 send_modules_map_[ssrc] = rtp_module;
Erik Språngc06aef22019-10-17 13:02:27 +020086}
87
88void PacketRouter::RemoveSendRtpModuleFromMap(uint32_t ssrc) {
89 auto kv = send_modules_map_.find(ssrc);
90 RTC_DCHECK(kv != send_modules_map_.end());
Erik Språng1e51a382019-12-11 16:47:09 +010091 send_modules_list_.remove(kv->second);
Erik Språngc06aef22019-10-17 13:02:27 +020092 send_modules_map_.erase(kv);
93}
94
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +020095void PacketRouter::RemoveSendRtpModule(RtpRtcpInterface* rtp_module) {
Markus Handell1e79c9b2020-06-10 15:12:15 +020096 MutexLock lock(&modules_mutex_);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010097 MaybeRemoveRembModuleCandidate(rtp_module, /* media_sender = */ true);
Erik Språngc06aef22019-10-17 13:02:27 +020098
99 RemoveSendRtpModuleFromMap(rtp_module->SSRC());
100 if (absl::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) {
101 RemoveSendRtpModuleFromMap(*rtx_ssrc);
102 }
103 if (absl::optional<uint32_t> flexfec_ssrc = rtp_module->FlexfecSsrc()) {
104 RemoveSendRtpModuleFromMap(*flexfec_ssrc);
105 }
106
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200107 if (last_send_module_ == rtp_module) {
108 last_send_module_ = nullptr;
109 }
Erik Språngb6bbdeb2021-08-13 16:12:41 +0200110 rtp_module->OnPacketSendingThreadSwitched();
nissefdbfdc92017-03-31 05:44:52 -0700111}
112
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100113void PacketRouter::AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender,
eladalon822ff2b2017-08-01 06:30:28 -0700114 bool remb_candidate) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200115 MutexLock lock(&modules_mutex_);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100116 RTC_DCHECK(std::find(rtcp_feedback_senders_.begin(),
117 rtcp_feedback_senders_.end(),
118 rtcp_sender) == rtcp_feedback_senders_.end());
eladalon822ff2b2017-08-01 06:30:28 -0700119
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100120 rtcp_feedback_senders_.push_back(rtcp_sender);
eladalon822ff2b2017-08-01 06:30:28 -0700121
122 if (remb_candidate) {
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100123 AddRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
eladalon822ff2b2017-08-01 06:30:28 -0700124 }
nissefdbfdc92017-03-31 05:44:52 -0700125}
126
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100127void PacketRouter::RemoveReceiveRtpModule(
128 RtcpFeedbackSenderInterface* rtcp_sender) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200129 MutexLock lock(&modules_mutex_);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100130 MaybeRemoveRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
131 auto it = std::find(rtcp_feedback_senders_.begin(),
132 rtcp_feedback_senders_.end(), rtcp_sender);
133 RTC_DCHECK(it != rtcp_feedback_senders_.end());
134 rtcp_feedback_senders_.erase(it);
Stefan Holmere5904162015-03-26 11:11:06 +0100135}
136
Erik Språng58ee1872019-06-18 16:20:11 +0200137void PacketRouter::SendPacket(std::unique_ptr<RtpPacketToSend> packet,
138 const PacedPacketInfo& cluster_info) {
Johannes Kron913ea5d2020-06-01 23:28:44 +0000139 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"), "PacketRouter::SendPacket",
140 "sequence_number", packet->SequenceNumber(), "rtp_timestamp",
141 packet->Timestamp());
142
Markus Handell1e79c9b2020-06-10 15:12:15 +0200143 MutexLock lock(&modules_mutex_);
Erik Språngf6468d22019-07-05 16:53:43 +0200144 // With the new pacer code path, transport sequence numbers are only set here,
145 // on the pacer thread. Therefore we don't need atomics/synchronization.
Erik Språngc62e1b82022-06-11 12:18:47 +0200146 bool assign_transport_sequence_number =
147 packet->HasExtension<TransportSequenceNumber>();
148 if (assign_transport_sequence_number) {
149 packet->SetExtension<TransportSequenceNumber>((transport_seq_ + 1) &
150 0xFFFF);
Erik Språngf6468d22019-07-05 16:53:43 +0200151 }
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000152
Erik Språngc06aef22019-10-17 13:02:27 +0200153 uint32_t ssrc = packet->Ssrc();
154 auto kv = send_modules_map_.find(ssrc);
155 if (kv == send_modules_map_.end()) {
156 RTC_LOG(LS_WARNING)
157 << "Failed to send packet, matching RTP module not found "
158 "or transport error. SSRC = "
159 << packet->Ssrc() << ", sequence number " << packet->SequenceNumber();
160 return;
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000161 }
162
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +0200163 RtpRtcpInterface* rtp_module = kv->second;
Erik Språngc06aef22019-10-17 13:02:27 +0200164 if (!rtp_module->TrySendPacket(packet.get(), cluster_info)) {
165 RTC_LOG(LS_WARNING) << "Failed to send packet, rejected by RTP module.";
166 return;
Erik Språng58ee1872019-06-18 16:20:11 +0200167 }
168
Erik Språngc62e1b82022-06-11 12:18:47 +0200169 // Sending succeeded.
170
171 if (assign_transport_sequence_number) {
172 ++transport_seq_;
173 }
174
Erik Språngc06aef22019-10-17 13:02:27 +0200175 if (rtp_module->SupportsRtxPayloadPadding()) {
176 // This is now the last module to send media, and has the desired
177 // properties needed for payload based padding. Cache it for later use.
178 last_send_module_ = rtp_module;
179 }
Erik Språng1d50cb62020-07-02 17:41:32 +0200180
181 for (auto& packet : rtp_module->FetchFecPackets()) {
182 pending_fec_packets_.push_back(std::move(packet));
183 }
184}
185
186std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::FetchFec() {
187 MutexLock lock(&modules_mutex_);
188 std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
189 std::move(pending_fec_packets_);
190 pending_fec_packets_.clear();
191 return fec_packets;
Erik Språng58ee1872019-06-18 16:20:11 +0200192}
193
Erik Språngf6468d22019-07-05 16:53:43 +0200194std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::GeneratePadding(
Erik Språnged1fb192020-06-30 11:53:37 +0000195 DataSize size) {
Johannes Kron913ea5d2020-06-01 23:28:44 +0000196 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("webrtc"),
Erik Språnged1fb192020-06-30 11:53:37 +0000197 "PacketRouter::GeneratePadding", "bytes", size.bytes());
Johannes Kron913ea5d2020-06-01 23:28:44 +0000198
Markus Handell1e79c9b2020-06-10 15:12:15 +0200199 MutexLock lock(&modules_mutex_);
Erik Språng478cb462019-06-26 15:49:27 +0200200 // First try on the last rtp module to have sent media. This increases the
201 // the chance that any payload based padding will be useful as it will be
202 // somewhat distributed over modules according the packet rate, even if it
203 // will be more skewed towards the highest bitrate stream. At the very least
204 // this prevents sending payload padding on a disabled stream where it's
205 // guaranteed not to be useful.
Erik Språngc06aef22019-10-17 13:02:27 +0200206 std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets;
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000207 if (last_send_module_ != nullptr &&
208 last_send_module_->SupportsRtxPayloadPadding()) {
Erik Språnged1fb192020-06-30 11:53:37 +0000209 padding_packets = last_send_module_->GeneratePadding(size.bytes());
Erik Språng478cb462019-06-26 15:49:27 +0200210 }
Erik Språngf6468d22019-07-05 16:53:43 +0200211
Johannes Kron913ea5d2020-06-01 23:28:44 +0000212 if (padding_packets.empty()) {
213 // Iterate over all modules send module. Video modules will be at the front
214 // and so will be prioritized. This is important since audio packets may not
215 // be taken into account by the bandwidth estimator, e.g. in FF.
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +0200216 for (RtpRtcpInterface* rtp_module : send_modules_list_) {
Johannes Kron913ea5d2020-06-01 23:28:44 +0000217 if (rtp_module->SupportsPadding()) {
Erik Språnged1fb192020-06-30 11:53:37 +0000218 padding_packets = rtp_module->GeneratePadding(size.bytes());
Johannes Kron913ea5d2020-06-01 23:28:44 +0000219 if (!padding_packets.empty()) {
220 last_send_module_ = rtp_module;
221 break;
222 }
Casey Fischer45bb7172020-06-01 18:38:55 +0000223 }
224 }
Erik Språngc06aef22019-10-17 13:02:27 +0200225 }
226
Johannes Kron913ea5d2020-06-01 23:28:44 +0000227 for (auto& packet : padding_packets) {
Jianhui Daib1ba8532022-05-13 10:40:25 +0800228 RTC_UNUSED(packet);
Johannes Kron913ea5d2020-06-01 23:28:44 +0000229 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"),
230 "PacketRouter::GeneratePadding::Loop", "sequence_number",
231 packet->SequenceNumber(), "rtp_timestamp",
232 packet->Timestamp());
233 }
Johannes Kron913ea5d2020-06-01 23:28:44 +0000234
Erik Språngc06aef22019-10-17 13:02:27 +0200235 return padding_packets;
Erik Språng478cb462019-06-26 15:49:27 +0200236}
237
Erik Språng5f01bf62019-10-16 17:06:34 +0200238uint16_t PacketRouter::CurrentTransportSequenceNumber() const {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200239 MutexLock lock(&modules_mutex_);
Erik Språng13a8e162019-10-21 19:39:57 +0200240 return transport_seq_ & 0xFFFF;
sprang867fb522015-08-03 04:38:41 -0700241}
242
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200243void PacketRouter::SendRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200244 MutexLock lock(&modules_mutex_);
eladalon822ff2b2017-08-01 06:30:28 -0700245
246 if (!active_remb_module_) {
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200247 return;
eladalon822ff2b2017-08-01 06:30:28 -0700248 }
249
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200250 // The Add* and Remove* methods above ensure that REMB is disabled on all
251 // other modules, because otherwise, they will send REMB with stale info.
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200252 active_remb_module_->SetRemb(bitrate_bps, std::move(ssrcs));
nisse05843312017-04-18 23:38:35 -0700253}
254
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200255void PacketRouter::SendCombinedRtcpPacket(
Per Kjellanderee153c92019-10-10 16:43:46 +0200256 std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200257 MutexLock lock(&modules_mutex_);
Per Kjellanderee153c92019-10-10 16:43:46 +0200258
nissefdbfdc92017-03-31 05:44:52 -0700259 // Prefer send modules.
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +0200260 for (RtpRtcpInterface* rtp_module : send_modules_list_) {
Per Kjellanderee153c92019-10-10 16:43:46 +0200261 if (rtp_module->RTCP() == RtcpMode::kOff) {
262 continue;
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200263 }
Per Kjellanderee153c92019-10-10 16:43:46 +0200264 rtp_module->SendCombinedRtcpPacket(std::move(packets));
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200265 return;
nissefdbfdc92017-03-31 05:44:52 -0700266 }
sprang233bd872015-09-08 13:25:16 -0700267
Per Kjellanderee153c92019-10-10 16:43:46 +0200268 if (rtcp_feedback_senders_.empty()) {
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200269 return;
Per Kjellander52f7ae72019-09-10 19:28:06 +0200270 }
Per Kjellanderee153c92019-10-10 16:43:46 +0200271 auto* rtcp_sender = rtcp_feedback_senders_[0];
272 rtcp_sender->SendCombinedRtcpPacket(std::move(packets));
Per Kjellander52f7ae72019-09-10 19:28:06 +0200273}
274
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100275void PacketRouter::AddRembModuleCandidate(
276 RtcpFeedbackSenderInterface* candidate_module,
277 bool media_sender) {
eladalon822ff2b2017-08-01 06:30:28 -0700278 RTC_DCHECK(candidate_module);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100279 std::vector<RtcpFeedbackSenderInterface*>& candidates =
280 media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
eladalon822ff2b2017-08-01 06:30:28 -0700281 RTC_DCHECK(std::find(candidates.cbegin(), candidates.cend(),
282 candidate_module) == candidates.cend());
283 candidates.push_back(candidate_module);
284 DetermineActiveRembModule();
285}
286
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100287void PacketRouter::MaybeRemoveRembModuleCandidate(
288 RtcpFeedbackSenderInterface* candidate_module,
289 bool media_sender) {
eladalon822ff2b2017-08-01 06:30:28 -0700290 RTC_DCHECK(candidate_module);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100291 std::vector<RtcpFeedbackSenderInterface*>& candidates =
292 media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
eladalon822ff2b2017-08-01 06:30:28 -0700293 auto it = std::find(candidates.begin(), candidates.end(), candidate_module);
294
295 if (it == candidates.end()) {
296 return; // Function called due to removal of non-REMB-candidate module.
297 }
298
299 if (*it == active_remb_module_) {
300 UnsetActiveRembModule();
301 }
302 candidates.erase(it);
303 DetermineActiveRembModule();
304}
305
306void PacketRouter::UnsetActiveRembModule() {
307 RTC_CHECK(active_remb_module_);
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200308 active_remb_module_->UnsetRemb();
eladalon822ff2b2017-08-01 06:30:28 -0700309 active_remb_module_ = nullptr;
310}
311
312void PacketRouter::DetermineActiveRembModule() {
313 // Sender modules take precedence over receiver modules, because SRs (sender
314 // reports) are sent more frequently than RR (receiver reports).
315 // When adding the first sender module, we should change the active REMB
316 // module to be that. Otherwise, we remain with the current active module.
317
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100318 RtcpFeedbackSenderInterface* new_active_remb_module;
eladalon822ff2b2017-08-01 06:30:28 -0700319
320 if (!sender_remb_candidates_.empty()) {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200321 new_active_remb_module = sender_remb_candidates_.front();
eladalon822ff2b2017-08-01 06:30:28 -0700322 } else if (!receiver_remb_candidates_.empty()) {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200323 new_active_remb_module = receiver_remb_candidates_.front();
eladalon822ff2b2017-08-01 06:30:28 -0700324 } else {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200325 new_active_remb_module = nullptr;
eladalon822ff2b2017-08-01 06:30:28 -0700326 }
327
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200328 if (new_active_remb_module != active_remb_module_ && active_remb_module_) {
329 UnsetActiveRembModule();
eladalon822ff2b2017-08-01 06:30:28 -0700330 }
331
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200332 active_remb_module_ = new_active_remb_module;
eladalon822ff2b2017-08-01 06:30:28 -0700333}
334
Stefan Holmere5904162015-03-26 11:11:06 +0100335} // namespace webrtc