diff --git a/modules/pacing/prioritized_packet_queue.cc b/modules/pacing/prioritized_packet_queue.cc index 15964848c2..2d0d829648 100644 --- a/modules/pacing/prioritized_packet_queue.cc +++ b/modules/pacing/prioritized_packet_queue.cc @@ -410,22 +410,24 @@ void PrioritizedPacketQueue::DequeuePacketInternal(QueuedPacket& packet) { } void PrioritizedPacketQueue::MaybeUpdateTopPrioLevel() { - if (top_active_prio_level_ == -1 || - streams_by_prio_[top_active_prio_level_].empty()) { - // No stream queues have packets at this prio level, find top priority - // that is not empty. - if (size_packets_ == 0) { - top_active_prio_level_ = -1; - } else { - for (int i = 0; i < kNumPriorityLevels; ++i) { - PurgeOldPacketsAtPriorityLevel(i, last_update_time_); - if (!streams_by_prio_[i].empty()) { - top_active_prio_level_ = i; - break; - } - } + if (top_active_prio_level_ != -1 && + !streams_by_prio_[top_active_prio_level_].empty()) { + return; + } + // No stream queues have packets at top_active_prio_level_, find top priority + // that is not empty. + for (int i = 0; i < kNumPriorityLevels; ++i) { + PurgeOldPacketsAtPriorityLevel(i, last_update_time_); + if (!streams_by_prio_[i].empty()) { + top_active_prio_level_ = i; + break; } } + if (size_packets_ == 0) { + // There are no packets left to send. Last packet may have been purged. Prio + // will change when a new packet is pushed. + top_active_prio_level_ = -1; + } } void PrioritizedPacketQueue::PurgeOldPacketsAtPriorityLevel(int prio_level, diff --git a/modules/pacing/prioritized_packet_queue_unittest.cc b/modules/pacing/prioritized_packet_queue_unittest.cc index f0c5f0eb1c..76c31036b3 100644 --- a/modules/pacing/prioritized_packet_queue_unittest.cc +++ b/modules/pacing/prioritized_packet_queue_unittest.cc @@ -519,6 +519,29 @@ TEST(PrioritizedPacketQueue, DontSendPacketsAfterTttl) { EXPECT_EQ(queue.SizeInPackets(), 0); } +TEST(PrioritizedPacketQueue, SendsNewVideoPacketAfterPurgingLastOldRtxPacket) { + Timestamp now = Timestamp::Zero(); + PacketQueueTTL ttls; + ttls.video_retransmission = TimeDelta::Millis(400); + PrioritizedPacketQueue queue(now, /*prioritize_audio_retransmission=*/true, + ttls); + + queue.Push(now, + CreateRetransmissionPacket(RtpPacketMediaType::kVideo, /*seq=*/1)); + now += ttls.video_retransmission + TimeDelta::Millis(1); + queue.Push(now, CreatePacket(RtpPacketMediaType::kAudio, /*seq=*/2)); + EXPECT_EQ(queue.SizeInPackets(), 2); + // Expect the audio packet to be send and the video retransmission packet to + // be dropped since it is old. + EXPECT_EQ(queue.Pop()->SequenceNumber(), 2); + EXPECT_EQ(queue.SizeInPackets(), 0); + + queue.Push(now, CreatePacket(RtpPacketMediaType::kVideo, /*seq=*/3)); + EXPECT_EQ(queue.SizeInPackets(), 1); + EXPECT_EQ(queue.Pop()->SequenceNumber(), 3); + EXPECT_EQ(queue.SizeInPackets(), 0); +} + TEST(PrioritizedPacketQueue, SendsPacketsAfterTttlIfPrioHigherThanPushedPackets) { Timestamp now = Timestamp::Zero();