xref: /aosp_15_r20/external/webrtc/modules/remote_bitrate_estimator/packet_arrival_map.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2021 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 #ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_PACKET_ARRIVAL_MAP_H_
11 #define MODULES_REMOTE_BITRATE_ESTIMATOR_PACKET_ARRIVAL_MAP_H_
12 
13 #include <algorithm>
14 #include <cstddef>
15 #include <cstdint>
16 #include <memory>
17 
18 #include "api/units/timestamp.h"
19 #include "rtc_base/checks.h"
20 
21 namespace webrtc {
22 
23 // PacketArrivalTimeMap is an optimized map of packet sequence number to arrival
24 // time, limited in size to never exceed `kMaxNumberOfPackets`. It will grow as
25 // needed, and remove old packets, and will expand to allow earlier packets to
26 // be added (out-of-order).
27 //
28 // Not yet received packets have the arrival time zero. The queue will not span
29 // larger than necessary and the last packet should always be received. The
30 // first packet in the queue doesn't have to be received in case of receiving
31 // packets out-of-order.
32 class PacketArrivalTimeMap {
33  public:
34   struct PacketArrivalTime {
35     Timestamp arrival_time;
36     int64_t sequence_number;
37   };
38   // Impossible to request feedback older than what can be represented by 15
39   // bits.
40   static constexpr int kMaxNumberOfPackets = (1 << 15);
41 
42   PacketArrivalTimeMap() = default;
43   PacketArrivalTimeMap(const PacketArrivalTimeMap&) = delete;
44   PacketArrivalTimeMap& operator=(const PacketArrivalTimeMap&) = delete;
45   ~PacketArrivalTimeMap() = default;
46 
47   // Indicates if the packet with `sequence_number` has already been received.
has_received(int64_t sequence_number)48   bool has_received(int64_t sequence_number) const {
49     return sequence_number >= begin_sequence_number() &&
50            sequence_number < end_sequence_number() &&
51            arrival_times_[Index(sequence_number)] >= Timestamp::Zero();
52   }
53 
54   // Returns the sequence number of the first entry in the map, i.e. the
55   // sequence number that a `begin()` iterator would represent.
begin_sequence_number()56   int64_t begin_sequence_number() const { return begin_sequence_number_; }
57 
58   // Returns the sequence number of the element just after the map, i.e. the
59   // sequence number that an `end()` iterator would represent.
end_sequence_number()60   int64_t end_sequence_number() const { return end_sequence_number_; }
61 
62   // Returns an element by `sequence_number`, which must be valid, i.e.
63   // between [begin_sequence_number, end_sequence_number).
get(int64_t sequence_number)64   Timestamp get(int64_t sequence_number) {
65     RTC_DCHECK_GE(sequence_number, begin_sequence_number());
66     RTC_DCHECK_LT(sequence_number, end_sequence_number());
67     return arrival_times_[Index(sequence_number)];
68   }
69 
70   // Returns timestamp and sequence number of the received packet with sequence
71   // number equal or larger than `sequence_number`. `sequence_number` must be in
72   // range [begin_sequence_number, end_sequence_number).
FindNextAtOrAfter(int64_t sequence_number)73   PacketArrivalTime FindNextAtOrAfter(int64_t sequence_number) const {
74     RTC_DCHECK_GE(sequence_number, begin_sequence_number());
75     RTC_DCHECK_LT(sequence_number, end_sequence_number());
76     while (true) {
77       Timestamp t = arrival_times_[Index(sequence_number)];
78       if (t >= Timestamp::Zero()) {
79         return {.arrival_time = t, .sequence_number = sequence_number};
80       }
81       ++sequence_number;
82     }
83   }
84 
85   // Clamps `sequence_number` between [begin_sequence_number,
86   // end_sequence_number].
clamp(int64_t sequence_number)87   int64_t clamp(int64_t sequence_number) const {
88     return std::clamp(sequence_number, begin_sequence_number(),
89                       end_sequence_number());
90   }
91 
92   // Erases all elements from the beginning of the map until `sequence_number`.
93   void EraseTo(int64_t sequence_number);
94 
95   // Records the fact that a packet with `sequence_number` arrived at
96   // `arrival_time_ms`.
97   void AddPacket(int64_t sequence_number, Timestamp arrival_time);
98 
99   // Removes packets from the beginning of the map as long as they are received
100   // before `sequence_number` and with an age older than `arrival_time_limit`
101   void RemoveOldPackets(int64_t sequence_number, Timestamp arrival_time_limit);
102 
103  private:
104   static constexpr int kMinCapacity = 128;
105 
106   // Returns index in the `arrival_times_` for value for `sequence_number`.
Index(int64_t sequence_number)107   int Index(int64_t sequence_number) const {
108     // Note that sequence_number might be negative, thus taking '%' requires
109     // extra handling and can be slow. Because capacity is a power of two, it
110     // is much faster to use '&' operator.
111     return sequence_number & capacity_minus_1_;
112   }
113 
114   void SetNotReceived(int64_t begin_sequence_number_inclusive,
115                       int64_t end_sequence_number_exclusive);
116 
117   void TrimLeadingNotReceivedEntries();
118 
119   // Adjust capacity to match new_size, may reduce capacity.
120   // On return guarantees capacity >= new_size.
121   void AdjustToSize(int new_size);
122   void Reallocate(int new_capacity);
123 
capacity()124   int capacity() const { return capacity_minus_1_ + 1; }
has_seen_packet()125   bool has_seen_packet() const { return arrival_times_ != nullptr; }
126 
127   // Circular buffer. Packet with sequence number `sequence_number`
128   // is stored in the slot `sequence_number % capacity_`
129   std::unique_ptr<Timestamp[]> arrival_times_ = nullptr;
130 
131   // Allocated size of the `arrival_times_`
132   // capacity_ is a power of 2 in range [kMinCapacity, kMaxNumberOfPackets]
133   // `capacity - 1` is used much more often than `capacity`, thus that value is
134   // stored.
135   int capacity_minus_1_ = -1;
136 
137   // The unwrapped sequence number for valid range of sequence numbers.
138   // arrival_times_ entries only valid for sequence numbers in range
139   // `begin_sequence_number_ <= sequence_number < end_sequence_number_`
140   int64_t begin_sequence_number_ = 0;
141   int64_t end_sequence_number_ = 0;
142 };
143 
144 }  // namespace webrtc
145 
146 #endif  // MODULES_REMOTE_BITRATE_ESTIMATOR_PACKET_ARRIVAL_MAP_H_
147