mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 05:40:42 +01:00

PacketArrivalMap explicitly doesn't promise packet at the beginning of it is received. Ensuring that property is wasteful Bug: chromium:1382563 Change-Id: Ifc898b7ec2bc7a302af8dcfd233e0c598f62db95 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/290501 Reviewed-by: Per Kjellander <perkj@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#39083}
144 lines
5.8 KiB
C++
144 lines
5.8 KiB
C++
/*
|
|
* Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
#ifndef MODULES_REMOTE_BITRATE_ESTIMATOR_PACKET_ARRIVAL_MAP_H_
|
|
#define MODULES_REMOTE_BITRATE_ESTIMATOR_PACKET_ARRIVAL_MAP_H_
|
|
|
|
#include <algorithm>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <memory>
|
|
|
|
#include "api/units/timestamp.h"
|
|
#include "rtc_base/checks.h"
|
|
|
|
namespace webrtc {
|
|
|
|
// PacketArrivalTimeMap is an optimized map of packet sequence number to arrival
|
|
// time, limited in size to never exceed `kMaxNumberOfPackets`. It will grow as
|
|
// needed, and remove old packets, and will expand to allow earlier packets to
|
|
// be added (out-of-order).
|
|
//
|
|
// Not yet received packets have the arrival time zero. The queue will not span
|
|
// larger than necessary and the last packet should always be received. The
|
|
// first packet in the queue doesn't have to be received in case of receiving
|
|
// packets out-of-order.
|
|
class PacketArrivalTimeMap {
|
|
public:
|
|
struct PacketArrivalTime {
|
|
Timestamp arrival_time;
|
|
int64_t sequence_number;
|
|
};
|
|
// Impossible to request feedback older than what can be represented by 15
|
|
// bits.
|
|
static constexpr int kMaxNumberOfPackets = (1 << 15);
|
|
|
|
PacketArrivalTimeMap() = default;
|
|
PacketArrivalTimeMap(const PacketArrivalTimeMap&) = delete;
|
|
PacketArrivalTimeMap& operator=(const PacketArrivalTimeMap&) = delete;
|
|
~PacketArrivalTimeMap() = default;
|
|
|
|
// Indicates if the packet with `sequence_number` has already been received.
|
|
bool has_received(int64_t sequence_number) const {
|
|
return sequence_number >= begin_sequence_number() &&
|
|
sequence_number < end_sequence_number() &&
|
|
arrival_times_[Index(sequence_number)] >= Timestamp::Zero();
|
|
}
|
|
|
|
// Returns the sequence number of the first entry in the map, i.e. the
|
|
// sequence number that a `begin()` iterator would represent.
|
|
int64_t begin_sequence_number() const { return begin_sequence_number_; }
|
|
|
|
// Returns the sequence number of the element just after the map, i.e. the
|
|
// sequence number that an `end()` iterator would represent.
|
|
int64_t end_sequence_number() const { return end_sequence_number_; }
|
|
|
|
// Returns an element by `sequence_number`, which must be valid, i.e.
|
|
// between [begin_sequence_number, end_sequence_number).
|
|
Timestamp get(int64_t sequence_number) {
|
|
RTC_DCHECK_GE(sequence_number, begin_sequence_number());
|
|
RTC_DCHECK_LT(sequence_number, end_sequence_number());
|
|
return arrival_times_[Index(sequence_number)];
|
|
}
|
|
|
|
// Returns timestamp and sequence number of the received packet with sequence
|
|
// number equal or larger than `sequence_number`. `sequence_number` must be in
|
|
// range [begin_sequence_number, end_sequence_number).
|
|
PacketArrivalTime FindNextAtOrAfter(int64_t sequence_number) const {
|
|
RTC_DCHECK_GE(sequence_number, begin_sequence_number());
|
|
RTC_DCHECK_LT(sequence_number, end_sequence_number());
|
|
while (true) {
|
|
Timestamp t = arrival_times_[Index(sequence_number)];
|
|
if (t >= Timestamp::Zero()) {
|
|
return {.arrival_time = t, .sequence_number = sequence_number};
|
|
}
|
|
++sequence_number;
|
|
}
|
|
}
|
|
|
|
// Clamps `sequence_number` between [begin_sequence_number,
|
|
// end_sequence_number].
|
|
int64_t clamp(int64_t sequence_number) const {
|
|
return std::clamp(sequence_number, begin_sequence_number(),
|
|
end_sequence_number());
|
|
}
|
|
|
|
// Erases all elements from the beginning of the map until `sequence_number`.
|
|
void EraseTo(int64_t sequence_number);
|
|
|
|
// Records the fact that a packet with `sequence_number` arrived at
|
|
// `arrival_time_ms`.
|
|
void AddPacket(int64_t sequence_number, Timestamp arrival_time);
|
|
|
|
// Removes packets from the beginning of the map as long as they are received
|
|
// before `sequence_number` and with an age older than `arrival_time_limit`
|
|
void RemoveOldPackets(int64_t sequence_number, Timestamp arrival_time_limit);
|
|
|
|
private:
|
|
static constexpr int kMinCapacity = 128;
|
|
|
|
// Returns index in the `arrival_times_` for value for `sequence_number`.
|
|
int Index(int64_t sequence_number) const {
|
|
// Note that sequence_number might be negative, thus taking '%' requires
|
|
// extra handling and can be slow. Because capacity is a power of two, it
|
|
// is much faster to use '&' operator.
|
|
return sequence_number & capacity_minus_1_;
|
|
}
|
|
|
|
void SetNotReceived(int64_t begin_sequence_number_inclusive,
|
|
int64_t end_sequence_number_exclusive);
|
|
|
|
// Adjust capacity to match new_size, may reduce capacity.
|
|
// On return guarantees capacity >= new_size.
|
|
void AdjustToSize(int new_size);
|
|
void Reallocate(int new_capacity);
|
|
|
|
int capacity() const { return capacity_minus_1_ + 1; }
|
|
bool has_seen_packet() const { return arrival_times_ != nullptr; }
|
|
|
|
// Circular buffer. Packet with sequence number `sequence_number`
|
|
// is stored in the slot `sequence_number % capacity_`
|
|
std::unique_ptr<Timestamp[]> arrival_times_ = nullptr;
|
|
|
|
// Allocated size of the `arrival_times_`
|
|
// capacity_ is a power of 2 in range [kMinCapacity, kMaxNumberOfPackets]
|
|
// `capacity - 1` is used much more often than `capacity`, thus that value is
|
|
// stored.
|
|
int capacity_minus_1_ = -1;
|
|
|
|
// The unwrapped sequence number for valid range of sequence numbers.
|
|
// arrival_times_ entries only valid for sequence numbers in range
|
|
// `begin_sequence_number_ <= sequence_number < end_sequence_number_`
|
|
int64_t begin_sequence_number_ = 0;
|
|
int64_t end_sequence_number_ = 0;
|
|
};
|
|
|
|
} // namespace webrtc
|
|
|
|
#endif // MODULES_REMOTE_BITRATE_ESTIMATOR_PACKET_ARRIVAL_MAP_H_
|