tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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_