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}
This commit is contained in:
Danil Chapovalov 2019-06-26 11:06:41 +02:00 committed by Commit Bot
parent 90f3b89550
commit db59de3e59
3 changed files with 56 additions and 33 deletions

View File

@ -67,6 +67,7 @@ void PacketRouter::AddSendRtpModule(RtpRtcp* rtp_module, bool remb_candidate) {
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 @@ RtpPacketSendResult PacketRouter::TimeToSendPacket(
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,

View File

@ -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 @@ class PacketRouter : public TransportSequenceNumberAllocator,
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 @@ class PacketRouter : public TransportSequenceNumberAllocator,
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.

View File

@ -108,14 +108,14 @@ TEST(PacketRouterTest, TimeToSendPacket) {
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 @@ TEST(PacketRouterTest, TimeToSendPacket) {
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 @@ TEST(PacketRouterTest, TimeToSendPacket) {
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 @@ TEST(PacketRouterTest, TimeToSendPacket) {
// 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,