blob: 3b1278e5045cea64f96bc8ff782d065b79a5ef98 [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ång1e51a382019-12-11 16:47:09 +010071 // Always keep the audio modules at the back of the list, so that when we
72 // iterate over the modules in order to find one that can send padding we
73 // will prioritize video. This is important to make sure they are counted
74 // into the bandwidth estimate properly.
75 if (rtp_module->IsAudioConfigured()) {
76 send_modules_list_.push_back(rtp_module);
77 } else {
78 send_modules_list_.push_front(rtp_module);
79 }
80 send_modules_map_[ssrc] = rtp_module;
Erik Språngc06aef22019-10-17 13:02:27 +020081}
82
83void PacketRouter::RemoveSendRtpModuleFromMap(uint32_t ssrc) {
84 auto kv = send_modules_map_.find(ssrc);
85 RTC_DCHECK(kv != send_modules_map_.end());
Erik Språng1e51a382019-12-11 16:47:09 +010086 send_modules_list_.remove(kv->second);
Erik Språngc06aef22019-10-17 13:02:27 +020087 send_modules_map_.erase(kv);
88}
89
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +020090void PacketRouter::RemoveSendRtpModule(RtpRtcpInterface* rtp_module) {
Markus Handell1e79c9b2020-06-10 15:12:15 +020091 MutexLock lock(&modules_mutex_);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +010092 MaybeRemoveRembModuleCandidate(rtp_module, /* media_sender = */ true);
Erik Språngc06aef22019-10-17 13:02:27 +020093
94 RemoveSendRtpModuleFromMap(rtp_module->SSRC());
95 if (absl::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) {
96 RemoveSendRtpModuleFromMap(*rtx_ssrc);
97 }
98 if (absl::optional<uint32_t> flexfec_ssrc = rtp_module->FlexfecSsrc()) {
99 RemoveSendRtpModuleFromMap(*flexfec_ssrc);
100 }
101
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200102 if (last_send_module_ == rtp_module) {
103 last_send_module_ = nullptr;
104 }
nissefdbfdc92017-03-31 05:44:52 -0700105}
106
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100107void PacketRouter::AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender,
eladalon822ff2b2017-08-01 06:30:28 -0700108 bool remb_candidate) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200109 MutexLock lock(&modules_mutex_);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100110 RTC_DCHECK(std::find(rtcp_feedback_senders_.begin(),
111 rtcp_feedback_senders_.end(),
112 rtcp_sender) == rtcp_feedback_senders_.end());
eladalon822ff2b2017-08-01 06:30:28 -0700113
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100114 rtcp_feedback_senders_.push_back(rtcp_sender);
eladalon822ff2b2017-08-01 06:30:28 -0700115
116 if (remb_candidate) {
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100117 AddRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
eladalon822ff2b2017-08-01 06:30:28 -0700118 }
nissefdbfdc92017-03-31 05:44:52 -0700119}
120
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100121void PacketRouter::RemoveReceiveRtpModule(
122 RtcpFeedbackSenderInterface* rtcp_sender) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200123 MutexLock lock(&modules_mutex_);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100124 MaybeRemoveRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
125 auto it = std::find(rtcp_feedback_senders_.begin(),
126 rtcp_feedback_senders_.end(), rtcp_sender);
127 RTC_DCHECK(it != rtcp_feedback_senders_.end());
128 rtcp_feedback_senders_.erase(it);
Stefan Holmere5904162015-03-26 11:11:06 +0100129}
130
Erik Språng58ee1872019-06-18 16:20:11 +0200131void PacketRouter::SendPacket(std::unique_ptr<RtpPacketToSend> packet,
132 const PacedPacketInfo& cluster_info) {
Johannes Kron913ea5d2020-06-01 23:28:44 +0000133 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"), "PacketRouter::SendPacket",
134 "sequence_number", packet->SequenceNumber(), "rtp_timestamp",
135 packet->Timestamp());
136
Markus Handell1e79c9b2020-06-10 15:12:15 +0200137 MutexLock lock(&modules_mutex_);
Erik Språngf6468d22019-07-05 16:53:43 +0200138 // With the new pacer code path, transport sequence numbers are only set here,
139 // on the pacer thread. Therefore we don't need atomics/synchronization.
Danil Chapovalov629de6f2020-01-16 18:59:01 +0100140 if (packet->HasExtension<TransportSequenceNumber>()) {
Erik Språng13a8e162019-10-21 19:39:57 +0200141 packet->SetExtension<TransportSequenceNumber>((++transport_seq_) & 0xFFFF);
Erik Språngf6468d22019-07-05 16:53:43 +0200142 }
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000143
Erik Språngc06aef22019-10-17 13:02:27 +0200144 uint32_t ssrc = packet->Ssrc();
145 auto kv = send_modules_map_.find(ssrc);
146 if (kv == send_modules_map_.end()) {
147 RTC_LOG(LS_WARNING)
148 << "Failed to send packet, matching RTP module not found "
149 "or transport error. SSRC = "
150 << packet->Ssrc() << ", sequence number " << packet->SequenceNumber();
151 return;
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000152 }
153
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +0200154 RtpRtcpInterface* rtp_module = kv->second;
Erik Språngc06aef22019-10-17 13:02:27 +0200155 if (!rtp_module->TrySendPacket(packet.get(), cluster_info)) {
156 RTC_LOG(LS_WARNING) << "Failed to send packet, rejected by RTP module.";
157 return;
Erik Språng58ee1872019-06-18 16:20:11 +0200158 }
159
Erik Språngc06aef22019-10-17 13:02:27 +0200160 if (rtp_module->SupportsRtxPayloadPadding()) {
161 // This is now the last module to send media, and has the desired
162 // properties needed for payload based padding. Cache it for later use.
163 last_send_module_ = rtp_module;
164 }
Erik Språng1d50cb62020-07-02 17:41:32 +0200165
166 for (auto& packet : rtp_module->FetchFecPackets()) {
167 pending_fec_packets_.push_back(std::move(packet));
168 }
169}
170
171std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::FetchFec() {
172 MutexLock lock(&modules_mutex_);
173 std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
174 std::move(pending_fec_packets_);
175 pending_fec_packets_.clear();
176 return fec_packets;
Erik Språng58ee1872019-06-18 16:20:11 +0200177}
178
Erik Språngf6468d22019-07-05 16:53:43 +0200179std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::GeneratePadding(
Erik Språnged1fb192020-06-30 11:53:37 +0000180 DataSize size) {
Johannes Kron913ea5d2020-06-01 23:28:44 +0000181 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("webrtc"),
Erik Språnged1fb192020-06-30 11:53:37 +0000182 "PacketRouter::GeneratePadding", "bytes", size.bytes());
Johannes Kron913ea5d2020-06-01 23:28:44 +0000183
Markus Handell1e79c9b2020-06-10 15:12:15 +0200184 MutexLock lock(&modules_mutex_);
Erik Språng478cb462019-06-26 15:49:27 +0200185 // First try on the last rtp module to have sent media. This increases the
186 // the chance that any payload based padding will be useful as it will be
187 // somewhat distributed over modules according the packet rate, even if it
188 // will be more skewed towards the highest bitrate stream. At the very least
189 // this prevents sending payload padding on a disabled stream where it's
190 // guaranteed not to be useful.
Erik Språngc06aef22019-10-17 13:02:27 +0200191 std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets;
Mirko Bonadei999a72a2019-07-12 17:33:46 +0000192 if (last_send_module_ != nullptr &&
193 last_send_module_->SupportsRtxPayloadPadding()) {
Erik Språnged1fb192020-06-30 11:53:37 +0000194 padding_packets = last_send_module_->GeneratePadding(size.bytes());
Erik Språng478cb462019-06-26 15:49:27 +0200195 }
Erik Språngf6468d22019-07-05 16:53:43 +0200196
Johannes Kron913ea5d2020-06-01 23:28:44 +0000197 if (padding_packets.empty()) {
198 // Iterate over all modules send module. Video modules will be at the front
199 // and so will be prioritized. This is important since audio packets may not
200 // be taken into account by the bandwidth estimator, e.g. in FF.
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +0200201 for (RtpRtcpInterface* rtp_module : send_modules_list_) {
Johannes Kron913ea5d2020-06-01 23:28:44 +0000202 if (rtp_module->SupportsPadding()) {
Erik Språnged1fb192020-06-30 11:53:37 +0000203 padding_packets = rtp_module->GeneratePadding(size.bytes());
Johannes Kron913ea5d2020-06-01 23:28:44 +0000204 if (!padding_packets.empty()) {
205 last_send_module_ = rtp_module;
206 break;
207 }
Casey Fischer45bb7172020-06-01 18:38:55 +0000208 }
209 }
Erik Språngc06aef22019-10-17 13:02:27 +0200210 }
211
Johannes Kron913ea5d2020-06-01 23:28:44 +0000212#if RTC_TRACE_EVENTS_ENABLED
213 for (auto& packet : padding_packets) {
214 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"),
215 "PacketRouter::GeneratePadding::Loop", "sequence_number",
216 packet->SequenceNumber(), "rtp_timestamp",
217 packet->Timestamp());
218 }
219#endif
220
Erik Språngc06aef22019-10-17 13:02:27 +0200221 return padding_packets;
Erik Språng478cb462019-06-26 15:49:27 +0200222}
223
Erik Språng5f01bf62019-10-16 17:06:34 +0200224uint16_t PacketRouter::CurrentTransportSequenceNumber() const {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200225 MutexLock lock(&modules_mutex_);
Erik Språng13a8e162019-10-21 19:39:57 +0200226 return transport_seq_ & 0xFFFF;
sprang867fb522015-08-03 04:38:41 -0700227}
228
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200229void PacketRouter::SendRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200230 MutexLock lock(&modules_mutex_);
eladalon822ff2b2017-08-01 06:30:28 -0700231
232 if (!active_remb_module_) {
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200233 return;
eladalon822ff2b2017-08-01 06:30:28 -0700234 }
235
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200236 // The Add* and Remove* methods above ensure that REMB is disabled on all
237 // other modules, because otherwise, they will send REMB with stale info.
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200238 active_remb_module_->SetRemb(bitrate_bps, std::move(ssrcs));
nisse05843312017-04-18 23:38:35 -0700239}
240
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200241void PacketRouter::SendCombinedRtcpPacket(
Per Kjellanderee153c92019-10-10 16:43:46 +0200242 std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets) {
Markus Handell1e79c9b2020-06-10 15:12:15 +0200243 MutexLock lock(&modules_mutex_);
Per Kjellanderee153c92019-10-10 16:43:46 +0200244
nissefdbfdc92017-03-31 05:44:52 -0700245 // Prefer send modules.
Tomas Gunnarssonf25761d2020-06-03 22:55:33 +0200246 for (RtpRtcpInterface* rtp_module : send_modules_list_) {
Per Kjellanderee153c92019-10-10 16:43:46 +0200247 if (rtp_module->RTCP() == RtcpMode::kOff) {
248 continue;
Erik Språng8b7ca4a2018-05-17 13:43:35 +0200249 }
Per Kjellanderee153c92019-10-10 16:43:46 +0200250 rtp_module->SendCombinedRtcpPacket(std::move(packets));
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200251 return;
nissefdbfdc92017-03-31 05:44:52 -0700252 }
sprang233bd872015-09-08 13:25:16 -0700253
Per Kjellanderee153c92019-10-10 16:43:46 +0200254 if (rtcp_feedback_senders_.empty()) {
Per Kjellanderfe2063e2021-05-12 09:02:43 +0200255 return;
Per Kjellander52f7ae72019-09-10 19:28:06 +0200256 }
Per Kjellanderee153c92019-10-10 16:43:46 +0200257 auto* rtcp_sender = rtcp_feedback_senders_[0];
258 rtcp_sender->SendCombinedRtcpPacket(std::move(packets));
Per Kjellander52f7ae72019-09-10 19:28:06 +0200259}
260
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100261void PacketRouter::AddRembModuleCandidate(
262 RtcpFeedbackSenderInterface* candidate_module,
263 bool media_sender) {
eladalon822ff2b2017-08-01 06:30:28 -0700264 RTC_DCHECK(candidate_module);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100265 std::vector<RtcpFeedbackSenderInterface*>& candidates =
266 media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
eladalon822ff2b2017-08-01 06:30:28 -0700267 RTC_DCHECK(std::find(candidates.cbegin(), candidates.cend(),
268 candidate_module) == candidates.cend());
269 candidates.push_back(candidate_module);
270 DetermineActiveRembModule();
271}
272
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100273void PacketRouter::MaybeRemoveRembModuleCandidate(
274 RtcpFeedbackSenderInterface* candidate_module,
275 bool media_sender) {
eladalon822ff2b2017-08-01 06:30:28 -0700276 RTC_DCHECK(candidate_module);
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100277 std::vector<RtcpFeedbackSenderInterface*>& candidates =
278 media_sender ? sender_remb_candidates_ : receiver_remb_candidates_;
eladalon822ff2b2017-08-01 06:30:28 -0700279 auto it = std::find(candidates.begin(), candidates.end(), candidate_module);
280
281 if (it == candidates.end()) {
282 return; // Function called due to removal of non-REMB-candidate module.
283 }
284
285 if (*it == active_remb_module_) {
286 UnsetActiveRembModule();
287 }
288 candidates.erase(it);
289 DetermineActiveRembModule();
290}
291
292void PacketRouter::UnsetActiveRembModule() {
293 RTC_CHECK(active_remb_module_);
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200294 active_remb_module_->UnsetRemb();
eladalon822ff2b2017-08-01 06:30:28 -0700295 active_remb_module_ = nullptr;
296}
297
298void PacketRouter::DetermineActiveRembModule() {
299 // Sender modules take precedence over receiver modules, because SRs (sender
300 // reports) are sent more frequently than RR (receiver reports).
301 // When adding the first sender module, we should change the active REMB
302 // module to be that. Otherwise, we remain with the current active module.
303
Danil Chapovaloveb0edd82017-12-14 16:02:31 +0100304 RtcpFeedbackSenderInterface* new_active_remb_module;
eladalon822ff2b2017-08-01 06:30:28 -0700305
306 if (!sender_remb_candidates_.empty()) {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200307 new_active_remb_module = sender_remb_candidates_.front();
eladalon822ff2b2017-08-01 06:30:28 -0700308 } else if (!receiver_remb_candidates_.empty()) {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200309 new_active_remb_module = receiver_remb_candidates_.front();
eladalon822ff2b2017-08-01 06:30:28 -0700310 } else {
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200311 new_active_remb_module = nullptr;
eladalon822ff2b2017-08-01 06:30:28 -0700312 }
313
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200314 if (new_active_remb_module != active_remb_module_ && active_remb_module_) {
315 UnsetActiveRembModule();
eladalon822ff2b2017-08-01 06:30:28 -0700316 }
317
Danil Chapovalov51e21aa2017-10-10 17:46:26 +0200318 active_remb_module_ = new_active_remb_module;
eladalon822ff2b2017-08-01 06:30:28 -0700319}
320
Stefan Holmere5904162015-03-26 11:11:06 +0100321} // namespace webrtc