/* * 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. */ #ifndef AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_ #define AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_ #include #include #include "absl/types/optional.h" namespace webrtc { namespace rtcp { class TransportFeedback; } struct PacketFeedback; class TransportFeedbackPacketLossTracker final { public: // * 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); ~TransportFeedbackPacketLossTracker(); void OnPacketAdded(uint16_t seq_num, int64_t send_time_ms); void OnPacketFeedbackVector( const std::vector& packet_feedbacks_vector); // Returns the packet loss rate, if the window has enough packet statuses to // reliably compute it. Otherwise, returns empty. absl::optional 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 GetRecoverablePacketLossRate() const; // Verifies that the internal states are correct. Only used for tests. void Validate() const; private: // 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 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) { Reset(); } void Reset() { num_received_packets_ = 0; num_lost_packets_ = 0; } absl::optional 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) { Reset(); } void Reset() { num_acked_pairs_ = 0; num_recoverable_losses_ = 0; } absl::optional 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 #endif // AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_