packet_router.cc (14463B)
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 "modules/pacing/packet_router.h" 12 13 #include <algorithm> 14 #include <cstdint> 15 #include <memory> 16 #include <optional> 17 #include <utility> 18 #include <vector> 19 20 #include "absl/functional/any_invocable.h" 21 #include "api/array_view.h" 22 #include "api/rtp_headers.h" 23 #include "api/sequence_checker.h" 24 #include "api/transport/network_types.h" 25 #include "api/units/data_size.h" 26 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" 27 #include "modules/rtp_rtcp/source/rtcp_packet.h" 28 #include "modules/rtp_rtcp/source/rtp_header_extensions.h" 29 #include "modules/rtp_rtcp/source/rtp_rtcp_interface.h" 30 #include "rtc_base/checks.h" 31 #include "rtc_base/logging.h" 32 #include "rtc_base/system/unused.h" 33 #include "rtc_base/trace_event.h" 34 35 namespace webrtc { 36 37 PacketRouter::PacketRouter() 38 : last_send_module_(nullptr), 39 active_remb_module_(nullptr), 40 transport_seq_(1) {} 41 42 PacketRouter::~PacketRouter() { 43 RTC_DCHECK_RUN_ON(&thread_checker_); 44 RTC_DCHECK(send_modules_map_.empty()); 45 RTC_DCHECK(send_modules_list_.empty()); 46 RTC_DCHECK(rtcp_feedback_senders_.empty()); 47 RTC_DCHECK(sender_remb_candidates_.empty()); 48 RTC_DCHECK(receiver_remb_candidates_.empty()); 49 RTC_DCHECK(active_remb_module_ == nullptr); 50 } 51 52 void PacketRouter::AddSendRtpModule(RtpRtcpInterface* rtp_module, 53 bool remb_candidate) { 54 RTC_DCHECK_RUN_ON(&thread_checker_); 55 56 AddSendRtpModuleToMap(rtp_module, rtp_module->SSRC()); 57 if (std::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) { 58 AddSendRtpModuleToMap(rtp_module, *rtx_ssrc); 59 } 60 if (std::optional<uint32_t> flexfec_ssrc = rtp_module->FlexfecSsrc()) { 61 AddSendRtpModuleToMap(rtp_module, *flexfec_ssrc); 62 } 63 64 if (rtp_module->SupportsRtxPayloadPadding()) { 65 last_send_module_ = rtp_module; 66 } 67 68 if (remb_candidate) { 69 AddRembModuleCandidate(rtp_module, /* media_sender = */ true); 70 } 71 } 72 73 bool PacketRouter::SupportsRtxPayloadPadding() const { 74 RTC_DCHECK_RUN_ON(&thread_checker_); 75 for (RtpRtcpInterface* rtp_module : send_modules_list_) { 76 if (rtp_module->SupportsRtxPayloadPadding()) { 77 return true; 78 } 79 } 80 return false; 81 } 82 83 void PacketRouter::RegisterNotifyBweCallback( 84 absl::AnyInvocable<void(const RtpPacketToSend& packet, 85 const PacedPacketInfo& pacing_info)> callback) { 86 RTC_DCHECK_RUN_ON(&thread_checker_); 87 notify_bwe_callback_ = std::move(callback); 88 } 89 90 void PacketRouter::ConfigureForRfc8888Feedback(bool send_rtp_packets_as_ect1) { 91 RTC_DCHECK_RUN_ON(&thread_checker_); 92 use_cc_feedback_according_to_rfc8888_ = true; 93 send_rtp_packets_as_ect1_ = send_rtp_packets_as_ect1; 94 } 95 96 void PacketRouter::AddSendRtpModuleToMap(RtpRtcpInterface* rtp_module, 97 uint32_t ssrc) { 98 RTC_DCHECK_RUN_ON(&thread_checker_); 99 RTC_CHECK(send_modules_map_.find(ssrc) == send_modules_map_.end()); 100 101 // Signal to module that the pacer thread is attached and can send packets. 102 rtp_module->OnPacketSendingThreadSwitched(); 103 104 // Always keep the audio modules at the back of the list, so that when we 105 // iterate over the modules in order to find one that can send padding we 106 // will prioritize video. This is important to make sure they are counted 107 // into the bandwidth estimate properly. 108 if (rtp_module->IsAudioConfigured()) { 109 send_modules_list_.push_back(rtp_module); 110 } else { 111 send_modules_list_.push_front(rtp_module); 112 } 113 send_modules_map_[ssrc] = rtp_module; 114 } 115 116 void PacketRouter::RemoveSendRtpModuleFromMap(uint32_t ssrc) { 117 RTC_DCHECK_RUN_ON(&thread_checker_); 118 auto it = send_modules_map_.find(ssrc); 119 if (it == send_modules_map_.end()) { 120 RTC_LOG(LS_ERROR) << "No send module found for ssrc " << ssrc; 121 return; 122 } 123 send_modules_list_.remove(it->second); 124 RTC_CHECK(modules_used_in_current_batch_.empty()); 125 send_modules_map_.erase(it); 126 } 127 128 void PacketRouter::RemoveSendRtpModule(RtpRtcpInterface* rtp_module) { 129 RTC_DCHECK_RUN_ON(&thread_checker_); 130 MaybeRemoveRembModuleCandidate(rtp_module, /* media_sender = */ true); 131 132 RemoveSendRtpModuleFromMap(rtp_module->SSRC()); 133 if (std::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) { 134 RemoveSendRtpModuleFromMap(*rtx_ssrc); 135 } 136 if (std::optional<uint32_t> flexfec_ssrc = rtp_module->FlexfecSsrc()) { 137 RemoveSendRtpModuleFromMap(*flexfec_ssrc); 138 } 139 140 if (last_send_module_ == rtp_module) { 141 last_send_module_ = nullptr; 142 } 143 rtp_module->OnPacketSendingThreadSwitched(); 144 } 145 146 void PacketRouter::AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender, 147 bool remb_candidate) { 148 RTC_DCHECK_RUN_ON(&thread_checker_); 149 RTC_DCHECK(std::find(rtcp_feedback_senders_.begin(), 150 rtcp_feedback_senders_.end(), 151 rtcp_sender) == rtcp_feedback_senders_.end()); 152 153 rtcp_feedback_senders_.push_back(rtcp_sender); 154 155 if (remb_candidate) { 156 AddRembModuleCandidate(rtcp_sender, /* media_sender = */ false); 157 } 158 } 159 160 void PacketRouter::RemoveReceiveRtpModule( 161 RtcpFeedbackSenderInterface* rtcp_sender) { 162 RTC_DCHECK_RUN_ON(&thread_checker_); 163 MaybeRemoveRembModuleCandidate(rtcp_sender, /* media_sender = */ false); 164 auto it = std::find(rtcp_feedback_senders_.begin(), 165 rtcp_feedback_senders_.end(), rtcp_sender); 166 RTC_DCHECK(it != rtcp_feedback_senders_.end()); 167 rtcp_feedback_senders_.erase(it); 168 } 169 170 void PacketRouter::SendPacket(std::unique_ptr<RtpPacketToSend> packet, 171 const PacedPacketInfo& cluster_info) { 172 RTC_DCHECK_RUN_ON(&thread_checker_); 173 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"), "PacketRouter::SendPacket", 174 "sequence_number", packet->SequenceNumber(), "rtp_timestamp", 175 packet->Timestamp()); 176 177 uint32_t ssrc = packet->Ssrc(); 178 auto it = send_modules_map_.find(ssrc); 179 if (it == send_modules_map_.end()) { 180 RTC_LOG(LS_WARNING) 181 << "Failed to send packet, matching RTP module not found " 182 "or transport error. SSRC = " 183 << packet->Ssrc() << ", sequence number " << packet->SequenceNumber(); 184 return; 185 } 186 187 RtpRtcpInterface* rtp_module = it->second; 188 if (!packet || !rtp_module->CanSendPacket(*packet)) { 189 RTC_LOG(LS_WARNING) << "Failed to send packet, Not sending media"; 190 return; 191 } 192 193 // Transport sequence numbers are used if send side bandwidth estimation is 194 // used. Send side BWE relies on RTCP feedback either using format described 195 // in RFC 8888 or 196 // https://datatracker.ietf.org/doc/html/draft-holmer-rmcat-transport-wide-cc-extensions-01. 197 // If RFC 8888 feedback is used, a transport 198 // sequence number is created for all RTP packets, but not sent in the RTP 199 // packet. Otherwise, the transport sequence number is only created 200 // if the TransportSequenceNumber header extension is negotiated for the 201 // specific media type. Historically, webrtc only used TransportSequenceNumber 202 // on video packets. 203 if (use_cc_feedback_according_to_rfc8888_ || 204 packet->HasExtension<TransportSequenceNumber>()) { 205 packet->set_transport_sequence_number(transport_seq_++); 206 } 207 if (send_rtp_packets_as_ect1_) { 208 packet->set_send_as_ect1(); 209 } 210 rtp_module->AssignSequenceNumber(*packet); 211 if (notify_bwe_callback_) { 212 notify_bwe_callback_(*packet, cluster_info); 213 } 214 215 rtp_module->SendPacket(std::move(packet), cluster_info); 216 modules_used_in_current_batch_.insert(rtp_module); 217 218 // Sending succeeded. 219 if (rtp_module->SupportsRtxPayloadPadding()) { 220 // This is now the last module to send media, and has the desired 221 // properties needed for payload based padding. Cache it for later use. 222 last_send_module_ = rtp_module; 223 } 224 225 for (auto& fec_packet : rtp_module->FetchFecPackets()) { 226 pending_fec_packets_.push_back(std::move(fec_packet)); 227 } 228 } 229 230 void PacketRouter::OnBatchComplete() { 231 RTC_DCHECK_RUN_ON(&thread_checker_); 232 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("webrtc"), 233 "PacketRouter::OnBatchComplete"); 234 for (auto& module : modules_used_in_current_batch_) { 235 module->OnBatchComplete(); 236 } 237 modules_used_in_current_batch_.clear(); 238 } 239 240 std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::FetchFec() { 241 RTC_DCHECK_RUN_ON(&thread_checker_); 242 std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets = 243 std::move(pending_fec_packets_); 244 pending_fec_packets_.clear(); 245 return fec_packets; 246 } 247 248 std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::GeneratePadding( 249 DataSize size) { 250 RTC_DCHECK_RUN_ON(&thread_checker_); 251 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("webrtc"), 252 "PacketRouter::GeneratePadding", "bytes", size.bytes()); 253 254 // First try on the last rtp module to have sent media. This increases the 255 // the chance that any payload based padding will be useful as it will be 256 // somewhat distributed over modules according the packet rate, even if it 257 // will be more skewed towards the highest bitrate stream. At the very least 258 // this prevents sending payload padding on a disabled stream where it's 259 // guaranteed not to be useful. 260 std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets; 261 if (last_send_module_ != nullptr && 262 last_send_module_->SupportsRtxPayloadPadding()) { 263 padding_packets = last_send_module_->GeneratePadding(size.bytes()); 264 } 265 266 if (padding_packets.empty()) { 267 // Iterate over all modules send module. Video modules will be at the front 268 // and so will be prioritized. This is important since audio packets may not 269 // be taken into account by the bandwidth estimator, e.g. in FF. 270 for (RtpRtcpInterface* rtp_module : send_modules_list_) { 271 if (rtp_module->SupportsPadding()) { 272 padding_packets = rtp_module->GeneratePadding(size.bytes()); 273 if (!padding_packets.empty()) { 274 last_send_module_ = rtp_module; 275 break; 276 } 277 } 278 } 279 } 280 281 for (auto& packet : padding_packets) { 282 RTC_UNUSED(packet); 283 TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"), 284 "PacketRouter::GeneratePadding::Loop", "sequence_number", 285 packet->SequenceNumber(), "rtp_timestamp", 286 packet->Timestamp()); 287 } 288 289 return padding_packets; 290 } 291 292 void PacketRouter::OnAbortedRetransmissions( 293 uint32_t ssrc, 294 ArrayView<const uint16_t> sequence_numbers) { 295 RTC_DCHECK_RUN_ON(&thread_checker_); 296 auto it = send_modules_map_.find(ssrc); 297 if (it != send_modules_map_.end()) { 298 it->second->OnAbortedRetransmissions(sequence_numbers); 299 } 300 } 301 302 std::optional<uint32_t> PacketRouter::GetRtxSsrcForMedia(uint32_t ssrc) const { 303 RTC_DCHECK_RUN_ON(&thread_checker_); 304 auto it = send_modules_map_.find(ssrc); 305 if (it != send_modules_map_.end() && it->second->SSRC() == ssrc) { 306 // A module is registered with the given SSRC, and that SSRC is the main 307 // media SSRC for that RTP module. 308 return it->second->RtxSsrc(); 309 } 310 return std::nullopt; 311 } 312 313 void PacketRouter::SendRemb(int64_t bitrate_bps, std::vector<uint32_t> ssrcs) { 314 RTC_DCHECK_RUN_ON(&thread_checker_); 315 316 if (!active_remb_module_) { 317 return; 318 } 319 320 // The Add* and Remove* methods above ensure that REMB is disabled on all 321 // other modules, because otherwise, they will send REMB with stale info. 322 active_remb_module_->SetRemb(bitrate_bps, std::move(ssrcs)); 323 } 324 325 void PacketRouter::SendCombinedRtcpPacket( 326 std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets) { 327 RTC_DCHECK_RUN_ON(&thread_checker_); 328 329 // Prefer send modules. 330 for (RtpRtcpInterface* rtp_module : send_modules_list_) { 331 if (rtp_module->RTCP() == RtcpMode::kOff) { 332 continue; 333 } 334 rtp_module->SendCombinedRtcpPacket(std::move(packets)); 335 return; 336 } 337 338 if (rtcp_feedback_senders_.empty()) { 339 return; 340 } 341 auto* rtcp_sender = rtcp_feedback_senders_[0]; 342 rtcp_sender->SendCombinedRtcpPacket(std::move(packets)); 343 } 344 345 void PacketRouter::AddRembModuleCandidate( 346 RtcpFeedbackSenderInterface* candidate_module, 347 bool media_sender) { 348 RTC_DCHECK(candidate_module); 349 std::vector<RtcpFeedbackSenderInterface*>& candidates = 350 media_sender ? sender_remb_candidates_ : receiver_remb_candidates_; 351 RTC_DCHECK(std::find(candidates.cbegin(), candidates.cend(), 352 candidate_module) == candidates.cend()); 353 candidates.push_back(candidate_module); 354 DetermineActiveRembModule(); 355 } 356 357 void PacketRouter::MaybeRemoveRembModuleCandidate( 358 RtcpFeedbackSenderInterface* candidate_module, 359 bool media_sender) { 360 RTC_DCHECK_RUN_ON(&thread_checker_); 361 RTC_DCHECK(candidate_module); 362 std::vector<RtcpFeedbackSenderInterface*>& candidates = 363 media_sender ? sender_remb_candidates_ : receiver_remb_candidates_; 364 auto it = std::find(candidates.begin(), candidates.end(), candidate_module); 365 366 if (it == candidates.end()) { 367 return; // Function called due to removal of non-REMB-candidate module. 368 } 369 370 if (*it == active_remb_module_) { 371 UnsetActiveRembModule(); 372 } 373 candidates.erase(it); 374 DetermineActiveRembModule(); 375 } 376 377 void PacketRouter::UnsetActiveRembModule() { 378 RTC_DCHECK_RUN_ON(&thread_checker_); 379 RTC_CHECK(active_remb_module_); 380 active_remb_module_->UnsetRemb(); 381 active_remb_module_ = nullptr; 382 } 383 384 void PacketRouter::DetermineActiveRembModule() { 385 RTC_DCHECK_RUN_ON(&thread_checker_); 386 // Sender modules take precedence over receiver modules, because SRs (sender 387 // reports) are sent more frequently than RR (receiver reports). 388 // When adding the first sender module, we should change the active REMB 389 // module to be that. Otherwise, we remain with the current active module. 390 391 RtcpFeedbackSenderInterface* new_active_remb_module; 392 393 if (!sender_remb_candidates_.empty()) { 394 new_active_remb_module = sender_remb_candidates_.front(); 395 } else if (!receiver_remb_candidates_.empty()) { 396 new_active_remb_module = receiver_remb_candidates_.front(); 397 } else { 398 new_active_remb_module = nullptr; 399 } 400 401 if (new_active_remb_module != active_remb_module_ && active_remb_module_) { 402 UnsetActiveRembModule(); 403 } 404 405 active_remb_module_ = new_active_remb_module; 406 } 407 408 } // namespace webrtc