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