summaryrefslogtreecommitdiff
path: root/chromium/third_party/webrtc/modules/pacing
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/third_party/webrtc/modules/pacing
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-chromium-85-based.tar.gz
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/third_party/webrtc/modules/pacing')
-rw-r--r--chromium/third_party/webrtc/modules/pacing/BUILD.gn3
-rw-r--r--chromium/third_party/webrtc/modules/pacing/paced_sender.cc15
-rw-r--r--chromium/third_party/webrtc/modules/pacing/paced_sender_unittest.cc15
-rw-r--r--chromium/third_party/webrtc/modules/pacing/pacing_controller.cc4
-rw-r--r--chromium/third_party/webrtc/modules/pacing/pacing_controller.h2
-rw-r--r--chromium/third_party/webrtc/modules/pacing/pacing_controller_unittest.cc30
-rw-r--r--chromium/third_party/webrtc/modules/pacing/packet_router.cc76
-rw-r--r--chromium/third_party/webrtc/modules/pacing/packet_router.h58
-rw-r--r--chromium/third_party/webrtc/modules/pacing/packet_router_unittest.cc91
-rw-r--r--chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender.cc26
-rw-r--r--chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender.h23
-rw-r--r--chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender_unittest.cc572
12 files changed, 540 insertions, 375 deletions
diff --git a/chromium/third_party/webrtc/modules/pacing/BUILD.gn b/chromium/third_party/webrtc/modules/pacing/BUILD.gn
index 6f65c33942e..b19c304e1f6 100644
--- a/chromium/third_party/webrtc/modules/pacing/BUILD.gn
+++ b/chromium/third_party/webrtc/modules/pacing/BUILD.gn
@@ -49,6 +49,7 @@ rtc_library("pacing") {
"../../rtc_base:rtc_base_approved",
"../../rtc_base:rtc_task_queue",
"../../rtc_base/experiments:field_trial_parser",
+ "../../rtc_base/synchronization:mutex",
"../../rtc_base/synchronization:sequence_checker",
"../../rtc_base/task_utils:to_queued_task",
"../../system_wrappers",
@@ -57,6 +58,8 @@ rtc_library("pacing") {
"../rtp_rtcp",
"../rtp_rtcp:rtp_rtcp_format",
"../utility",
+ ]
+ absl_deps = [
"//third_party/abseil-cpp/absl/memory",
"//third_party/abseil-cpp/absl/strings",
"//third_party/abseil-cpp/absl/types:optional",
diff --git a/chromium/third_party/webrtc/modules/pacing/paced_sender.cc b/chromium/third_party/webrtc/modules/pacing/paced_sender.cc
index cd298f9b0bf..e38863031b3 100644
--- a/chromium/third_party/webrtc/modules/pacing/paced_sender.cc
+++ b/chromium/third_party/webrtc/modules/pacing/paced_sender.cc
@@ -22,13 +22,15 @@
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
#include "rtc_base/time_utils.h"
+#include "rtc_base/trace_event.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
const int64_t PacedSender::kMaxQueueLengthMs = 2000;
const float PacedSender::kDefaultPaceMultiplier = 2.5f;
-PacedSender::PacedSender(Clock* clock, PacketRouter* packet_router,
+PacedSender::PacedSender(Clock* clock,
+ PacketRouter* packet_router,
RtcEventLog* event_log,
const WebRtcKeyValueConfig* field_trials,
ProcessThread* process_thread)
@@ -40,7 +42,9 @@ PacedSender::PacedSender(Clock* clock, PacketRouter* packet_router,
: PacingController::ProcessMode::kPeriodic),
pacing_controller_(clock,
static_cast<PacingController::PacketSender*>(this),
- event_log, field_trials, process_mode_),
+ event_log,
+ field_trials,
+ process_mode_),
clock_(clock),
packet_router_(packet_router),
process_thread_(process_thread) {
@@ -112,8 +116,15 @@ void PacedSender::SetPacingRates(DataRate pacing_rate, DataRate padding_rate) {
void PacedSender::EnqueuePackets(
std::vector<std::unique_ptr<RtpPacketToSend>> packets) {
{
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("webrtc"),
+ "PacedSender::EnqueuePackets");
rtc::CritScope cs(&critsect_);
for (auto& packet : packets) {
+ TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"),
+ "PacedSender::EnqueuePackets::Loop", "sequence_number",
+ packet->SequenceNumber(), "rtp_timestamp",
+ packet->Timestamp());
+
pacing_controller_.EnqueuePacket(std::move(packet));
}
}
diff --git a/chromium/third_party/webrtc/modules/pacing/paced_sender_unittest.cc b/chromium/third_party/webrtc/modules/pacing/paced_sender_unittest.cc
index 26d2eac4132..dcbe7d56556 100644
--- a/chromium/third_party/webrtc/modules/pacing/paced_sender_unittest.cc
+++ b/chromium/third_party/webrtc/modules/pacing/paced_sender_unittest.cc
@@ -39,12 +39,15 @@ constexpr size_t kDefaultPacketSize = 234;
// Mock callback implementing the raw api.
class MockCallback : public PacketRouter {
public:
- MOCK_METHOD2(SendPacket,
- void(std::unique_ptr<RtpPacketToSend> packet,
- const PacedPacketInfo& cluster_info));
- MOCK_METHOD1(
- GeneratePadding,
- std::vector<std::unique_ptr<RtpPacketToSend>>(size_t target_size_bytes));
+ MOCK_METHOD(void,
+ SendPacket,
+ (std::unique_ptr<RtpPacketToSend> packet,
+ const PacedPacketInfo& cluster_info),
+ (override));
+ MOCK_METHOD(std::vector<std::unique_ptr<RtpPacketToSend>>,
+ GeneratePadding,
+ (size_t target_size_bytes),
+ (override));
};
class ProcessModeTrials : public WebRtcKeyValueConfig {
diff --git a/chromium/third_party/webrtc/modules/pacing/pacing_controller.cc b/chromium/third_party/webrtc/modules/pacing/pacing_controller.cc
index 4b4fb0bd260..7c523068438 100644
--- a/chromium/third_party/webrtc/modules/pacing/pacing_controller.cc
+++ b/chromium/third_party/webrtc/modules/pacing/pacing_controller.cc
@@ -193,6 +193,10 @@ bool PacingController::Congested() const {
return false;
}
+bool PacingController::IsProbing() const {
+ return prober_.is_probing();
+}
+
Timestamp PacingController::CurrentTime() const {
Timestamp time = clock_->CurrentTime();
if (time < last_timestamp_) {
diff --git a/chromium/third_party/webrtc/modules/pacing/pacing_controller.h b/chromium/third_party/webrtc/modules/pacing/pacing_controller.h
index 27f1614b08c..20d2539e452 100644
--- a/chromium/third_party/webrtc/modules/pacing/pacing_controller.h
+++ b/chromium/third_party/webrtc/modules/pacing/pacing_controller.h
@@ -146,6 +146,8 @@ class PacingController {
bool Congested() const;
+ bool IsProbing() const;
+
private:
void EnqueuePacketInternal(std::unique_ptr<RtpPacketToSend> packet,
int priority);
diff --git a/chromium/third_party/webrtc/modules/pacing/pacing_controller_unittest.cc b/chromium/third_party/webrtc/modules/pacing/pacing_controller_unittest.cc
index fa23da70a02..e7a61f75e47 100644
--- a/chromium/third_party/webrtc/modules/pacing/pacing_controller_unittest.cc
+++ b/chromium/third_party/webrtc/modules/pacing/pacing_controller_unittest.cc
@@ -90,24 +90,28 @@ class MockPacingControllerCallback : public PacingController::PacketSender {
return ret;
}
- MOCK_METHOD5(SendPacket,
- void(uint32_t ssrc,
- uint16_t sequence_number,
- int64_t capture_timestamp,
- bool retransmission,
- bool padding));
- MOCK_METHOD1(SendPadding, size_t(size_t target_size));
+ MOCK_METHOD(void,
+ SendPacket,
+ (uint32_t ssrc,
+ uint16_t sequence_number,
+ int64_t capture_timestamp,
+ bool retransmission,
+ bool padding));
+ MOCK_METHOD(size_t, SendPadding, (size_t target_size));
};
// Mock callback implementing the raw api.
class MockPacketSender : public PacingController::PacketSender {
public:
- MOCK_METHOD2(SendRtpPacket,
- void(std::unique_ptr<RtpPacketToSend> packet,
- const PacedPacketInfo& cluster_info));
- MOCK_METHOD1(
- GeneratePadding,
- std::vector<std::unique_ptr<RtpPacketToSend>>(DataSize target_size));
+ MOCK_METHOD(void,
+ SendRtpPacket,
+ (std::unique_ptr<RtpPacketToSend> packet,
+ const PacedPacketInfo& cluster_info),
+ (override));
+ MOCK_METHOD(std::vector<std::unique_ptr<RtpPacketToSend>>,
+ GeneratePadding,
+ (DataSize target_size),
+ (override));
};
class PacingControllerPadding : public PacingController::PacketSender {
diff --git a/chromium/third_party/webrtc/modules/pacing/packet_router.cc b/chromium/third_party/webrtc/modules/pacing/packet_router.cc
index fa643314934..3569738cdf1 100644
--- a/chromium/third_party/webrtc/modules/pacing/packet_router.cc
+++ b/chromium/third_party/webrtc/modules/pacing/packet_router.cc
@@ -17,13 +17,14 @@
#include <utility>
#include "absl/types/optional.h"
-#include "modules/rtp_rtcp/include/rtp_rtcp.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtcp_packet.h"
#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
+#include "modules/rtp_rtcp/source/rtp_rtcp_interface.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/time_utils.h"
+#include "rtc_base/trace_event.h"
namespace webrtc {
namespace {
@@ -52,8 +53,9 @@ PacketRouter::~PacketRouter() {
RTC_DCHECK(active_remb_module_ == nullptr);
}
-void PacketRouter::AddSendRtpModule(RtpRtcp* rtp_module, bool remb_candidate) {
- rtc::CritScope cs(&modules_crit_);
+void PacketRouter::AddSendRtpModule(RtpRtcpInterface* rtp_module,
+ bool remb_candidate) {
+ MutexLock lock(&modules_mutex_);
AddSendRtpModuleToMap(rtp_module, rtp_module->SSRC());
if (absl::optional<uint32_t> rtx_ssrc = rtp_module->RtxSsrc()) {
@@ -72,7 +74,8 @@ void PacketRouter::AddSendRtpModule(RtpRtcp* rtp_module, bool remb_candidate) {
}
}
-void PacketRouter::AddSendRtpModuleToMap(RtpRtcp* rtp_module, uint32_t ssrc) {
+void PacketRouter::AddSendRtpModuleToMap(RtpRtcpInterface* rtp_module,
+ uint32_t ssrc) {
RTC_DCHECK(send_modules_map_.find(ssrc) == send_modules_map_.end());
// 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
@@ -93,8 +96,8 @@ void PacketRouter::RemoveSendRtpModuleFromMap(uint32_t ssrc) {
send_modules_map_.erase(kv);
}
-void PacketRouter::RemoveSendRtpModule(RtpRtcp* rtp_module) {
- rtc::CritScope cs(&modules_crit_);
+void PacketRouter::RemoveSendRtpModule(RtpRtcpInterface* rtp_module) {
+ MutexLock lock(&modules_mutex_);
MaybeRemoveRembModuleCandidate(rtp_module, /* media_sender = */ true);
RemoveSendRtpModuleFromMap(rtp_module->SSRC());
@@ -112,7 +115,7 @@ void PacketRouter::RemoveSendRtpModule(RtpRtcp* rtp_module) {
void PacketRouter::AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender,
bool remb_candidate) {
- rtc::CritScope cs(&modules_crit_);
+ MutexLock lock(&modules_mutex_);
RTC_DCHECK(std::find(rtcp_feedback_senders_.begin(),
rtcp_feedback_senders_.end(),
rtcp_sender) == rtcp_feedback_senders_.end());
@@ -126,7 +129,7 @@ void PacketRouter::AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender,
void PacketRouter::RemoveReceiveRtpModule(
RtcpFeedbackSenderInterface* rtcp_sender) {
- rtc::CritScope cs(&modules_crit_);
+ MutexLock lock(&modules_mutex_);
MaybeRemoveRembModuleCandidate(rtcp_sender, /* media_sender = */ false);
auto it = std::find(rtcp_feedback_senders_.begin(),
rtcp_feedback_senders_.end(), rtcp_sender);
@@ -136,7 +139,11 @@ void PacketRouter::RemoveReceiveRtpModule(
void PacketRouter::SendPacket(std::unique_ptr<RtpPacketToSend> packet,
const PacedPacketInfo& cluster_info) {
- rtc::CritScope cs(&modules_crit_);
+ TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"), "PacketRouter::SendPacket",
+ "sequence_number", packet->SequenceNumber(), "rtp_timestamp",
+ packet->Timestamp());
+
+ MutexLock lock(&modules_mutex_);
// With the new pacer code path, transport sequence numbers are only set here,
// on the pacer thread. Therefore we don't need atomics/synchronization.
if (packet->HasExtension<TransportSequenceNumber>()) {
@@ -153,7 +160,7 @@ void PacketRouter::SendPacket(std::unique_ptr<RtpPacketToSend> packet,
return;
}
- RtpRtcp* rtp_module = kv->second;
+ RtpRtcpInterface* rtp_module = kv->second;
if (!rtp_module->TrySendPacket(packet.get(), cluster_info)) {
RTC_LOG(LS_WARNING) << "Failed to send packet, rejected by RTP module.";
return;
@@ -168,7 +175,10 @@ void PacketRouter::SendPacket(std::unique_ptr<RtpPacketToSend> packet,
std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::GeneratePadding(
size_t target_size_bytes) {
- rtc::CritScope cs(&modules_crit_);
+ TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("webrtc"),
+ "PacketRouter::GeneratePadding", "bytes", target_size_bytes);
+
+ MutexLock lock(&modules_mutex_);
// 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
@@ -179,29 +189,37 @@ std::vector<std::unique_ptr<RtpPacketToSend>> PacketRouter::GeneratePadding(
if (last_send_module_ != nullptr &&
last_send_module_->SupportsRtxPayloadPadding()) {
padding_packets = last_send_module_->GeneratePadding(target_size_bytes);
- if (!padding_packets.empty()) {
- return padding_packets;
- }
}
- // 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 (RtpRtcp* rtp_module : send_modules_list_) {
- if (rtp_module->SupportsPadding()) {
- padding_packets = rtp_module->GeneratePadding(target_size_bytes);
- if (!padding_packets.empty()) {
- last_send_module_ = rtp_module;
- break;
+ 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(target_size_bytes);
+ if (!padding_packets.empty()) {
+ last_send_module_ = rtp_module;
+ break;
+ }
}
}
}
+#if RTC_TRACE_EVENTS_ENABLED
+ for (auto& packet : padding_packets) {
+ TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"),
+ "PacketRouter::GeneratePadding::Loop", "sequence_number",
+ packet->SequenceNumber(), "rtp_timestamp",
+ packet->Timestamp());
+ }
+#endif
+
return padding_packets;
}
uint16_t PacketRouter::CurrentTransportSequenceNumber() const {
- rtc::CritScope lock(&modules_crit_);
+ MutexLock lock(&modules_mutex_);
return transport_seq_ & 0xFFFF;
}
@@ -215,7 +233,7 @@ void PacketRouter::OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
int64_t now_ms = rtc::TimeMillis();
{
- rtc::CritScope lock(&remb_crit_);
+ MutexLock lock(&remb_mutex_);
// If we already have an estimate, check if the new total estimate is below
// kSendThresholdPercent of the previous estimate.
@@ -248,7 +266,7 @@ void PacketRouter::OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
void PacketRouter::SetMaxDesiredReceiveBitrate(int64_t bitrate_bps) {
RTC_DCHECK_GE(bitrate_bps, 0);
{
- rtc::CritScope lock(&remb_crit_);
+ MutexLock lock(&remb_mutex_);
max_bitrate_bps_ = bitrate_bps;
if (rtc::TimeMillis() - last_remb_time_ms_ < kRembSendIntervalMs &&
last_send_bitrate_bps_ > 0 &&
@@ -262,7 +280,7 @@ void PacketRouter::SetMaxDesiredReceiveBitrate(int64_t bitrate_bps) {
bool PacketRouter::SendRemb(int64_t bitrate_bps,
const std::vector<uint32_t>& ssrcs) {
- rtc::CritScope lock(&modules_crit_);
+ MutexLock lock(&modules_mutex_);
if (!active_remb_module_) {
return false;
@@ -277,10 +295,10 @@ bool PacketRouter::SendRemb(int64_t bitrate_bps,
bool PacketRouter::SendCombinedRtcpPacket(
std::vector<std::unique_ptr<rtcp::RtcpPacket>> packets) {
- rtc::CritScope cs(&modules_crit_);
+ MutexLock lock(&modules_mutex_);
// Prefer send modules.
- for (RtpRtcp* rtp_module : send_modules_list_) {
+ for (RtpRtcpInterface* rtp_module : send_modules_list_) {
if (rtp_module->RTCP() == RtcpMode::kOff) {
continue;
}
diff --git a/chromium/third_party/webrtc/modules/pacing/packet_router.h b/chromium/third_party/webrtc/modules/pacing/packet_router.h
index 40b3ad14077..379ec20f200 100644
--- a/chromium/third_party/webrtc/modules/pacing/packet_router.h
+++ b/chromium/third_party/webrtc/modules/pacing/packet_router.h
@@ -27,11 +27,12 @@
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "rtc_base/constructor_magic.h"
#include "rtc_base/critical_section.h"
+#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread_annotations.h"
namespace webrtc {
-class RtpRtcp;
+class RtpRtcpInterface;
// PacketRouter keeps track of rtp send modules to support the pacer.
// In addition, it handles feedback messages, which are sent on a send
@@ -45,8 +46,8 @@ class PacketRouter : public RemoteBitrateObserver,
explicit PacketRouter(uint16_t start_transport_seq);
~PacketRouter() override;
- void AddSendRtpModule(RtpRtcp* rtp_module, bool remb_candidate);
- void RemoveSendRtpModule(RtpRtcp* rtp_module);
+ void AddSendRtpModule(RtpRtcpInterface* rtp_module, bool remb_candidate);
+ void RemoveSendRtpModule(RtpRtcpInterface* rtp_module);
void AddReceiveRtpModule(RtcpFeedbackSenderInterface* rtcp_sender,
bool remb_candidate);
@@ -82,48 +83,49 @@ class PacketRouter : public RemoteBitrateObserver,
private:
void AddRembModuleCandidate(RtcpFeedbackSenderInterface* candidate_module,
bool media_sender)
- RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_crit_);
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_mutex_);
void MaybeRemoveRembModuleCandidate(
RtcpFeedbackSenderInterface* candidate_module,
- bool media_sender) RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_crit_);
- void UnsetActiveRembModule() RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_crit_);
- void DetermineActiveRembModule() RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_crit_);
- void AddSendRtpModuleToMap(RtpRtcp* rtp_module, uint32_t ssrc)
- RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_crit_);
+ bool media_sender) RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_mutex_);
+ void UnsetActiveRembModule() RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_mutex_);
+ void DetermineActiveRembModule() RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_mutex_);
+ void AddSendRtpModuleToMap(RtpRtcpInterface* rtp_module, uint32_t ssrc)
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_mutex_);
void RemoveSendRtpModuleFromMap(uint32_t ssrc)
- RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_crit_);
-
- rtc::CriticalSection modules_crit_;
- // Ssrc to RtpRtcp module;
- std::unordered_map<uint32_t, RtpRtcp*> send_modules_map_
- RTC_GUARDED_BY(modules_crit_);
- std::list<RtpRtcp*> send_modules_list_ RTC_GUARDED_BY(modules_crit_);
+ RTC_EXCLUSIVE_LOCKS_REQUIRED(modules_mutex_);
+
+ mutable Mutex modules_mutex_;
+ // Ssrc to RtpRtcpInterface module;
+ std::unordered_map<uint32_t, RtpRtcpInterface*> send_modules_map_
+ RTC_GUARDED_BY(modules_mutex_);
+ std::list<RtpRtcpInterface*> send_modules_list_
+ RTC_GUARDED_BY(modules_mutex_);
// The last module used to send media.
- RtpRtcp* last_send_module_ RTC_GUARDED_BY(modules_crit_);
+ RtpRtcpInterface* last_send_module_ RTC_GUARDED_BY(modules_mutex_);
// Rtcp modules of the rtp receivers.
std::vector<RtcpFeedbackSenderInterface*> rtcp_feedback_senders_
- RTC_GUARDED_BY(modules_crit_);
+ RTC_GUARDED_BY(modules_mutex_);
- // TODO(eladalon): remb_crit_ only ever held from one function, and it's not
+ // TODO(eladalon): remb_mutex_ only ever held from one function, and it's not
// clear if that function can actually be called from more than one thread.
- rtc::CriticalSection remb_crit_;
+ Mutex remb_mutex_;
// The last time a REMB was sent.
- int64_t last_remb_time_ms_ RTC_GUARDED_BY(remb_crit_);
- int64_t last_send_bitrate_bps_ RTC_GUARDED_BY(remb_crit_);
+ int64_t last_remb_time_ms_ RTC_GUARDED_BY(remb_mutex_);
+ int64_t last_send_bitrate_bps_ RTC_GUARDED_BY(remb_mutex_);
// The last bitrate update.
- int64_t bitrate_bps_ RTC_GUARDED_BY(remb_crit_);
- int64_t max_bitrate_bps_ RTC_GUARDED_BY(remb_crit_);
+ int64_t bitrate_bps_ RTC_GUARDED_BY(remb_mutex_);
+ int64_t max_bitrate_bps_ RTC_GUARDED_BY(remb_mutex_);
// Candidates for the REMB module can be RTP sender/receiver modules, with
// the sender modules taking precedence.
std::vector<RtcpFeedbackSenderInterface*> sender_remb_candidates_
- RTC_GUARDED_BY(modules_crit_);
+ RTC_GUARDED_BY(modules_mutex_);
std::vector<RtcpFeedbackSenderInterface*> receiver_remb_candidates_
- RTC_GUARDED_BY(modules_crit_);
+ RTC_GUARDED_BY(modules_mutex_);
RtcpFeedbackSenderInterface* active_remb_module_
- RTC_GUARDED_BY(modules_crit_);
+ RTC_GUARDED_BY(modules_mutex_);
- uint64_t transport_seq_ RTC_GUARDED_BY(modules_crit_);
+ uint64_t transport_seq_ RTC_GUARDED_BY(modules_mutex_);
RTC_DISALLOW_COPY_AND_ASSIGN(PacketRouter);
};
diff --git a/chromium/third_party/webrtc/modules/pacing/packet_router_unittest.cc b/chromium/third_party/webrtc/modules/pacing/packet_router_unittest.cc
index b8f16cb9242..6af7529e861 100644
--- a/chromium/third_party/webrtc/modules/pacing/packet_router_unittest.cc
+++ b/chromium/third_party/webrtc/modules/pacing/packet_router_unittest.cc
@@ -101,12 +101,12 @@ TEST_F(PacketRouterTest, GeneratePaddingPrioritizesRtx) {
const uint16_t kSsrc1 = 1234;
const uint16_t kSsrc2 = 4567;
- NiceMock<MockRtpRtcp> rtp_1;
+ NiceMock<MockRtpRtcpInterface> rtp_1;
ON_CALL(rtp_1, RtxSendStatus()).WillByDefault(Return(kRtxRedundantPayloads));
ON_CALL(rtp_1, SSRC()).WillByDefault(Return(kSsrc1));
ON_CALL(rtp_1, SupportsPadding).WillByDefault(Return(false));
- NiceMock<MockRtpRtcp> rtp_2;
+ NiceMock<MockRtpRtcpInterface> rtp_2;
ON_CALL(rtp_2, RtxSendStatus()).WillByDefault(Return(kRtxOff));
ON_CALL(rtp_2, SSRC()).WillByDefault(Return(kSsrc2));
ON_CALL(rtp_2, SupportsPadding).WillByDefault(Return(true));
@@ -142,13 +142,13 @@ TEST_F(PacketRouterTest, GeneratePaddingPrioritizesVideo) {
kExpectedPaddingPackets);
};
- NiceMock<MockRtpRtcp> audio_module;
+ NiceMock<MockRtpRtcpInterface> audio_module;
ON_CALL(audio_module, RtxSendStatus()).WillByDefault(Return(kRtxOff));
ON_CALL(audio_module, SSRC()).WillByDefault(Return(kSsrc1));
ON_CALL(audio_module, SupportsPadding).WillByDefault(Return(true));
ON_CALL(audio_module, IsAudioConfigured).WillByDefault(Return(true));
- NiceMock<MockRtpRtcp> video_module;
+ NiceMock<MockRtpRtcpInterface> video_module;
ON_CALL(video_module, RtxSendStatus()).WillByDefault(Return(kRtxOff));
ON_CALL(video_module, SSRC()).WillByDefault(Return(kSsrc2));
ON_CALL(video_module, SupportsPadding).WillByDefault(Return(true));
@@ -194,7 +194,7 @@ TEST_F(PacketRouterTest, PadsOnLastActiveMediaStream) {
const uint16_t kSsrc3 = 8901;
// First two rtp modules send media and have rtx.
- NiceMock<MockRtpRtcp> rtp_1;
+ NiceMock<MockRtpRtcpInterface> rtp_1;
EXPECT_CALL(rtp_1, SSRC()).WillRepeatedly(Return(kSsrc1));
EXPECT_CALL(rtp_1, SupportsPadding).WillRepeatedly(Return(true));
EXPECT_CALL(rtp_1, SupportsRtxPayloadPadding).WillRepeatedly(Return(true));
@@ -205,7 +205,7 @@ TEST_F(PacketRouterTest, PadsOnLastActiveMediaStream) {
::testing::Pointee(Property(&RtpPacketToSend::Ssrc, kSsrc1)), _))
.WillRepeatedly(Return(true));
- NiceMock<MockRtpRtcp> rtp_2;
+ NiceMock<MockRtpRtcpInterface> rtp_2;
EXPECT_CALL(rtp_2, SSRC()).WillRepeatedly(Return(kSsrc2));
EXPECT_CALL(rtp_2, SupportsPadding).WillRepeatedly(Return(true));
EXPECT_CALL(rtp_2, SupportsRtxPayloadPadding).WillRepeatedly(Return(true));
@@ -217,7 +217,7 @@ TEST_F(PacketRouterTest, PadsOnLastActiveMediaStream) {
.WillRepeatedly(Return(true));
// Third module is sending media, but does not support rtx.
- NiceMock<MockRtpRtcp> rtp_3;
+ NiceMock<MockRtpRtcpInterface> rtp_3;
EXPECT_CALL(rtp_3, SSRC()).WillRepeatedly(Return(kSsrc3));
EXPECT_CALL(rtp_3, SupportsPadding).WillRepeatedly(Return(true));
EXPECT_CALL(rtp_3, SupportsRtxPayloadPadding).WillRepeatedly(Return(false));
@@ -265,7 +265,7 @@ TEST_F(PacketRouterTest, PadsOnLastActiveMediaStream) {
packet_router_.RemoveSendRtpModule(&rtp_2);
// Send on and then remove all remaining modules.
- RtpRtcp* last_send_module;
+ RtpRtcpInterface* last_send_module;
EXPECT_CALL(rtp_1, GeneratePadding(kPaddingBytes))
.Times(1)
.WillOnce([&](size_t target_size_bytes) {
@@ -297,7 +297,7 @@ TEST_F(PacketRouterTest, AllocatesTransportSequenceNumbers) {
const uint16_t kSsrc1 = 1234;
PacketRouter packet_router(kStartSeq - 1);
- NiceMock<MockRtpRtcp> rtp_1;
+ NiceMock<MockRtpRtcpInterface> rtp_1;
EXPECT_CALL(rtp_1, SSRC()).WillRepeatedly(Return(kSsrc1));
EXPECT_CALL(rtp_1, TrySendPacket).WillRepeatedly(Return(true));
packet_router.AddSendRtpModule(&rtp_1, false);
@@ -315,8 +315,8 @@ TEST_F(PacketRouterTest, AllocatesTransportSequenceNumbers) {
}
TEST_F(PacketRouterTest, SendTransportFeedback) {
- NiceMock<MockRtpRtcp> rtp_1;
- NiceMock<MockRtpRtcp> rtp_2;
+ NiceMock<MockRtpRtcpInterface> rtp_1;
+ NiceMock<MockRtpRtcpInterface> rtp_2;
ON_CALL(rtp_1, RTCP()).WillByDefault(Return(RtcpMode::kCompound));
ON_CALL(rtp_2, RTCP()).WillByDefault(Return(RtcpMode::kCompound));
@@ -338,7 +338,7 @@ TEST_F(PacketRouterTest, SendTransportFeedback) {
TEST_F(PacketRouterTest, SendPacketWithoutTransportSequenceNumbers) {
const uint16_t kSsrc1 = 1234;
- NiceMock<MockRtpRtcp> rtp_1;
+ NiceMock<MockRtpRtcpInterface> rtp_1;
ON_CALL(rtp_1, SendingMedia).WillByDefault(Return(true));
ON_CALL(rtp_1, SSRC).WillByDefault(Return(kSsrc1));
packet_router_.AddSendRtpModule(&rtp_1, false);
@@ -361,8 +361,8 @@ TEST_F(PacketRouterTest, SendPacketWithoutTransportSequenceNumbers) {
}
TEST_F(PacketRouterTest, SendPacketAssignsTransportSequenceNumbers) {
- NiceMock<MockRtpRtcp> rtp_1;
- NiceMock<MockRtpRtcp> rtp_2;
+ NiceMock<MockRtpRtcpInterface> rtp_1;
+ NiceMock<MockRtpRtcpInterface> rtp_2;
const uint16_t kSsrc1 = 1234;
const uint16_t kSsrc2 = 2345;
@@ -405,8 +405,9 @@ TEST_F(PacketRouterTest, SendPacketAssignsTransportSequenceNumbers) {
}
#if RTC_DCHECK_IS_ON && GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
-TEST_F(PacketRouterTest, DoubleRegistrationOfSendModuleDisallowed) {
- NiceMock<MockRtpRtcp> module;
+using PacketRouterDeathTest = PacketRouterTest;
+TEST_F(PacketRouterDeathTest, DoubleRegistrationOfSendModuleDisallowed) {
+ NiceMock<MockRtpRtcpInterface> module;
constexpr bool remb_candidate = false; // Value irrelevant.
packet_router_.AddSendRtpModule(&module, remb_candidate);
@@ -416,8 +417,8 @@ TEST_F(PacketRouterTest, DoubleRegistrationOfSendModuleDisallowed) {
packet_router_.RemoveSendRtpModule(&module);
}
-TEST_F(PacketRouterTest, DoubleRegistrationOfReceiveModuleDisallowed) {
- NiceMock<MockRtpRtcp> module;
+TEST_F(PacketRouterDeathTest, DoubleRegistrationOfReceiveModuleDisallowed) {
+ NiceMock<MockRtpRtcpInterface> module;
constexpr bool remb_candidate = false; // Value irrelevant.
packet_router_.AddReceiveRtpModule(&module, remb_candidate);
@@ -427,14 +428,14 @@ TEST_F(PacketRouterTest, DoubleRegistrationOfReceiveModuleDisallowed) {
packet_router_.RemoveReceiveRtpModule(&module);
}
-TEST_F(PacketRouterTest, RemovalOfNeverAddedSendModuleDisallowed) {
- NiceMock<MockRtpRtcp> module;
+TEST_F(PacketRouterDeathTest, RemovalOfNeverAddedSendModuleDisallowed) {
+ NiceMock<MockRtpRtcpInterface> module;
EXPECT_DEATH(packet_router_.RemoveSendRtpModule(&module), "");
}
-TEST_F(PacketRouterTest, RemovalOfNeverAddedReceiveModuleDisallowed) {
- NiceMock<MockRtpRtcp> module;
+TEST_F(PacketRouterDeathTest, RemovalOfNeverAddedReceiveModuleDisallowed) {
+ NiceMock<MockRtpRtcpInterface> module;
EXPECT_DEATH(packet_router_.RemoveReceiveRtpModule(&module), "");
}
@@ -442,7 +443,7 @@ TEST_F(PacketRouterTest, RemovalOfNeverAddedReceiveModuleDisallowed) {
TEST(PacketRouterRembTest, LowerEstimateToSendRemb) {
rtc::ScopedFakeClock clock;
- NiceMock<MockRtpRtcp> rtp;
+ NiceMock<MockRtpRtcpInterface> rtp;
PacketRouter packet_router;
packet_router.AddSendRtpModule(&rtp, true);
@@ -468,7 +469,7 @@ TEST(PacketRouterRembTest, LowerEstimateToSendRemb) {
TEST(PacketRouterRembTest, VerifyIncreasingAndDecreasing) {
rtc::ScopedFakeClock clock;
- NiceMock<MockRtpRtcp> rtp;
+ NiceMock<MockRtpRtcpInterface> rtp;
PacketRouter packet_router;
packet_router.AddSendRtpModule(&rtp, true);
@@ -493,7 +494,7 @@ TEST(PacketRouterRembTest, VerifyIncreasingAndDecreasing) {
TEST(PacketRouterRembTest, NoRembForIncreasedBitrate) {
rtc::ScopedFakeClock clock;
- NiceMock<MockRtpRtcp> rtp;
+ NiceMock<MockRtpRtcpInterface> rtp;
PacketRouter packet_router;
packet_router.AddSendRtpModule(&rtp, true);
@@ -521,8 +522,8 @@ TEST(PacketRouterRembTest, NoRembForIncreasedBitrate) {
TEST(PacketRouterRembTest, ChangeSendRtpModule) {
rtc::ScopedFakeClock clock;
- NiceMock<MockRtpRtcp> rtp_send;
- NiceMock<MockRtpRtcp> rtp_recv;
+ NiceMock<MockRtpRtcpInterface> rtp_send;
+ NiceMock<MockRtpRtcpInterface> rtp_recv;
PacketRouter packet_router;
packet_router.AddSendRtpModule(&rtp_send, true);
packet_router.AddReceiveRtpModule(&rtp_recv, true);
@@ -556,7 +557,7 @@ TEST(PacketRouterRembTest, ChangeSendRtpModule) {
TEST(PacketRouterRembTest, OnlyOneRembForRepeatedOnReceiveBitrateChanged) {
rtc::ScopedFakeClock clock;
- NiceMock<MockRtpRtcp> rtp;
+ NiceMock<MockRtpRtcpInterface> rtp;
PacketRouter packet_router;
packet_router.AddSendRtpModule(&rtp, true);
@@ -585,7 +586,7 @@ TEST(PacketRouterRembTest, SetMaxDesiredReceiveBitrateLimitsSetRemb) {
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
clock.AdvanceTime(TimeDelta::Millis(1000));
- NiceMock<MockRtpRtcp> remb_sender;
+ NiceMock<MockRtpRtcpInterface> remb_sender;
constexpr bool remb_candidate = true;
packet_router.AddSendRtpModule(&remb_sender, remb_candidate);
@@ -608,7 +609,7 @@ TEST(PacketRouterRembTest,
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
clock.AdvanceTime(TimeDelta::Millis(1000));
- NiceMock<MockRtpRtcp> remb_sender;
+ NiceMock<MockRtpRtcpInterface> remb_sender;
constexpr bool remb_candidate = true;
packet_router.AddSendRtpModule(&remb_sender, remb_candidate);
@@ -630,7 +631,7 @@ TEST(PacketRouterRembTest,
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
clock.AdvanceTime(TimeDelta::Millis(1000));
- NiceMock<MockRtpRtcp> remb_sender;
+ NiceMock<MockRtpRtcpInterface> remb_sender;
constexpr bool remb_candidate = true;
packet_router.AddSendRtpModule(&remb_sender, remb_candidate);
@@ -652,7 +653,7 @@ TEST(PacketRouterRembTest,
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
clock.AdvanceTime(TimeDelta::Millis(1000));
- NiceMock<MockRtpRtcp> remb_sender;
+ NiceMock<MockRtpRtcpInterface> remb_sender;
constexpr bool remb_candidate = true;
packet_router.AddSendRtpModule(&remb_sender, remb_candidate);
@@ -674,7 +675,7 @@ TEST(PacketRouterRembTest,
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
clock.AdvanceTime(TimeDelta::Millis(1000));
- NiceMock<MockRtpRtcp> remb_sender;
+ NiceMock<MockRtpRtcpInterface> remb_sender;
constexpr bool remb_candidate = true;
packet_router.AddSendRtpModule(&remb_sender, remb_candidate);
@@ -697,7 +698,7 @@ TEST(PacketRouterRembTest,
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
clock.AdvanceTime(TimeDelta::Millis(1000));
- NiceMock<MockRtpRtcp> remb_sender;
+ NiceMock<MockRtpRtcpInterface> remb_sender;
constexpr bool remb_candidate = true;
packet_router.AddSendRtpModule(&remb_sender, remb_candidate);
@@ -719,7 +720,7 @@ TEST(PacketRouterRembTest,
// packet on this one.
TEST(PacketRouterRembTest, NoSendingRtpModule) {
rtc::ScopedFakeClock clock;
- NiceMock<MockRtpRtcp> rtp;
+ NiceMock<MockRtpRtcpInterface> rtp;
PacketRouter packet_router;
packet_router.AddReceiveRtpModule(&rtp, true);
@@ -745,7 +746,7 @@ TEST(PacketRouterRembTest, NoSendingRtpModule) {
TEST(PacketRouterRembTest, NonCandidateSendRtpModuleNotUsedForRemb) {
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
- NiceMock<MockRtpRtcp> module;
+ NiceMock<MockRtpRtcpInterface> module;
constexpr bool remb_candidate = false;
@@ -764,7 +765,7 @@ TEST(PacketRouterRembTest, NonCandidateSendRtpModuleNotUsedForRemb) {
TEST(PacketRouterRembTest, CandidateSendRtpModuleUsedForRemb) {
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
- NiceMock<MockRtpRtcp> module;
+ NiceMock<MockRtpRtcpInterface> module;
constexpr bool remb_candidate = true;
@@ -783,7 +784,7 @@ TEST(PacketRouterRembTest, CandidateSendRtpModuleUsedForRemb) {
TEST(PacketRouterRembTest, NonCandidateReceiveRtpModuleNotUsedForRemb) {
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
- NiceMock<MockRtpRtcp> module;
+ NiceMock<MockRtpRtcpInterface> module;
constexpr bool remb_candidate = false;
@@ -802,7 +803,7 @@ TEST(PacketRouterRembTest, NonCandidateReceiveRtpModuleNotUsedForRemb) {
TEST(PacketRouterRembTest, CandidateReceiveRtpModuleUsedForRemb) {
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
- NiceMock<MockRtpRtcp> module;
+ NiceMock<MockRtpRtcpInterface> module;
constexpr bool remb_candidate = true;
@@ -822,8 +823,8 @@ TEST(PacketRouterRembTest,
SendCandidatePreferredOverReceiveCandidate_SendModuleAddedFirst) {
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
- NiceMock<MockRtpRtcp> send_module;
- NiceMock<MockRtpRtcp> receive_module;
+ NiceMock<MockRtpRtcpInterface> send_module;
+ NiceMock<MockRtpRtcpInterface> receive_module;
constexpr bool remb_candidate = true;
@@ -850,8 +851,8 @@ TEST(PacketRouterRembTest,
SendCandidatePreferredOverReceiveCandidate_ReceiveModuleAddedFirst) {
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
- NiceMock<MockRtpRtcp> send_module;
- NiceMock<MockRtpRtcp> receive_module;
+ NiceMock<MockRtpRtcpInterface> send_module;
+ NiceMock<MockRtpRtcpInterface> receive_module;
constexpr bool remb_candidate = true;
@@ -877,8 +878,8 @@ TEST(PacketRouterRembTest,
TEST(PacketRouterRembTest, ReceiveModuleTakesOverWhenLastSendModuleRemoved) {
rtc::ScopedFakeClock clock;
PacketRouter packet_router;
- NiceMock<MockRtpRtcp> send_module;
- NiceMock<MockRtpRtcp> receive_module;
+ NiceMock<MockRtpRtcpInterface> send_module;
+ NiceMock<MockRtpRtcpInterface> receive_module;
constexpr bool remb_candidate = true;
diff --git a/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender.cc b/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender.cc
index 16d6df554c2..531e9d6ad32 100644
--- a/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender.cc
+++ b/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender.cc
@@ -17,6 +17,7 @@
#include "rtc_base/event.h"
#include "rtc_base/logging.h"
#include "rtc_base/task_utils/to_queued_task.h"
+#include "rtc_base/trace_event.h"
namespace webrtc {
namespace {
@@ -34,8 +35,10 @@ TaskQueuePacedSender::TaskQueuePacedSender(
PacketRouter* packet_router,
RtcEventLog* event_log,
const WebRtcKeyValueConfig* field_trials,
- TaskQueueFactory* task_queue_factory)
+ TaskQueueFactory* task_queue_factory,
+ TimeDelta hold_back_window)
: clock_(clock),
+ hold_back_window_(hold_back_window),
packet_router_(packet_router),
pacing_controller_(clock,
static_cast<PacingController::PacketSender*>(this),
@@ -120,6 +123,17 @@ void TaskQueuePacedSender::SetPacingRates(DataRate pacing_rate,
void TaskQueuePacedSender::EnqueuePackets(
std::vector<std::unique_ptr<RtpPacketToSend>> packets) {
+#if RTC_TRACE_EVENTS_ENABLED
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("webrtc"),
+ "TaskQueuePacedSender::EnqueuePackets");
+ for (auto& packet : packets) {
+ TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"),
+ "TaskQueuePacedSender::EnqueuePackets::Loop",
+ "sequence_number", packet->SequenceNumber(), "rtp_timestamp",
+ packet->Timestamp());
+ }
+#endif
+
task_queue_.PostTask([this, packets_ = std::move(packets)]() mutable {
RTC_DCHECK_RUN_ON(&task_queue_);
for (auto& packet : packets_) {
@@ -175,7 +189,7 @@ TimeDelta TaskQueuePacedSender::OldestPacketWaitTime() const {
}
void TaskQueuePacedSender::OnStatsUpdated(const Stats& stats) {
- rtc::CritScope cs(&stats_crit_);
+ MutexLock lock(&stats_mutex_);
current_stats_ = stats;
}
@@ -205,8 +219,10 @@ void TaskQueuePacedSender::MaybeProcessPackets(
next_process_time = pacing_controller_.NextSendTime();
}
- next_process_time =
- std::max(now + PacingController::kMinSleepTime, next_process_time);
+ const TimeDelta min_sleep = pacing_controller_.IsProbing()
+ ? PacingController::kMinSleepTime
+ : hold_back_window_;
+ next_process_time = std::max(now + min_sleep, next_process_time);
TimeDelta sleep_time = next_process_time - now;
if (next_process_time_.IsMinusInfinity() ||
@@ -295,7 +311,7 @@ void TaskQueuePacedSender::MaybeUpdateStats(bool is_scheduled_call) {
}
TaskQueuePacedSender::Stats TaskQueuePacedSender::GetStats() const {
- rtc::CritScope cs(&stats_crit_);
+ MutexLock lock(&stats_mutex_);
return current_stats_;
}
diff --git a/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender.h b/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender.h
index 3f53f000970..71b3be27e6f 100644
--- a/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender.h
+++ b/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender.h
@@ -30,6 +30,7 @@
#include "modules/pacing/rtp_packet_pacer.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "rtc_base/critical_section.h"
+#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/synchronization/sequence_checker.h"
#include "rtc_base/task_queue.h"
#include "rtc_base/thread_annotations.h"
@@ -42,11 +43,18 @@ class TaskQueuePacedSender : public RtpPacketPacer,
public RtpPacketSender,
private PacingController::PacketSender {
public:
- TaskQueuePacedSender(Clock* clock,
- PacketRouter* packet_router,
- RtcEventLog* event_log,
- const WebRtcKeyValueConfig* field_trials,
- TaskQueueFactory* task_queue_factory);
+ // The |hold_back_window| parameter sets a lower bound on time to sleep if
+ // there is currently a pacer queue and packets can't immediately be
+ // processed. Increasing this reduces thread wakeups at the expense of higher
+ // latency.
+ // TODO(bugs.webrtc.org/10809): Remove default value for hold_back_window.
+ TaskQueuePacedSender(
+ Clock* clock,
+ PacketRouter* packet_router,
+ RtcEventLog* event_log,
+ const WebRtcKeyValueConfig* field_trials,
+ TaskQueueFactory* task_queue_factory,
+ TimeDelta hold_back_window = PacingController::kMinSleepTime);
~TaskQueuePacedSender() override;
@@ -134,6 +142,7 @@ class TaskQueuePacedSender : public RtpPacketPacer,
Stats GetStats() const;
Clock* const clock_;
+ const TimeDelta hold_back_window_;
PacketRouter* const packet_router_ RTC_GUARDED_BY(task_queue_);
PacingController pacing_controller_ RTC_GUARDED_BY(task_queue_);
@@ -159,8 +168,8 @@ class TaskQueuePacedSender : public RtpPacketPacer,
// never drain.
bool is_shutdown_ RTC_GUARDED_BY(task_queue_);
- rtc::CriticalSection stats_crit_;
- Stats current_stats_ RTC_GUARDED_BY(stats_crit_);
+ mutable Mutex stats_mutex_;
+ Stats current_stats_ RTC_GUARDED_BY(stats_mutex_);
rtc::TaskQueue task_queue_;
};
diff --git a/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender_unittest.cc b/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender_unittest.cc
index 83aa73e9aaa..ab6a24ba42b 100644
--- a/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender_unittest.cc
+++ b/chromium/third_party/webrtc/modules/pacing/task_queue_paced_sender_unittest.cc
@@ -24,6 +24,7 @@
#include "test/time_controller/simulated_time_controller.h"
using ::testing::_;
+using ::testing::AtLeast;
using ::testing::Return;
using ::testing::SaveArg;
@@ -37,26 +38,40 @@ constexpr size_t kDefaultPacketSize = 1234;
class MockPacketRouter : public PacketRouter {
public:
- MOCK_METHOD2(SendPacket,
- void(std::unique_ptr<RtpPacketToSend> packet,
- const PacedPacketInfo& cluster_info));
- MOCK_METHOD1(
- GeneratePadding,
- std::vector<std::unique_ptr<RtpPacketToSend>>(size_t target_size_bytes));
+ MOCK_METHOD(void,
+ SendPacket,
+ (std::unique_ptr<RtpPacketToSend> packet,
+ const PacedPacketInfo& cluster_info),
+ (override));
+ MOCK_METHOD(std::vector<std::unique_ptr<RtpPacketToSend>>,
+ GeneratePadding,
+ (size_t target_size_bytes),
+ (override));
+};
+
+class StatsUpdateObserver {
+ public:
+ StatsUpdateObserver() = default;
+ virtual ~StatsUpdateObserver() = default;
+
+ virtual void OnStatsUpdated() = 0;
};
class TaskQueuePacedSenderForTest : public TaskQueuePacedSender {
public:
- TaskQueuePacedSenderForTest(Clock* clock,
- PacketRouter* packet_router,
- RtcEventLog* event_log,
- const WebRtcKeyValueConfig* field_trials,
- TaskQueueFactory* task_queue_factory)
+ TaskQueuePacedSenderForTest(
+ Clock* clock,
+ PacketRouter* packet_router,
+ RtcEventLog* event_log,
+ const WebRtcKeyValueConfig* field_trials,
+ TaskQueueFactory* task_queue_factory,
+ TimeDelta hold_back_window = PacingController::kMinSleepTime)
: TaskQueuePacedSender(clock,
packet_router,
event_log,
field_trials,
- task_queue_factory) {}
+ task_queue_factory,
+ hold_back_window) {}
void OnStatsUpdated(const Stats& stats) override {
++num_stats_updates_;
@@ -65,250 +80,327 @@ class TaskQueuePacedSenderForTest : public TaskQueuePacedSender {
size_t num_stats_updates_ = 0;
};
+} // namespace
-std::unique_ptr<RtpPacketToSend> BuildRtpPacket(RtpPacketMediaType type) {
- auto packet = std::make_unique<RtpPacketToSend>(nullptr);
- packet->set_packet_type(type);
- switch (type) {
- case RtpPacketMediaType::kAudio:
- packet->SetSsrc(kAudioSsrc);
- break;
- case RtpPacketMediaType::kVideo:
- packet->SetSsrc(kVideoSsrc);
- break;
- case RtpPacketMediaType::kRetransmission:
- case RtpPacketMediaType::kPadding:
- packet->SetSsrc(kVideoRtxSsrc);
- break;
- case RtpPacketMediaType::kForwardErrorCorrection:
- packet->SetSsrc(kFlexFecSsrc);
- break;
+namespace test {
+
+ std::unique_ptr<RtpPacketToSend> BuildRtpPacket(RtpPacketMediaType type) {
+ auto packet = std::make_unique<RtpPacketToSend>(nullptr);
+ packet->set_packet_type(type);
+ switch (type) {
+ case RtpPacketMediaType::kAudio:
+ packet->SetSsrc(kAudioSsrc);
+ break;
+ case RtpPacketMediaType::kVideo:
+ packet->SetSsrc(kVideoSsrc);
+ break;
+ case RtpPacketMediaType::kRetransmission:
+ case RtpPacketMediaType::kPadding:
+ packet->SetSsrc(kVideoRtxSsrc);
+ break;
+ case RtpPacketMediaType::kForwardErrorCorrection:
+ packet->SetSsrc(kFlexFecSsrc);
+ break;
+ }
+
+ packet->SetPayloadSize(kDefaultPacketSize);
+ return packet;
}
- packet->SetPayloadSize(kDefaultPacketSize);
- return packet;
-}
+ std::vector<std::unique_ptr<RtpPacketToSend>> GeneratePackets(
+ RtpPacketMediaType type,
+ size_t num_packets) {
+ std::vector<std::unique_ptr<RtpPacketToSend>> packets;
+ for (size_t i = 0; i < num_packets; ++i) {
+ packets.push_back(BuildRtpPacket(type));
+ }
+ return packets;
+ }
-std::vector<std::unique_ptr<RtpPacketToSend>> GeneratePackets(
- RtpPacketMediaType type,
- size_t num_packets) {
- std::vector<std::unique_ptr<RtpPacketToSend>> packets;
- for (size_t i = 0; i < num_packets; ++i) {
- packets.push_back(BuildRtpPacket(type));
+ TEST(TaskQueuePacedSenderTest, PacesPackets) {
+ GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
+ MockPacketRouter packet_router;
+ TaskQueuePacedSenderForTest pacer(
+ time_controller.GetClock(), &packet_router,
+ /*event_log=*/nullptr,
+ /*field_trials=*/nullptr, time_controller.GetTaskQueueFactory(),
+ PacingController::kMinSleepTime);
+
+ // Insert a number of packets, covering one second.
+ static constexpr size_t kPacketsToSend = 42;
+ pacer.SetPacingRates(
+ DataRate::BitsPerSec(kDefaultPacketSize * 8 * kPacketsToSend),
+ DataRate::Zero());
+ pacer.EnqueuePackets(
+ GeneratePackets(RtpPacketMediaType::kVideo, kPacketsToSend));
+
+ // Expect all of them to be sent.
+ size_t packets_sent = 0;
+ Timestamp end_time = Timestamp::PlusInfinity();
+ EXPECT_CALL(packet_router, SendPacket)
+ .WillRepeatedly([&](std::unique_ptr<RtpPacketToSend> packet,
+ const PacedPacketInfo& cluster_info) {
+ ++packets_sent;
+ if (packets_sent == kPacketsToSend) {
+ end_time = time_controller.GetClock()->CurrentTime();
+ }
+ });
+
+ const Timestamp start_time = time_controller.GetClock()->CurrentTime();
+
+ // Packets should be sent over a period of close to 1s. Expect a little
+ // lower than this since initial probing is a bit quicker.
+ time_controller.AdvanceTime(TimeDelta::Seconds(1));
+ EXPECT_EQ(packets_sent, kPacketsToSend);
+ ASSERT_TRUE(end_time.IsFinite());
+ EXPECT_NEAR((end_time - start_time).ms<double>(), 1000.0, 50.0);
}
- return packets;
-}
-} // namespace
-namespace test {
+ TEST(TaskQueuePacedSenderTest, ReschedulesProcessOnRateChange) {
+ GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
+ MockPacketRouter packet_router;
+ TaskQueuePacedSenderForTest pacer(
+ time_controller.GetClock(), &packet_router,
+ /*event_log=*/nullptr,
+ /*field_trials=*/nullptr, time_controller.GetTaskQueueFactory(),
+ PacingController::kMinSleepTime);
+
+ // Insert a number of packets to be sent 200ms apart.
+ const size_t kPacketsPerSecond = 5;
+ const DataRate kPacingRate =
+ DataRate::BitsPerSec(kDefaultPacketSize * 8 * kPacketsPerSecond);
+ pacer.SetPacingRates(kPacingRate, DataRate::Zero());
+
+ // Send some initial packets to be rid of any probes.
+ EXPECT_CALL(packet_router, SendPacket).Times(kPacketsPerSecond);
+ pacer.EnqueuePackets(
+ GeneratePackets(RtpPacketMediaType::kVideo, kPacketsPerSecond));
+ time_controller.AdvanceTime(TimeDelta::Seconds(1));
+
+ // Insert three packets, and record send time of each of them.
+ // After the second packet is sent, double the send rate so we can
+ // check the third packets is sent after half the wait time.
+ Timestamp first_packet_time = Timestamp::MinusInfinity();
+ Timestamp second_packet_time = Timestamp::MinusInfinity();
+ Timestamp third_packet_time = Timestamp::MinusInfinity();
+
+ EXPECT_CALL(packet_router, SendPacket)
+ .Times(3)
+ .WillRepeatedly([&](std::unique_ptr<RtpPacketToSend> packet,
+ const PacedPacketInfo& cluster_info) {
+ if (first_packet_time.IsInfinite()) {
+ first_packet_time = time_controller.GetClock()->CurrentTime();
+ } else if (second_packet_time.IsInfinite()) {
+ second_packet_time = time_controller.GetClock()->CurrentTime();
+ pacer.SetPacingRates(2 * kPacingRate, DataRate::Zero());
+ } else {
+ third_packet_time = time_controller.GetClock()->CurrentTime();
+ }
+ });
+
+ pacer.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kVideo, 3));
+ time_controller.AdvanceTime(TimeDelta::Millis(500));
+ ASSERT_TRUE(third_packet_time.IsFinite());
+ EXPECT_NEAR((second_packet_time - first_packet_time).ms<double>(), 200.0,
+ 1.0);
+ EXPECT_NEAR((third_packet_time - second_packet_time).ms<double>(), 100.0,
+ 1.0);
+ }
-class TaskQueuePacedSenderTest : public ::testing::Test {
- public:
- TaskQueuePacedSenderTest()
- : time_controller_(Timestamp::Millis(1234)),
- pacer_(time_controller_.GetClock(),
- &packet_router_,
- /*event_log=*/nullptr,
- /*field_trials=*/nullptr,
- time_controller_.GetTaskQueueFactory()) {}
-
- protected:
- Timestamp CurrentTime() { return time_controller_.GetClock()->CurrentTime(); }
-
- GlobalSimulatedTimeController time_controller_;
- MockPacketRouter packet_router_;
- TaskQueuePacedSender pacer_;
-};
+ TEST(TaskQueuePacedSenderTest, SendsAudioImmediately) {
+ GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
+ MockPacketRouter packet_router;
+ TaskQueuePacedSenderForTest pacer(
+ time_controller.GetClock(), &packet_router,
+ /*event_log=*/nullptr,
+ /*field_trials=*/nullptr, time_controller.GetTaskQueueFactory(),
+ PacingController::kMinSleepTime);
-TEST_F(TaskQueuePacedSenderTest, PacesPackets) {
- // Insert a number of packets, covering one second.
- static constexpr size_t kPacketsToSend = 42;
- pacer_.SetPacingRates(
- DataRate::BitsPerSec(kDefaultPacketSize * 8 * kPacketsToSend),
- DataRate::Zero());
- pacer_.EnqueuePackets(
- GeneratePackets(RtpPacketMediaType::kVideo, kPacketsToSend));
-
- // Expect all of them to be sent.
- size_t packets_sent = 0;
- Timestamp end_time = Timestamp::PlusInfinity();
- EXPECT_CALL(packet_router_, SendPacket)
- .WillRepeatedly([&](std::unique_ptr<RtpPacketToSend> packet,
- const PacedPacketInfo& cluster_info) {
- ++packets_sent;
- if (packets_sent == kPacketsToSend) {
- end_time = time_controller_.GetClock()->CurrentTime();
- }
- });
-
- const Timestamp start_time = time_controller_.GetClock()->CurrentTime();
-
- // Packets should be sent over a period of close to 1s. Expect a little lower
- // than this since initial probing is a bit quicker.
- time_controller_.AdvanceTime(TimeDelta::Seconds(1));
- EXPECT_EQ(packets_sent, kPacketsToSend);
- ASSERT_TRUE(end_time.IsFinite());
- EXPECT_NEAR((end_time - start_time).ms<double>(), 1000.0, 50.0);
-}
-
-TEST_F(TaskQueuePacedSenderTest, ReschedulesProcessOnRateChange) {
- // Insert a number of packets to be sent 200ms apart.
- const size_t kPacketsPerSecond = 5;
- const DataRate kPacingRate =
- DataRate::BitsPerSec(kDefaultPacketSize * 8 * kPacketsPerSecond);
- pacer_.SetPacingRates(kPacingRate, DataRate::Zero());
-
- // Send some initial packets to be rid of any probes.
- EXPECT_CALL(packet_router_, SendPacket).Times(kPacketsPerSecond);
- pacer_.EnqueuePackets(
- GeneratePackets(RtpPacketMediaType::kVideo, kPacketsPerSecond));
- time_controller_.AdvanceTime(TimeDelta::Seconds(1));
-
- // Insert three packets, and record send time of each of them.
- // After the second packet is sent, double the send rate so we can
- // check the third packets is sent after half the wait time.
- Timestamp first_packet_time = Timestamp::MinusInfinity();
- Timestamp second_packet_time = Timestamp::MinusInfinity();
- Timestamp third_packet_time = Timestamp::MinusInfinity();
-
- EXPECT_CALL(packet_router_, SendPacket)
- .Times(3)
- .WillRepeatedly([&](std::unique_ptr<RtpPacketToSend> packet,
- const PacedPacketInfo& cluster_info) {
- if (first_packet_time.IsInfinite()) {
- first_packet_time = CurrentTime();
- } else if (second_packet_time.IsInfinite()) {
- second_packet_time = CurrentTime();
- pacer_.SetPacingRates(2 * kPacingRate, DataRate::Zero());
- } else {
- third_packet_time = CurrentTime();
- }
- });
-
- pacer_.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kVideo, 3));
- time_controller_.AdvanceTime(TimeDelta::Millis(500));
- ASSERT_TRUE(third_packet_time.IsFinite());
- EXPECT_NEAR((second_packet_time - first_packet_time).ms<double>(), 200.0,
- 1.0);
- EXPECT_NEAR((third_packet_time - second_packet_time).ms<double>(), 100.0,
- 1.0);
-}
-
-TEST_F(TaskQueuePacedSenderTest, SendsAudioImmediately) {
- const DataRate kPacingDataRate = DataRate::KilobitsPerSec(125);
- const DataSize kPacketSize = DataSize::Bytes(kDefaultPacketSize);
- const TimeDelta kPacketPacingTime = kPacketSize / kPacingDataRate;
-
- pacer_.SetPacingRates(kPacingDataRate, DataRate::Zero());
-
- // Add some initial video packets, only one should be sent.
- EXPECT_CALL(packet_router_, SendPacket);
- pacer_.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kVideo, 10));
- time_controller_.AdvanceTime(TimeDelta::Zero());
- ::testing::Mock::VerifyAndClearExpectations(&packet_router_);
-
- // Advance time, but still before next packet should be sent.
- time_controller_.AdvanceTime(kPacketPacingTime / 2);
-
- // Insert an audio packet, it should be sent immediately.
- EXPECT_CALL(packet_router_, SendPacket);
- pacer_.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kAudio, 1));
- time_controller_.AdvanceTime(TimeDelta::Zero());
- ::testing::Mock::VerifyAndClearExpectations(&packet_router_);
-}
-
-TEST(TaskQueuePacedSenderTestNew, RespectedMinTimeBetweenStatsUpdates) {
- GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
- MockPacketRouter packet_router;
- TaskQueuePacedSenderForTest pacer(time_controller.GetClock(), &packet_router,
- /*event_log=*/nullptr,
- /*field_trials=*/nullptr,
- time_controller.GetTaskQueueFactory());
- const DataRate kPacingDataRate = DataRate::KilobitsPerSec(300);
- pacer.SetPacingRates(kPacingDataRate, DataRate::Zero());
-
- const TimeDelta kMinTimeBetweenStatsUpdates = TimeDelta::Millis(1);
-
- // Nothing inserted, no stats updates yet.
- EXPECT_EQ(pacer.num_stats_updates_, 0u);
-
- // Insert one packet, stats should be updated.
- pacer.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kVideo, 1));
- time_controller.AdvanceTime(TimeDelta::Zero());
- EXPECT_EQ(pacer.num_stats_updates_, 1u);
-
- // Advance time half of the min stats update interval, and trigger a
- // refresh - stats should not be updated yet.
- time_controller.AdvanceTime(kMinTimeBetweenStatsUpdates / 2);
- pacer.EnqueuePackets({});
- time_controller.AdvanceTime(TimeDelta::Zero());
- EXPECT_EQ(pacer.num_stats_updates_, 1u);
-
- // Advance time the next half, now stats update is triggered.
- time_controller.AdvanceTime(kMinTimeBetweenStatsUpdates / 2);
- pacer.EnqueuePackets({});
- time_controller.AdvanceTime(TimeDelta::Zero());
- EXPECT_EQ(pacer.num_stats_updates_, 2u);
-}
-
-TEST(TaskQueuePacedSenderTestNew, ThrottlesStatsUpdates) {
- GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
- MockPacketRouter packet_router;
- TaskQueuePacedSenderForTest pacer(time_controller.GetClock(), &packet_router,
- /*event_log=*/nullptr,
- /*field_trials=*/nullptr,
- time_controller.GetTaskQueueFactory());
-
- // Set rates so one packet adds 10ms of buffer level.
- const DataSize kPacketSize = DataSize::Bytes(kDefaultPacketSize);
- const TimeDelta kPacketPacingTime = TimeDelta::Millis(10);
- const DataRate kPacingDataRate = kPacketSize / kPacketPacingTime;
- const TimeDelta kMinTimeBetweenStatsUpdates = TimeDelta::Millis(1);
- const TimeDelta kMaxTimeBetweenStatsUpdates = TimeDelta::Millis(33);
-
- // Nothing inserted, no stats updates yet.
- size_t num_expected_stats_updates = 0;
- EXPECT_EQ(pacer.num_stats_updates_, num_expected_stats_updates);
- pacer.SetPacingRates(kPacingDataRate, DataRate::Zero());
- time_controller.AdvanceTime(kMinTimeBetweenStatsUpdates);
- // Updating pacing rates refreshes stats.
- EXPECT_EQ(pacer.num_stats_updates_, ++num_expected_stats_updates);
-
- // Record time when we insert first packet, this triggers the scheduled
- // stats updating.
- Clock* const clock = time_controller.GetClock();
- const Timestamp start_time = clock->CurrentTime();
-
- while (clock->CurrentTime() - start_time <=
- kMaxTimeBetweenStatsUpdates - kPacketPacingTime) {
- // Enqueue packet, expect stats update.
- pacer.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kVideo, 1));
+ const DataRate kPacingDataRate = DataRate::KilobitsPerSec(125);
+ const DataSize kPacketSize = DataSize::Bytes(kDefaultPacketSize);
+ const TimeDelta kPacketPacingTime = kPacketSize / kPacingDataRate;
+
+ pacer.SetPacingRates(kPacingDataRate, DataRate::Zero());
+
+ // Add some initial video packets, only one should be sent.
+ EXPECT_CALL(packet_router, SendPacket);
+ pacer.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kVideo, 10));
time_controller.AdvanceTime(TimeDelta::Zero());
- EXPECT_EQ(pacer.num_stats_updates_, ++num_expected_stats_updates);
+ ::testing::Mock::VerifyAndClearExpectations(&packet_router);
- // Advance time to halfway through pacing time, expect another stats
- // update.
+ // Advance time, but still before next packet should be sent.
time_controller.AdvanceTime(kPacketPacingTime / 2);
+
+ // Insert an audio packet, it should be sent immediately.
+ EXPECT_CALL(packet_router, SendPacket);
+ pacer.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kAudio, 1));
+ time_controller.AdvanceTime(TimeDelta::Zero());
+ ::testing::Mock::VerifyAndClearExpectations(&packet_router);
+ }
+
+ TEST(TaskQueuePacedSenderTest, SleepsDuringCoalscingWindow) {
+ const TimeDelta kCoalescingWindow = TimeDelta::Millis(5);
+ GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
+ MockPacketRouter packet_router;
+ TaskQueuePacedSenderForTest pacer(
+ time_controller.GetClock(), &packet_router,
+ /*event_log=*/nullptr,
+ /*field_trials=*/nullptr, time_controller.GetTaskQueueFactory(),
+ kCoalescingWindow);
+
+ // Set rates so one packet adds one ms of buffer level.
+ const DataSize kPacketSize = DataSize::Bytes(kDefaultPacketSize);
+ const TimeDelta kPacketPacingTime = TimeDelta::Millis(1);
+ const DataRate kPacingDataRate = kPacketSize / kPacketPacingTime;
+
+ pacer.SetPacingRates(kPacingDataRate, DataRate::Zero());
+
+ // Add 10 packets. The first should be sent immediately since the buffers
+ // are clear.
+ EXPECT_CALL(packet_router, SendPacket);
+ pacer.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kVideo, 10));
+ time_controller.AdvanceTime(TimeDelta::Zero());
+ ::testing::Mock::VerifyAndClearExpectations(&packet_router);
+
+ // Advance time to 1ms before the coalescing window ends. No packets should
+ // be sent.
+ EXPECT_CALL(packet_router, SendPacket).Times(0);
+ time_controller.AdvanceTime(kCoalescingWindow - TimeDelta::Millis(1));
+
+ // Advance time to where coalescing window ends. All packets that should
+ // have been sent up til now will be sent.
+ EXPECT_CALL(packet_router, SendPacket).Times(5);
+ time_controller.AdvanceTime(TimeDelta::Millis(1));
+ ::testing::Mock::VerifyAndClearExpectations(&packet_router);
+ }
+
+ TEST(TaskQueuePacedSenderTest, ProbingOverridesCoalescingWindow) {
+ const TimeDelta kCoalescingWindow = TimeDelta::Millis(5);
+ GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
+ MockPacketRouter packet_router;
+ TaskQueuePacedSenderForTest pacer(
+ time_controller.GetClock(), &packet_router,
+ /*event_log=*/nullptr,
+ /*field_trials=*/nullptr, time_controller.GetTaskQueueFactory(),
+ kCoalescingWindow);
+
+ // Set rates so one packet adds one ms of buffer level.
+ const DataSize kPacketSize = DataSize::Bytes(kDefaultPacketSize);
+ const TimeDelta kPacketPacingTime = TimeDelta::Millis(1);
+ const DataRate kPacingDataRate = kPacketSize / kPacketPacingTime;
+
+ pacer.SetPacingRates(kPacingDataRate, DataRate::Zero());
+
+ // Add 10 packets. The first should be sent immediately since the buffers
+ // are clear. This will also trigger the probe to start.
+ EXPECT_CALL(packet_router, SendPacket).Times(AtLeast(1));
+ pacer.CreateProbeCluster(kPacingDataRate * 2, 17);
+ pacer.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kVideo, 10));
+ time_controller.AdvanceTime(TimeDelta::Zero());
+ ::testing::Mock::VerifyAndClearExpectations(&packet_router);
+
+ // Advance time to 1ms before the coalescing window ends. Packets should be
+ // flying.
+ EXPECT_CALL(packet_router, SendPacket).Times(AtLeast(1));
+ time_controller.AdvanceTime(kCoalescingWindow - TimeDelta::Millis(1));
+ }
+
+ TEST(TaskQueuePacedSenderTest, RespectedMinTimeBetweenStatsUpdates) {
+ const TimeDelta kCoalescingWindow = TimeDelta::Millis(5);
+ GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
+ MockPacketRouter packet_router;
+ TaskQueuePacedSenderForTest pacer(
+ time_controller.GetClock(), &packet_router,
+ /*event_log=*/nullptr,
+ /*field_trials=*/nullptr, time_controller.GetTaskQueueFactory(),
+ kCoalescingWindow);
+ const DataRate kPacingDataRate = DataRate::KilobitsPerSec(300);
+ pacer.SetPacingRates(kPacingDataRate, DataRate::Zero());
+
+ const TimeDelta kMinTimeBetweenStatsUpdates = TimeDelta::Millis(1);
+
+ // Nothing inserted, no stats updates yet.
+ EXPECT_EQ(pacer.num_stats_updates_, 0u);
+
+ // Insert one packet, stats should be updated.
+ pacer.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kVideo, 1));
+ time_controller.AdvanceTime(TimeDelta::Zero());
+ EXPECT_EQ(pacer.num_stats_updates_, 1u);
+
+ // Advance time half of the min stats update interval, and trigger a
+ // refresh - stats should not be updated yet.
+ time_controller.AdvanceTime(kMinTimeBetweenStatsUpdates / 2);
pacer.EnqueuePackets({});
time_controller.AdvanceTime(TimeDelta::Zero());
- EXPECT_EQ(pacer.num_stats_updates_, ++num_expected_stats_updates);
+ EXPECT_EQ(pacer.num_stats_updates_, 1u);
- // Advance time the rest of the way.
- time_controller.AdvanceTime(kPacketPacingTime / 2);
+ // Advance time the next half, now stats update is triggered.
+ time_controller.AdvanceTime(kMinTimeBetweenStatsUpdates / 2);
+ pacer.EnqueuePackets({});
+ time_controller.AdvanceTime(TimeDelta::Zero());
+ EXPECT_EQ(pacer.num_stats_updates_, 2u);
}
- // At this point, the pace queue is drained so there is no more intersting
- // update to be made - but there is still as schduled task that should run
- // |kMaxTimeBetweenStatsUpdates| after the first update.
- time_controller.AdvanceTime(start_time + kMaxTimeBetweenStatsUpdates -
- clock->CurrentTime());
- EXPECT_EQ(pacer.num_stats_updates_, ++num_expected_stats_updates);
-
- // Advance time a significant time - don't expect any more calls as stats
- // updating does not happen when queue is drained.
- time_controller.AdvanceTime(TimeDelta::Millis(400));
- EXPECT_EQ(pacer.num_stats_updates_, num_expected_stats_updates);
-}
+ TEST(TaskQueuePacedSenderTest, ThrottlesStatsUpdates) {
+ const TimeDelta kCoalescingWindow = TimeDelta::Millis(5);
+ GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
+ MockPacketRouter packet_router;
+ TaskQueuePacedSenderForTest pacer(
+ time_controller.GetClock(), &packet_router,
+ /*event_log=*/nullptr,
+ /*field_trials=*/nullptr, time_controller.GetTaskQueueFactory(),
+ kCoalescingWindow);
+
+ // Set rates so one packet adds 10ms of buffer level.
+ const DataSize kPacketSize = DataSize::Bytes(kDefaultPacketSize);
+ const TimeDelta kPacketPacingTime = TimeDelta::Millis(10);
+ const DataRate kPacingDataRate = kPacketSize / kPacketPacingTime;
+ const TimeDelta kMinTimeBetweenStatsUpdates = TimeDelta::Millis(1);
+ const TimeDelta kMaxTimeBetweenStatsUpdates = TimeDelta::Millis(33);
+
+ // Nothing inserted, no stats updates yet.
+ size_t num_expected_stats_updates = 0;
+ EXPECT_EQ(pacer.num_stats_updates_, num_expected_stats_updates);
+ pacer.SetPacingRates(kPacingDataRate, DataRate::Zero());
+ time_controller.AdvanceTime(kMinTimeBetweenStatsUpdates);
+ // Updating pacing rates refreshes stats.
+ EXPECT_EQ(pacer.num_stats_updates_, ++num_expected_stats_updates);
+
+ // Record time when we insert first packet, this triggers the scheduled
+ // stats updating.
+ Clock* const clock = time_controller.GetClock();
+ const Timestamp start_time = clock->CurrentTime();
+
+ while (clock->CurrentTime() - start_time <=
+ kMaxTimeBetweenStatsUpdates - kPacketPacingTime) {
+ // Enqueue packet, expect stats update.
+ pacer.EnqueuePackets(GeneratePackets(RtpPacketMediaType::kVideo, 1));
+ time_controller.AdvanceTime(TimeDelta::Zero());
+ EXPECT_EQ(pacer.num_stats_updates_, ++num_expected_stats_updates);
+
+ // Advance time to halfway through pacing time, expect another stats
+ // update.
+ time_controller.AdvanceTime(kPacketPacingTime / 2);
+ pacer.EnqueuePackets({});
+ time_controller.AdvanceTime(TimeDelta::Zero());
+ EXPECT_EQ(pacer.num_stats_updates_, ++num_expected_stats_updates);
+
+ // Advance time the rest of the way.
+ time_controller.AdvanceTime(kPacketPacingTime / 2);
+ }
+
+ // At this point, the pace queue is drained so there is no more intersting
+ // update to be made - but there is still as schduled task that should run
+ // |kMaxTimeBetweenStatsUpdates| after the first update.
+ time_controller.AdvanceTime(start_time + kMaxTimeBetweenStatsUpdates -
+ clock->CurrentTime());
+ EXPECT_EQ(pacer.num_stats_updates_, ++num_expected_stats_updates);
+
+ // Advance time a significant time - don't expect any more calls as stats
+ // updating does not happen when queue is drained.
+ time_controller.AdvanceTime(TimeDelta::Millis(400));
+ EXPECT_EQ(pacer.num_stats_updates_, num_expected_stats_updates);
+ }
} // namespace test
} // namespace webrtc