commit 6ab7a68262240625f16ced2522206376712d9428
parent 28f960657f424793ea5ac989d22aa5e1a77dff3c
Author: Dan Baker <dbaker@mozilla.com>
Date: Mon, 27 Oct 2025 15:29:22 -0600
Bug 1995393 - Vendor libwebrtc from 73aba0d728
Upstream commit: https://webrtc.googlesource.com/src/+/73aba0d7280f7fbd93a11a18d6b7eb713fe06e02
Ensures that TaskQueuePacedSender::SetPacingRates does not recursively send packets
This cl ensures that API methods do no trigger sending a packet in the
same call stack in order to avoid recursive invocation of the send function.
Bug: chromium:40242052, b/441565798
Change-Id: Ifd1038b5a42671432ed4877b277df3d05e8afc67
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/406781
Commit-Queue: Per Kjellander <perkj@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Reviewed-by: Markus Handell <handellm@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#45489}
Diffstat:
5 files changed, 58 insertions(+), 16 deletions(-)
diff --git a/third_party/libwebrtc/README.mozilla.last-vendor b/third_party/libwebrtc/README.mozilla.last-vendor
@@ -1,4 +1,4 @@
# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc --commit mozpatches libwebrtc
-libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-27T21:27:05.517565+00:00.
+libwebrtc updated from /Users/danielbaker/elm/.moz-fast-forward/moz-libwebrtc commit mozpatches on 2025-10-27T21:29:10.797855+00:00.
# base of lastest vendoring
-624780b387
+73aba0d728
diff --git a/third_party/libwebrtc/modules/pacing/BUILD.gn b/third_party/libwebrtc/modules/pacing/BUILD.gn
@@ -104,6 +104,7 @@ if (rtc_include_tests) {
"../../test/time_controller",
"../rtp_rtcp:mock_rtp_rtcp",
"../rtp_rtcp:rtp_rtcp_format",
+ "//third_party/abseil-cpp/absl/cleanup",
]
}
}
diff --git a/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.cc b/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.cc
@@ -75,14 +75,20 @@ void TaskQueuePacedSender::SetAllowProbeWithoutMediaPacket(bool allow) {
void TaskQueuePacedSender::EnsureStarted() {
RTC_DCHECK_RUN_ON(task_queue_);
is_started_ = true;
- MaybeProcessPackets(Timestamp::MinusInfinity());
+ PostMaybeProcessPackets();
}
void TaskQueuePacedSender::CreateProbeClusters(
std::vector<ProbeClusterConfig> probe_cluster_configs) {
RTC_DCHECK_RUN_ON(task_queue_);
pacing_controller_.CreateProbeClusters(probe_cluster_configs);
- MaybeScheduleProcessPackets();
+
+ // Probing should be scheduled regardless of if the queue is empty or not in
+ // order to be able to BWE probe before media is sent.
+ task_queue_->PostTask(SafeTask(safety_.flag(), [this]() {
+ RTC_DCHECK_RUN_ON(task_queue_);
+ MaybeProcessPackets(Timestamp::MinusInfinity());
+ }));
}
void TaskQueuePacedSender::Pause() {
@@ -93,20 +99,20 @@ void TaskQueuePacedSender::Pause() {
void TaskQueuePacedSender::Resume() {
RTC_DCHECK_RUN_ON(task_queue_);
pacing_controller_.Resume();
- MaybeProcessPackets(Timestamp::MinusInfinity());
+ PostMaybeProcessPackets();
}
void TaskQueuePacedSender::SetCongested(bool congested) {
RTC_DCHECK_RUN_ON(task_queue_);
pacing_controller_.SetCongested(congested);
- MaybeScheduleProcessPackets();
+ PostMaybeProcessPackets();
}
void TaskQueuePacedSender::SetPacingRates(DataRate pacing_rate,
DataRate padding_rate) {
RTC_DCHECK_RUN_ON(task_queue_);
pacing_controller_.SetPacingRates(pacing_rate, padding_rate);
- MaybeScheduleProcessPackets();
+ PostMaybeProcessPackets();
}
void TaskQueuePacedSender::EnqueuePackets(
@@ -145,26 +151,26 @@ void TaskQueuePacedSender::RemovePacketsForSsrc(uint32_t ssrc) {
void TaskQueuePacedSender::SetAccountForAudioPackets(bool account_for_audio) {
RTC_DCHECK_RUN_ON(task_queue_);
pacing_controller_.SetAccountForAudioPackets(account_for_audio);
- MaybeProcessPackets(Timestamp::MinusInfinity());
+ PostMaybeProcessPackets();
}
void TaskQueuePacedSender::SetIncludeOverhead() {
RTC_DCHECK_RUN_ON(task_queue_);
include_overhead_ = true;
pacing_controller_.SetIncludeOverhead();
- MaybeProcessPackets(Timestamp::MinusInfinity());
+ PostMaybeProcessPackets();
}
void TaskQueuePacedSender::SetTransportOverhead(DataSize overhead_per_packet) {
RTC_DCHECK_RUN_ON(task_queue_);
pacing_controller_.SetTransportOverhead(overhead_per_packet);
- MaybeProcessPackets(Timestamp::MinusInfinity());
+ PostMaybeProcessPackets();
}
void TaskQueuePacedSender::SetQueueTimeLimit(TimeDelta limit) {
RTC_DCHECK_RUN_ON(task_queue_);
pacing_controller_.SetQueueTimeLimit(limit);
- MaybeProcessPackets(Timestamp::MinusInfinity());
+ PostMaybeProcessPackets();
}
TimeDelta TaskQueuePacedSender::ExpectedQueueTime() const {
@@ -199,10 +205,14 @@ void TaskQueuePacedSender::OnStatsUpdated(const Stats& stats) {
current_stats_ = stats;
}
-// RTC_RUN_ON(task_queue_)
-void TaskQueuePacedSender::MaybeScheduleProcessPackets() {
- if (!processing_packets_)
+void TaskQueuePacedSender::PostMaybeProcessPackets() {
+ if (pacing_controller_.QueueSizePackets() == 0) {
+ return;
+ }
+ task_queue_->PostTask(SafeTask(safety_.flag(), [this]() {
+ RTC_DCHECK_RUN_ON(task_queue_);
MaybeProcessPackets(Timestamp::MinusInfinity());
+ }));
}
void TaskQueuePacedSender::MaybeProcessPackets(
diff --git a/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.h b/third_party/libwebrtc/modules/pacing/task_queue_paced_sender.h
@@ -136,8 +136,10 @@ class TaskQueuePacedSender : public RtpPacketPacer, public RtpPacketSender {
private:
// Call in response to state updates that could warrant sending out packets.
- // Protected against re-entry from packet sent receipts.
- void MaybeScheduleProcessPackets() RTC_RUN_ON(task_queue_);
+ // API methods should use this method if the method can be executed as a
+ // consequence of sending a packet to avoid sending another packet in the same
+ // call stack.
+ void PostMaybeProcessPackets() RTC_RUN_ON(task_queue_);
// Check if it is time to send packets, or schedule a delayed task if not.
// Use Timestamp::MinusInfinity() to indicate that this call has _not_
// been scheduled by the pacing controller. If this is the case, check if we
diff --git a/third_party/libwebrtc/modules/pacing/task_queue_paced_sender_unittest.cc b/third_party/libwebrtc/modules/pacing/task_queue_paced_sender_unittest.cc
@@ -17,6 +17,7 @@
#include <utility>
#include <vector>
+#include "absl/cleanup/cleanup.h"
#include "api/field_trials.h"
#include "api/sequence_checker.h"
#include "api/task_queue/task_queue_base.h"
@@ -751,5 +752,33 @@ TEST(TaskQueuePacedSenderTest, Stats) {
EXPECT_TRUE(pacer.ExpectedQueueTime().IsZero());
}
+TEST(TaskQueuePacedSenderTest,
+ ChangePacingRateInSentPacketCallstackDoesNotSendNextPacketInSameStack) {
+ FieldTrials trials = CreateTestFieldTrials();
+ GlobalSimulatedTimeController time_controller(Timestamp::Millis(1234));
+ MockPacketRouter packet_router;
+ TaskQueuePacedSender pacer(time_controller.GetClock(), &packet_router, trials,
+ PacingController::kMinSleepTime,
+ TaskQueuePacedSender::kNoPacketHoldback);
+ pacer.EnsureStarted();
+ pacer.SetPacingRates(DataRate::KilobitsPerSec(500),
+ /*padding_rate=*/DataRate::Zero());
+
+ bool send_packet_stack = false;
+ EXPECT_CALL(packet_router, SendPacket)
+ .Times(2)
+ .WillRepeatedly([&](std::unique_ptr<RtpPacketToSend> packet,
+ const PacedPacketInfo& cluster_info) {
+ EXPECT_FALSE(send_packet_stack);
+ send_packet_stack = true;
+ absl::Cleanup cleanup = [&] { send_packet_stack = false; };
+ pacer.SetPacingRates(DataRate::KilobitsPerSec(1000),
+ /*padding_rate=*/DataRate::Zero());
+ });
+ pacer.EnqueuePackets(
+ GeneratePackets(RtpPacketMediaType::kVideo, /*num_packets=*/2));
+ time_controller.AdvanceTime(TimeDelta::Millis(10));
+}
+
} // namespace test
} // namespace webrtc