Add optimization to PacketRouter for large number of senders.
Remove expectation in PacketRouter tests for exact number const accessors are called
Bug: None
Change-Id: I79c08f0c802b0c863adb133819d32e0b9203e721
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/143799
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28387}
diff --git a/modules/pacing/packet_router.cc b/modules/pacing/packet_router.cc
index 6d2c7ff..791f54e 100644
--- a/modules/pacing/packet_router.cc
+++ b/modules/pacing/packet_router.cc
@@ -67,6 +67,7 @@
void PacketRouter::RemoveSendRtpModule(RtpRtcp* rtp_module) {
rtc::CritScope cs(&modules_crit_);
+ rtp_module_cache_map_.clear();
MaybeRemoveRembModuleCandidate(rtp_module, /* media_sender = */ true);
auto it =
std::find(rtp_send_modules_.begin(), rtp_send_modules_.end(), rtp_module);
@@ -108,23 +109,38 @@
bool retransmission,
const PacedPacketInfo& pacing_info) {
rtc::CritScope cs(&modules_crit_);
- for (auto* rtp_module : rtp_send_modules_) {
- if (!rtp_module->SendingMedia()) {
- continue;
+ RtpRtcp* rtp_module = FindRtpModule(ssrc);
+ if (rtp_module == nullptr || !rtp_module->SendingMedia()) {
+ return RtpPacketSendResult::kPacketNotFound;
+ }
+
+ if ((rtp_module->RtxSendStatus() & kRtxRedundantPayloads) &&
+ rtp_module->HasBweExtensions()) {
+ // 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;
+ }
+ return rtp_module->TimeToSendPacket(ssrc, sequence_number, capture_timestamp,
+ retransmission, pacing_info);
+}
+
+RtpRtcp* PacketRouter::FindRtpModule(uint32_t ssrc) {
+ auto it = rtp_module_cache_map_.find(ssrc);
+ if (it != rtp_module_cache_map_.end()) {
+ if (ssrc == it->second->SSRC() || ssrc == it->second->FlexfecSsrc()) {
+ return it->second;
}
+ // This entry is stale due to a changed ssrc - remove it.
+ rtp_module_cache_map_.erase(it);
+ }
+ // Slow path - find and cache matching module
+ for (RtpRtcp* rtp_module : rtp_send_modules_) {
if (ssrc == rtp_module->SSRC() || ssrc == rtp_module->FlexfecSsrc()) {
- if ((rtp_module->RtxSendStatus() & kRtxRedundantPayloads) &&
- rtp_module->HasBweExtensions()) {
- // 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;
- }
- return rtp_module->TimeToSendPacket(ssrc, sequence_number,
- capture_timestamp, retransmission,
- pacing_info);
+ rtp_module_cache_map_[ssrc] = rtp_module;
+ return rtp_module;
}
}
- return RtpPacketSendResult::kPacketNotFound;
+ return nullptr;
}
void PacketRouter::SendPacket(std::unique_ptr<RtpPacketToSend> packet,
diff --git a/modules/pacing/packet_router.h b/modules/pacing/packet_router.h
index 9a51899..0ca4607 100644
--- a/modules/pacing/packet_router.h
+++ b/modules/pacing/packet_router.h
@@ -15,6 +15,7 @@
#include <stdint.h>
#include <list>
#include <memory>
+#include <unordered_map>
#include <vector>
#include "api/transport/network_types.h"
@@ -86,6 +87,9 @@
bool SendTransportFeedback(rtcp::TransportFeedback* packet) override;
private:
+ RtpRtcp* FindRtpModule(uint32_t ssrc)
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_crit_);
+
void AddRembModuleCandidate(RtcpFeedbackSenderInterface* candidate_module,
bool media_sender)
RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_crit_);
@@ -98,6 +102,9 @@
rtc::CriticalSection modules_crit_;
// Rtp and Rtcp modules of the rtp senders.
std::list<RtpRtcp*> rtp_send_modules_ RTC_GUARDED_BY(modules_crit_);
+ // Ssrc to RtpRtcp module cache.
+ std::unordered_map<uint32_t, RtpRtcp*> rtp_module_cache_map_
+ RTC_GUARDED_BY(modules_crit_);
// The last module used to send media.
RtpRtcp* last_send_module_ RTC_GUARDED_BY(modules_crit_);
// Rtcp modules of the rtp receivers.
diff --git a/modules/pacing/packet_router_unittest.cc b/modules/pacing/packet_router_unittest.cc
index df7619a..1677b0c 100644
--- a/modules/pacing/packet_router_unittest.cc
+++ b/modules/pacing/packet_router_unittest.cc
@@ -108,14 +108,14 @@
bool retransmission = false;
// Send on the first module by letting rtp_1 be sending with correct ssrc.
- EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(true));
- EXPECT_CALL(rtp_1, SSRC()).Times(1).WillOnce(Return(kSsrc1));
+ ON_CALL(rtp_1, SendingMedia).WillByDefault(Return(true));
+ ON_CALL(rtp_1, SSRC).WillByDefault(Return(kSsrc1));
EXPECT_CALL(rtp_1, TimeToSendPacket(
kSsrc1, sequence_number, timestamp, retransmission,
Field(&PacedPacketInfo::probe_cluster_id, 1)))
.Times(1)
.WillOnce(Return(RtpPacketSendResult::kSuccess));
- EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
+ EXPECT_CALL(rtp_2, TimeToSendPacket).Times(0);
EXPECT_EQ(RtpPacketSendResult::kSuccess,
packet_router.TimeToSendPacket(
kSsrc1, sequence_number, timestamp, retransmission,
@@ -126,10 +126,10 @@
timestamp += 30;
retransmission = true;
const uint16_t kSsrc2 = 4567;
- EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(false));
- EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(true));
- EXPECT_CALL(rtp_2, SSRC()).Times(1).WillOnce(Return(kSsrc2));
- EXPECT_CALL(rtp_1, TimeToSendPacket(_, _, _, _, _)).Times(0);
+ ON_CALL(rtp_1, SendingMedia).WillByDefault(Return(false));
+ ON_CALL(rtp_2, SendingMedia).WillByDefault(Return(true));
+ ON_CALL(rtp_2, SSRC).WillByDefault(Return(kSsrc2));
+ EXPECT_CALL(rtp_1, TimeToSendPacket).Times(0);
EXPECT_CALL(rtp_2, TimeToSendPacket(
kSsrc2, sequence_number, timestamp, retransmission,
Field(&PacedPacketInfo::probe_cluster_id, 2)))
@@ -141,22 +141,22 @@
PacedPacketInfo(2, kProbeMinProbes, kProbeMinBytes)));
// No module is sending, hence no packet should be sent.
- EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(false));
- EXPECT_CALL(rtp_1, TimeToSendPacket(_, _, _, _, _)).Times(0);
- EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(false));
- EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
+ ON_CALL(rtp_1, SendingMedia).WillByDefault(Return(false));
+ ON_CALL(rtp_2, SendingMedia).WillByDefault(Return(false));
+ EXPECT_CALL(rtp_1, TimeToSendPacket).Times(0);
+ EXPECT_CALL(rtp_2, TimeToSendPacket).Times(0);
EXPECT_EQ(RtpPacketSendResult::kPacketNotFound,
packet_router.TimeToSendPacket(
kSsrc1, sequence_number, timestamp, retransmission,
PacedPacketInfo(1, kProbeMinProbes, kProbeMinBytes)));
// Add a packet with incorrect ssrc and test it's dropped in the router.
- EXPECT_CALL(rtp_1, SendingMedia()).Times(1).WillOnce(Return(true));
- EXPECT_CALL(rtp_1, SSRC()).Times(1).WillOnce(Return(kSsrc1));
- EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(true));
- EXPECT_CALL(rtp_2, SSRC()).Times(1).WillOnce(Return(kSsrc2));
- EXPECT_CALL(rtp_1, TimeToSendPacket(_, _, _, _, _)).Times(0);
- EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
+ ON_CALL(rtp_1, SendingMedia).WillByDefault(Return(true));
+ ON_CALL(rtp_1, SSRC).WillByDefault(Return(kSsrc1));
+ ON_CALL(rtp_2, SendingMedia).WillByDefault(Return(true));
+ ON_CALL(rtp_2, SSRC).WillByDefault(Return(kSsrc2));
+ EXPECT_CALL(rtp_1, TimeToSendPacket).Times(0);
+ EXPECT_CALL(rtp_2, TimeToSendPacket).Times(0);
EXPECT_EQ(RtpPacketSendResult::kPacketNotFound,
packet_router.TimeToSendPacket(
kSsrc1 + kSsrc2, sequence_number, timestamp, retransmission,
@@ -166,9 +166,9 @@
// rtp_1 has been removed, try sending a packet on that ssrc and make sure
// it is dropped as expected by not expecting any calls to rtp_1.
- EXPECT_CALL(rtp_2, SendingMedia()).Times(1).WillOnce(Return(true));
- EXPECT_CALL(rtp_2, SSRC()).Times(1).WillOnce(Return(kSsrc2));
- EXPECT_CALL(rtp_2, TimeToSendPacket(_, _, _, _, _)).Times(0);
+ ON_CALL(rtp_2, SendingMedia).WillByDefault(Return(true));
+ ON_CALL(rtp_2, SSRC).WillByDefault(Return(kSsrc2));
+ EXPECT_CALL(rtp_2, TimeToSendPacket).Times(0);
EXPECT_EQ(RtpPacketSendResult::kPacketNotFound,
packet_router.TimeToSendPacket(
kSsrc1, sequence_number, timestamp, retransmission,