Batch DtlsTransport lookups in SdpOfferAnswerHandler
This reduces the number of blocking calls to the network thread during
SDP negotiation by fetching all DtlsTransports for affected transceivers
in a single blocking call instead of one per transceiver.
In some situations this means a significant reduction of hops to the
network thread. Example from the
RenegotiateManyVideoTransceiversAndWatchAudioDelay test:
Before: Blocking ApplyLocalDescription: total=34
After: Blocking ApplyLocalDescription: total=19
Bug: webrtc:42222804
Change-Id: I09d205959e18ef9c4c28db937fdd58fe44274d1b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/439360
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#46551}
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 00862f1..8245cd3 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -1118,6 +1118,7 @@
":codec_vendor",
":connection_context",
":data_channel_controller",
+ ":dtls_transport",
":jsep_transport_collection",
":jsep_transport_controller",
":legacy_stats_collector",
diff --git a/pc/sdp_offer_answer.cc b/pc/sdp_offer_answer.cc
index f517378..642e352 100644
--- a/pc/sdp_offer_answer.cc
+++ b/pc/sdp_offer_answer.cc
@@ -71,6 +71,7 @@
#include "pc/channel_interface.h"
#include "pc/codec_vendor.h"
#include "pc/connection_context.h"
+#include "pc/dtls_transport.h"
#include "pc/jsep_transport_controller.h"
#include "pc/legacy_stats_collector.h"
#include "pc/media_options.h"
@@ -177,6 +178,36 @@
return bundle_groups_by_mid;
}
+// Helper function to look up DTLS transports for all transceivers in a single
+// blocking call to the network thread.
+flat_map<std::string, scoped_refptr<DtlsTransport>> GetDtlsTransports(
+ const TransceiverList& transceivers,
+ Thread* network_thread,
+ JsepTransportController* transport_controller) {
+ const auto& transceiver_list = transceivers.ListRef();
+ std::vector<std::string> mids_to_lookup;
+ mids_to_lookup.reserve(transceiver_list.size());
+ for (const auto& transceiver : transceiver_list) {
+ if (const auto mid = transceiver->internal()->mid()) {
+ mids_to_lookup.push_back(*mid);
+ }
+ }
+ if (mids_to_lookup.empty()) {
+ return flat_map<std::string, scoped_refptr<DtlsTransport>>();
+ }
+ return network_thread->BlockingCall([&] {
+ RTC_DCHECK_RUN_ON(network_thread);
+ std::vector<std::pair<std::string, scoped_refptr<DtlsTransport>>> entries;
+ entries.reserve(mids_to_lookup.size());
+ for (const auto& mid : mids_to_lookup) {
+ entries.emplace_back(
+ mid, transport_controller->LookupDtlsTransportByMid_n(mid));
+ }
+ return flat_map<std::string, scoped_refptr<DtlsTransport>>(
+ std::move(entries));
+ });
+}
+
// Returns true if `new_desc` requests an ICE restart (i.e., new ufrag/pwd).
bool CheckForRemoteIceRestart(const SessionDescriptionInterface* old_desc,
const SessionDescriptionInterface* new_desc,
@@ -1867,6 +1898,11 @@
if (ConfiguredForMedia()) {
std::vector<scoped_refptr<RtpTransceiverInterface>> remove_list;
std::vector<scoped_refptr<MediaStreamInterface>> removed_streams;
+ flat_map<std::string, scoped_refptr<DtlsTransport>>
+ dtls_transports_by_mid =
+ GetDtlsTransports(*transceivers(), context_->network_thread(),
+ transport_controller_s());
+
for (const auto& transceiver_ext : transceivers()->List()) {
auto transceiver = transceiver_ext->internal();
if (transceiver->stopped()) {
@@ -1877,11 +1913,10 @@
// Note that code paths that don't set MID won't be able to use
// information about DTLS transports.
if (transceiver->mid()) {
- auto dtls_transport =
- transport_controller_s()->LookupDtlsTransportByMid(
- *transceiver->mid());
- transceiver->sender_internal()->set_transport(dtls_transport);
- transceiver->receiver_internal()->set_transport(dtls_transport);
+ auto it = dtls_transports_by_mid.find(*transceiver->mid());
+ RTC_DCHECK(it != dtls_transports_by_mid.end());
+ transceiver->sender_internal()->set_transport(it->second);
+ transceiver->receiver_internal()->set_transport(it->second);
}
const ContentInfo* content =
@@ -2269,6 +2304,10 @@
std::vector<scoped_refptr<RtpTransceiverInterface>> remove_list;
std::vector<scoped_refptr<MediaStreamInterface>> added_streams;
std::vector<scoped_refptr<MediaStreamInterface>> removed_streams;
+ flat_map<std::string, scoped_refptr<DtlsTransport>> dtls_transports_by_mid =
+ GetDtlsTransports(*transceivers(), context_->network_thread(),
+ transport_controller_s());
+
for (const auto& transceiver_ext : transceivers()->List()) {
const auto transceiver = transceiver_ext->internal();
const ContentInfo* content =
@@ -2344,11 +2383,10 @@
transceiver->set_current_direction(local_direction);
// 2.2.8.1.11.[3-6]: Set the transport internal slots.
if (transceiver->mid()) {
- auto dtls_transport =
- transport_controller_s()->LookupDtlsTransportByMid(
- *transceiver->mid());
- transceiver->sender_internal()->set_transport(dtls_transport);
- transceiver->receiver_internal()->set_transport(dtls_transport);
+ auto it = dtls_transports_by_mid.find(*transceiver->mid());
+ RTC_DCHECK(it != dtls_transports_by_mid.end());
+ transceiver->sender_internal()->set_transport(it->second);
+ transceiver->receiver_internal()->set_transport(it->second);
}
}
// 2.2.8.1.12: If the media description is rejected, and transceiver is
diff --git a/pc/transceiver_list.cc b/pc/transceiver_list.cc
index 3c824ce..8b1a59e 100644
--- a/pc/transceiver_list.cc
+++ b/pc/transceiver_list.cc
@@ -55,6 +55,7 @@
std::vector<RtpTransceiver*> TransceiverList::ListInternal() const {
RTC_DCHECK_RUN_ON(&sequence_checker_);
std::vector<RtpTransceiver*> internals;
+ internals.reserve(transceivers_.size());
for (auto transceiver : transceivers_) {
internals.push_back(transceiver->internal());
}
diff --git a/pc/transceiver_list.h b/pc/transceiver_list.h
index a29d384..d7583ae 100644
--- a/pc/transceiver_list.h
+++ b/pc/transceiver_list.h
@@ -99,6 +99,12 @@
return transceivers_;
}
+ // Returns a const reference to the list without generating a copy.
+ const std::vector<RtpTransceiverProxyRefPtr>& ListRef() const {
+ RTC_DCHECK_RUN_ON(&sequence_checker_);
+ return transceivers_;
+ }
+
// Returns a list of the internal() pointers of the currently active list
// of transceivers. These raw pointers are not thread-safe, so need to
// be consumed on the same thread.