Fix issue with pacing rate after long queue times.

A recent cleanup cl (r36900) had an unintended side-effect.

If the queue-time limit is expected to be hit, we adjust the pacing
bitrate up to make sure all packets are sent within the nominal time
frame.
However after that change we stopped adjusting the pacing rate back to
normal levels when queue clears - at least not until the next BWE
update (which is fairly often - but not immediate).

This CL fixes that, and also makes sure whe properly update the
adjusted media rate on enqueu, dequeue and set rate calls.

Bug: webrtc:10809
Change-Id: If00dc35169f1a1347fea6eb44fdb2868282ed3b7
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/265387
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Commit-Queue: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37178}
This commit is contained in:
Erik Språng
2022-06-10 11:42:15 +02:00
committed by WebRTC LUCI CQ
parent da12e10aba
commit df9e51a190
3 changed files with 102 additions and 81 deletions

View File

@ -1096,45 +1096,6 @@ TEST_F(PacingControllerTest, InactiveFromStart) {
2 * PacingController::kPausedProcessInterval);
}
TEST_F(PacingControllerTest, ExpectedQueueTimeMs) {
uint32_t ssrc = 12346;
uint16_t sequence_number = 1234;
const size_t kNumPackets = 60;
const size_t kPacketSize = 1200;
const int32_t kMaxBitrate = kPaceMultiplier * 30000;
auto pacer = std::make_unique<PacingController>(&clock_, &callback_, trials_);
pacer->SetPacingRates(kTargetRate * kPaceMultiplier, DataRate::Zero());
EXPECT_TRUE(pacer->OldestPacketEnqueueTime().IsInfinite());
pacer->SetPacingRates(DataRate::BitsPerSec(30000 * kPaceMultiplier),
DataRate::Zero());
for (size_t i = 0; i < kNumPackets; ++i) {
SendAndExpectPacket(pacer.get(), RtpPacketMediaType::kVideo, ssrc,
sequence_number++, clock_.TimeInMilliseconds(),
kPacketSize);
}
// Queue in ms = 1000 * (bytes in queue) *8 / (bits per second)
TimeDelta queue_time =
TimeDelta::Millis(1000 * kNumPackets * kPacketSize * 8 / kMaxBitrate);
EXPECT_EQ(queue_time, pacer->ExpectedQueueTime());
const Timestamp time_start = clock_.CurrentTime();
while (pacer->QueueSizePackets() > 0) {
AdvanceTimeUntil(pacer->NextSendTime());
pacer->ProcessPackets();
}
TimeDelta duration = clock_.CurrentTime() - time_start;
EXPECT_EQ(TimeDelta::Zero(), pacer->ExpectedQueueTime());
// Allow for aliasing, duration should be within one pack of max time limit.
const TimeDelta deviation =
duration - PacingController::kMaxExpectedQueueLength;
EXPECT_LT(deviation.Abs(),
TimeDelta::Millis(1000 * kPacketSize * 8 / kMaxBitrate));
}
TEST_F(PacingControllerTest, QueueTimeGrowsOverTime) {
uint32_t ssrc = 12346;
uint16_t sequence_number = 1234;
@ -1756,7 +1717,7 @@ TEST_F(PacingControllerTest,
}
}
TEST_F(PacingControllerTest, AccountsForAudioEnqueuTime) {
TEST_F(PacingControllerTest, AccountsForAudioEnqueueTime) {
const uint32_t kSsrc = 12345;
const DataRate kPacingDataRate = DataRate::KilobitsPerSec(125);
const DataRate kPaddingDataRate = DataRate::Zero();
@ -2063,5 +2024,45 @@ TEST_F(PacingControllerTest, RespectsTargetRateWhenSendingPacketsInBursts) {
EXPECT_EQ(number_of_bursts, 4);
}
TEST_F(PacingControllerTest, RespectsQueueTimeLimit) {
static constexpr DataSize kPacketSize = DataSize::Bytes(100);
static constexpr DataRate kNominalPacingRate = DataRate::KilobitsPerSec(200);
static constexpr TimeDelta kPacketPacingTime =
kPacketSize / kNominalPacingRate;
static constexpr TimeDelta kQueueTimeLimit = TimeDelta::Millis(1000);
PacingController pacer(&clock_, &callback_, trials_);
pacer.SetPacingRates(kNominalPacingRate, /*padding_rate=*/DataRate::Zero());
pacer.SetQueueTimeLimit(kQueueTimeLimit);
// Fill pacer up to queue time limit.
static constexpr int kNumPackets = kQueueTimeLimit / kPacketPacingTime;
for (int i = 0; i < kNumPackets; ++i) {
pacer.EnqueuePacket(video_.BuildNextPacket(kPacketSize.bytes()));
}
EXPECT_EQ(pacer.ExpectedQueueTime(), kQueueTimeLimit);
EXPECT_EQ(pacer.pacing_rate(), kNominalPacingRate);
// Double the amount of packets in the queue, the queue time limit should
// effectively double the pacing rate in response.
for (int i = 0; i < kNumPackets; ++i) {
pacer.EnqueuePacket(video_.BuildNextPacket(kPacketSize.bytes()));
}
EXPECT_EQ(pacer.ExpectedQueueTime(), kQueueTimeLimit);
EXPECT_EQ(pacer.pacing_rate(), 2 * kNominalPacingRate);
// Send all the packets, should take as long as the queue time limit.
Timestamp start_time = clock_.CurrentTime();
while (pacer.QueueSizePackets() > 0) {
AdvanceTimeUntil(pacer.NextSendTime());
pacer.ProcessPackets();
}
EXPECT_EQ(clock_.CurrentTime() - start_time, kQueueTimeLimit);
// We're back in a normal state - pacing rate should be back to previous
// levels.
EXPECT_EQ(pacer.pacing_rate(), kNominalPacingRate);
}
} // namespace
} // namespace webrtc