void RtpTransport::SetRtpPacketTransport(
PacketTransportInternal* new_packet_transport) {
std::unique_ptr<PacketTransportInternal> delete_on_exit;
if (new_packet_transport != owned_rtp_packet_transport_.get()) {
delete_on_exit = std::move(owned_rtp_packet_transport_);
}
ChangePacketTransport(new_packet_transport, rtp_packet_transport_); // Assumes the transport is ready to send if it is writable.
SetReadyToSend(/* rtcp= */ false,
rtp_packet_transport_ && rtp_packet_transport_->writable());
}
void RtpTransport::SetRtcpPacketTransport(
PacketTransportInternal* new_packet_transport) {
std::unique_ptr<PacketTransportInternal> delete_on_exit;
if (new_packet_transport != owned_rtcp_packet_transport_.get()) { // rtcp_packet_transport_ might still point to owned_rtcp_packet_transport_, // so move the owned object to delete_on_exit while we change the transport.
delete_on_exit = std::move(owned_rtcp_packet_transport_);
}
ChangePacketTransport(new_packet_transport, rtcp_packet_transport_); // Assumes the transport is ready to send if it is writable.
SetReadyToSend(/* rtcp= */ true,
rtcp_packet_transport_ && rtcp_packet_transport_->writable());
}
bool RtpTransport::IsWritable(bool rtcp) const {
PacketTransportInternal* transport = rtcp && !rtcp_mux_enabled_
? rtcp_packet_transport_
: rtp_packet_transport_; return transport && transport->writable();
}
RTCError error = VerifyExtensionIds(extensions);
if (!error.ok()) { return error;
}
for (constauto& new_extension : extensions) {
if (new_extension.id == 0) { continue;
} // TODO: bugs.webrtc.org/503013383 - Introduce checking against IDs that are // currently not present in the SDP, but have been used in previous // negotiation rounds. Reusing extensions with a different ID is a protocol // violation, but we cannot check this until we check against the same // protocol violation on the sender side.
for (constauto& [mid, active_extensions] : header_extensions_by_mid_) { auto it = absl::c_find_if(
active_extensions,
[&](const RtpExtension& ext) { return ext.id == new_extension.id; });
if (it != active_extensions.end() && it->uri != new_extension.uri) { return RTCError::InvalidParameter()
<< "RTP extension ID reassignment not supported (collision on " "active MID "
<< mid << ", id=" << new_extension.id << ", old_uri=\""
<< it->uri << "\", new_uri=\"" << new_extension.uri << "\").";
}
}
}
// RFC 8843 (BUNDLE) Section 7.1.3 requires that the same local identifier // MUST be used for a given RTP header extension across all m-sections in a // BUNDLE group. // // However, during negotiation, we may encounter transient states with // conflicting IDs. This can occur with buggy endpoints or during "forked" // signaling (e.g., an Offer followed by a PR-Answer from one endpoint, // then a final Answer from a different endpoint). While most browsers // send identical extension sets, different endpoints ringing simultaneously // could theoretically provide differing maps. // // To handle this gracefully, we merge the maps. Because // `header_extensions_by_mid_` preserves registration order, we iterate in // reverse (newest first). This ensures tie-breaking is deterministic: // more recently registered or updated MIDs (like those in a final Answer) // take precedence over older or provisional ones.
for (auto rit = header_extensions_by_mid_.rbegin();
rit != header_extensions_by_mid_.rend(); ++rit) {
for (constauto& extension : rit->second) {
if (extension.id == RtpHeaderExtensionMap::kInvalidId) { continue;
} // Only register if the ID is not already in use.
RTPExtensionType type = merged_map.GetType(extension.id);
if (type == kRtpExtensionNone) {
merged_map.RegisterByUri(extension.id, extension.uri);
}
}
}
header_extension_map_ = std::move(merged_map);
}
// When using RTCP multiplexing we might get RTCP packets on the RTP // transport. We check the RTP payload type to determine if it is RTCP.
RtpPacketType packet_type = InferRtpPacketType(received_packet.payload()); // Filter out the packet that is neither RTP nor RTCP.
if (packet_type == RtpPacketType::kUnknown) { return;
}
void RtpTransport::MaybeSignalReadyToSend() { bool ready_to_send =
rtp_ready_to_send_ && (rtcp_ready_to_send_ || rtcp_mux_enabled_);
if (ready_to_send != ready_to_send_) {
if (processing_ready_to_send_) { // Delay ReadyToSend processing until current operation is finished. // Note that this may not cause a signal, since ready_to_send may // have a new value by the time this executes.
TaskQueueBase::Current()->PostTask(
SafeTask(safety_.flag(), [this] { MaybeSignalReadyToSend(); })); return;
}
ready_to_send_ = ready_to_send;
processing_ready_to_send_ = true;
SendReadyToSend(ready_to_send);
processing_ready_to_send_ = false;
}
}
} // namespace webrtc
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-08-27)
¤
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.