/* * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
// Signal to module that the pacer thread is attached and can send packets.
rtp_module->OnPacketSendingThreadSwitched();
// Always keep the audio modules at the back of the list, so that when we // iterate over the modules in order to find one that can send padding we // will prioritize video. This is important to make sure they are counted // into the bandwidth estimate properly. if (rtp_module->IsAudioConfigured()) {
send_modules_list_.push_back(rtp_module);
} else {
send_modules_list_.push_front(rtp_module);
}
send_modules_map_[ssrc] = rtp_module;
}
void PacketRouter::RemoveSendRtpModuleFromMap(uint32_t ssrc) {
RTC_DCHECK_RUN_ON(&thread_checker_); auto it = send_modules_map_.find(ssrc); if (it == send_modules_map_.end()) {
RTC_LOG(LS_ERROR) << "No send module found for ssrc " << ssrc; return;
}
send_modules_list_.remove(it->second);
RTC_CHECK(modules_used_in_current_batch_.empty());
send_modules_map_.erase(it);
}
uint32_t ssrc = packet->Ssrc(); auto it = send_modules_map_.find(ssrc); if (it == send_modules_map_.end()) {
RTC_LOG(LS_WARNING)
<< "Failed to send packet, matching RTP module not found " "or transport error. SSRC = "
<< packet->Ssrc() << ", sequence number " << packet->SequenceNumber(); return;
}
RtpRtcpInterface* rtp_module = it->second; if (!packet || !rtp_module->CanSendPacket(*packet)) {
RTC_LOG(LS_WARNING) << "Failed to send packet, Not sending media"; return;
} // TODO(bugs.webrtc.org/15368): Even if the TransportSequenceNumber extension // is not negotiated, we will need the transport sequence number for BWE. if (packet->HasExtension<TransportSequenceNumber>()) {
packet->set_transport_sequence_number(transport_seq_++);
}
rtp_module->AssignSequenceNumber(*packet); if (notify_bwe_callback_) {
notify_bwe_callback_(*packet, cluster_info);
}
// Sending succeeded. if (rtp_module->SupportsRtxPayloadPadding()) { // This is now the last module to send media, and has the desired // properties needed for payload based padding. Cache it for later use.
last_send_module_ = rtp_module;
}
for (auto& packet : rtp_module->FetchFecPackets()) {
pending_fec_packets_.push_back(std::move(packet));
}
}
// First try on the last rtp module to have sent media. This increases the // the chance that any payload based padding will be useful as it will be // somewhat distributed over modules according the packet rate, even if it // will be more skewed towards the highest bitrate stream. At the very least // this prevents sending payload padding on a disabled stream where it's // guaranteed not to be useful.
std::vector<std::unique_ptr<RtpPacketToSend>> padding_packets; if (last_send_module_ != nullptr &&
last_send_module_->SupportsRtxPayloadPadding()) {
padding_packets = last_send_module_->GeneratePadding(size.bytes());
}
if (padding_packets.empty()) { // Iterate over all modules send module. Video modules will be at the front // and so will be prioritized. This is important since audio packets may not // be taken into account by the bandwidth estimator, e.g. in FF. for (RtpRtcpInterface* rtp_module : send_modules_list_) { if (rtp_module->SupportsPadding()) {
padding_packets = rtp_module->GeneratePadding(size.bytes()); if (!padding_packets.empty()) {
last_send_module_ = rtp_module; break;
}
}
}
}
void PacketRouter::OnAbortedRetransmissions(
uint32_t ssrc,
rtc::ArrayView<const uint16_t> sequence_numbers) {
RTC_DCHECK_RUN_ON(&thread_checker_); auto it = send_modules_map_.find(ssrc); if (it != send_modules_map_.end()) {
it->second->OnAbortedRetransmissions(sequence_numbers);
}
}
std::optional<uint32_t> PacketRouter::GetRtxSsrcForMedia(uint32_t ssrc) const {
RTC_DCHECK_RUN_ON(&thread_checker_); auto it = send_modules_map_.find(ssrc); if (it != send_modules_map_.end() && it->second->SSRC() == ssrc) { // A module is registered with the given SSRC, and that SSRC is the main // media SSRC for that RTP module. return it->second->RtxSsrc();
} return std::nullopt;
}
// The Add* and Remove* methods above ensure that REMB is disabled on all // other modules, because otherwise, they will send REMB with stale info.
active_remb_module_->SetRemb(bitrate_bps, std::move(ssrcs));
}
void PacketRouter::DetermineActiveRembModule() {
RTC_DCHECK_RUN_ON(&thread_checker_); // Sender modules take precedence over receiver modules, because SRs (sender // reports) are sent more frequently than RR (receiver reports). // When adding the first sender module, we should change the active REMB // module to be that. Otherwise, we remain with the current active module.
if (new_active_remb_module != active_remb_module_ && active_remb_module_) {
UnsetActiveRembModule();
}
active_remb_module_ = new_active_remb_module;
}
} // namespace webrtc
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.14Bemerkung:
(vorverarbeitet am 2026-04-25)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.