prioritized_packet_queue.h (7471B)
1 /* 2 * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef MODULES_PACING_PRIORITIZED_PACKET_QUEUE_H_ 12 #define MODULES_PACING_PRIORITIZED_PACKET_QUEUE_H_ 13 14 #include <stddef.h> 15 16 #include <array> 17 #include <cstdint> 18 #include <deque> 19 #include <list> 20 #include <memory> 21 #include <unordered_map> 22 23 #include "absl/container/inlined_vector.h" 24 #include "api/units/data_size.h" 25 #include "api/units/time_delta.h" 26 #include "api/units/timestamp.h" 27 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" 28 #include "modules/rtp_rtcp/source/rtp_packet_to_send.h" 29 30 namespace webrtc { 31 32 // Describes how long time a packet may stay in the queue before being dropped. 33 struct PacketQueueTTL { 34 TimeDelta audio_retransmission = TimeDelta::PlusInfinity(); 35 TimeDelta video_retransmission = TimeDelta::PlusInfinity(); 36 TimeDelta video = TimeDelta::PlusInfinity(); 37 }; 38 39 class PrioritizedPacketQueue { 40 public: 41 explicit PrioritizedPacketQueue( 42 Timestamp creation_time, 43 bool prioritize_audio_retransmission = false, 44 PacketQueueTTL packet_queue_ttl = PacketQueueTTL()); 45 PrioritizedPacketQueue(const PrioritizedPacketQueue&) = delete; 46 PrioritizedPacketQueue& operator=(const PrioritizedPacketQueue&) = delete; 47 48 // Add a packet to the queue. The enqueue time is used for queue time stats 49 // and to report the leading packet enqueue time per packet type. 50 void Push(Timestamp enqueue_time, std::unique_ptr<RtpPacketToSend> packet); 51 52 // Remove the next packet from the queue. Packets a prioritized first 53 // according to packet type, in the following order: 54 // - audio, retransmissions, video / fec, padding 55 // For each packet type, we use one FIFO-queue per SSRC and emit from 56 // those queues in a round-robin fashion. 57 std::unique_ptr<RtpPacketToSend> Pop(); 58 59 // Number of packets in the queue. 60 int SizeInPackets() const; 61 62 // Sum of all payload bytes in the queue, where the payload is calculated 63 // as `packet->payload_size() + packet->padding_size()`. 64 DataSize SizeInPayloadBytes() const; 65 66 // Convenience method for `SizeInPackets() == 0`. 67 bool Empty() const; 68 69 // Total packets in the queue per media type (RtpPacketMediaType values are 70 // used as lookup index). 71 const std::array<int, kNumMediaTypes>& SizeInPacketsPerRtpPacketMediaType() 72 const; 73 74 // The enqueue time of the next packet this queue will return via the Pop() 75 // method, for the given packet type. If queue has no packets, of that type, 76 // returns Timestamp::MinusInfinity(). 77 Timestamp LeadingPacketEnqueueTime(RtpPacketMediaType type) const; 78 Timestamp LeadingPacketEnqueueTimeForRetransmission() const; 79 80 // Enqueue time of the oldest packet in the queue, 81 // Timestamp::MinusInfinity() if queue is empty. 82 Timestamp OldestEnqueueTime() const; 83 84 // Average queue time for the packets currently in the queue. 85 // The queuing time is calculated from Push() to the last UpdateQueueTime() 86 // call - with any time spent in a paused state subtracted. 87 // Returns TimeDelta::Zero() for an empty queue. 88 TimeDelta AverageQueueTime() const; 89 90 // Called during packet processing or when pause stats changes. Since the 91 // AverageQueueTime() method does not look at the wall time, this method 92 // needs to be called before querying queue time. 93 void UpdateAverageQueueTime(Timestamp now); 94 95 // Set the pause state, while `paused` is true queuing time is not counted. 96 void SetPauseState(bool paused, Timestamp now); 97 98 // Remove any packets matching the given SSRC. 99 void RemovePacketsForSsrc(uint32_t ssrc); 100 101 // Checks if the queue for the given SSRC has original (retransmissions not 102 // counted) video packets containing keyframe data. 103 bool HasKeyframePackets(uint32_t ssrc) const; 104 105 private: 106 static constexpr int kNumPriorityLevels = 5; 107 108 class QueuedPacket { 109 public: 110 DataSize PacketSize() const; 111 112 std::unique_ptr<RtpPacketToSend> packet; 113 Timestamp enqueue_time; 114 std::list<Timestamp>::iterator enqueue_time_iterator; 115 }; 116 117 // Class containing packets for an RTP stream. 118 // For each priority level, packets are simply stored in a fifo queue. 119 class StreamQueue { 120 public: 121 explicit StreamQueue(Timestamp creation_time); 122 StreamQueue(StreamQueue&&) = default; 123 StreamQueue& operator=(StreamQueue&&) = default; 124 125 StreamQueue(const StreamQueue&) = delete; 126 StreamQueue& operator=(const StreamQueue&) = delete; 127 128 // Enqueue packet at the given priority level. Returns true if the packet 129 // count for that priority level went from zero to non-zero. 130 bool EnqueuePacket(QueuedPacket packet, int priority_level); 131 132 QueuedPacket DequeuePacket(int priority_level); 133 134 bool HasPacketsAtPrio(int priority_level) const; 135 bool IsEmpty() const; 136 Timestamp LeadingPacketEnqueueTime(int priority_level) const; 137 Timestamp LastEnqueueTime() const; 138 bool has_keyframe_packets() const { return num_keyframe_packets_ > 0; } 139 140 std::array<std::deque<QueuedPacket>, kNumPriorityLevels> DequeueAll(); 141 142 private: 143 std::deque<QueuedPacket> packets_[kNumPriorityLevels]; 144 Timestamp last_enqueue_time_; 145 int num_keyframe_packets_; 146 }; 147 148 // Remove the packet from the internal state, e.g. queue time / size etc. 149 void DequeuePacketInternal(QueuedPacket& packet); 150 151 // Check if the queue pointed to by `top_active_prio_level_` is empty and 152 // if so move it to the lowest non-empty index. 153 void MaybeUpdateTopPrioLevel(); 154 155 void PurgeOldPacketsAtPriorityLevel(int prio_level, Timestamp now); 156 157 static absl::InlinedVector<TimeDelta, kNumPriorityLevels> ToTtlPerPrio( 158 PacketQueueTTL); 159 160 const bool prioritize_audio_retransmission_; 161 const absl::InlinedVector<TimeDelta, kNumPriorityLevels> 162 time_to_live_per_prio_; 163 164 // Cumulative sum, over all packets, of time spent in the queue. 165 TimeDelta queue_time_sum_; 166 // Cumulative sum of time the queue has spent in a paused state. 167 TimeDelta pause_time_sum_; 168 // Total number of packets stored in this queue. 169 int size_packets_; 170 // Total number of packets stored in this queue per RtpPacketMediaType. 171 std::array<int, kNumMediaTypes> size_packets_per_media_type_; 172 // Sum of payload sizes for all packts stored in this queue. 173 DataSize size_payload_; 174 // The last time queue/pause time sums were updated. 175 Timestamp last_update_time_; 176 bool paused_; 177 178 // Last time `streams_` was culled for inactive streams. 179 Timestamp last_culling_time_; 180 181 // Map from SSRC to packet queues for the associated RTP stream. 182 std::unordered_map<uint32_t, std::unique_ptr<StreamQueue>> streams_; 183 184 // For each priority level, a queue of StreamQueues which have at least one 185 // packet pending for that prio level. 186 std::deque<StreamQueue*> streams_by_prio_[kNumPriorityLevels]; 187 188 // The first index into `stream_by_prio_` that is non-empty. 189 int top_active_prio_level_; 190 191 // Ordered list of enqueue times. Additions are always increasing and added to 192 // the end. QueuedPacket instances have a iterators into this list for fast 193 // removal. 194 std::list<Timestamp> enqueue_times_; 195 }; 196 197 } // namespace webrtc 198 199 #endif // MODULES_PACING_PRIORITIZED_PACKET_QUEUE_H_