blob: 180b64a16a82b7d058463c66bed0eff3c6796885 [file] [log] [blame]
* Copyright (c) 2017 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.
#include <map>
#include <vector>
#include "absl/types/optional.h"
namespace webrtc {
namespace rtcp {
class TransportFeedback;
struct PacketFeedback;
class TransportFeedbackPacketLossTracker final {
// * We count up to |max_window_size_ms| from the sent
// time of the latest acked packet for the calculation of the metrics.
// * PLR (packet-loss-rate) is reliably computable once the statuses of
// |plr_min_num_acked_packets| packets are known.
// * RPLR (recoverable-packet-loss-rate) is reliably computable once the
// statuses of |rplr_min_num_acked_pairs| pairs are known.
TransportFeedbackPacketLossTracker(int64_t max_window_size_ms,
size_t plr_min_num_acked_packets,
size_t rplr_min_num_acked_pairs);
void OnPacketAdded(uint16_t seq_num, int64_t send_time_ms);
void OnPacketFeedbackVector(
const std::vector<PacketFeedback>& packet_feedbacks_vector);
// Returns the packet loss rate, if the window has enough packet statuses to
// reliably compute it. Otherwise, returns empty.
absl::optional<float> GetPacketLossRate() const;
// Returns the first-order-FEC recoverable packet loss rate, if the window has
// enough status pairs to reliably compute it. Otherwise, returns empty.
absl::optional<float> GetRecoverablePacketLossRate() const;
// Verifies that the internal states are correct. Only used for tests.
void Validate() const;
// When a packet is sent, we memorize its association with the stream by
// marking it as (sent-but-so-far-) unacked. If we ever receive a feedback
// that reports it as received/lost, we update the state and
// metrics accordingly.
enum class PacketStatus { Unacked = 0, Received = 1, Lost = 2 };
struct SentPacket {
SentPacket(int64_t send_time_ms, PacketStatus status)
: send_time_ms(send_time_ms), status(status) {}
int64_t send_time_ms;
PacketStatus status;
typedef std::map<uint16_t, SentPacket> SentPacketStatusMap;
typedef SentPacketStatusMap::const_iterator ConstPacketStatusIterator;
void Reset();
// ReferenceSequenceNumber() provides a sequence number that defines the
// order of packet reception info stored in |packet_status_window_|. In
// particular, given any sequence number |x|,
// (2^16 + x - ref_seq_num_) % 2^16 defines its actual position in
// |packet_status_window_|.
uint16_t ReferenceSequenceNumber() const;
uint16_t NewestSequenceNumber() const;
void UpdatePacketStatus(SentPacketStatusMap::iterator it,
PacketStatus new_status);
void RemoveOldestPacketStatus();
void UpdateMetrics(ConstPacketStatusIterator it,
bool apply /* false = undo */);
void UpdatePlr(ConstPacketStatusIterator it, bool apply /* false = undo */);
void UpdateRplr(ConstPacketStatusIterator it, bool apply /* false = undo */);
ConstPacketStatusIterator PreviousPacketStatus(
ConstPacketStatusIterator it) const;
ConstPacketStatusIterator NextPacketStatus(
ConstPacketStatusIterator it) const;
const int64_t max_window_size_ms_;
size_t acked_packets_;
SentPacketStatusMap packet_status_window_;
// |ref_packet_status_| points to the oldest item in |packet_status_window_|.
ConstPacketStatusIterator ref_packet_status_;
// Packet-loss-rate calculation (lost / all-known-packets).
struct PlrState {
explicit PlrState(size_t min_num_acked_packets)
: min_num_acked_packets_(min_num_acked_packets) {
void Reset() {
num_received_packets_ = 0;
num_lost_packets_ = 0;
absl::optional<float> GetMetric() const;
const size_t min_num_acked_packets_;
size_t num_received_packets_;
size_t num_lost_packets_;
} plr_state_;
// Recoverable packet loss calculation (first-order-FEC recoverable).
struct RplrState {
explicit RplrState(size_t min_num_acked_pairs)
: min_num_acked_pairs_(min_num_acked_pairs) {
void Reset() {
num_acked_pairs_ = 0;
num_recoverable_losses_ = 0;
absl::optional<float> GetMetric() const;
// Recoverable packets are those which were lost, but immediately followed
// by a properly received packet. If that second packet carried FEC,
// the data from the former (lost) packet could be recovered.
// The RPLR is calculated as the fraction of such pairs (lost-received) out
// of all pairs of consecutive acked packets.
const size_t min_num_acked_pairs_;
size_t num_acked_pairs_;
size_t num_recoverable_losses_;
} rplr_state_;
} // namespace webrtc