aboutsummaryrefslogtreecommitdiff
path: root/audio/transport_feedback_packet_loss_tracker.h
blob: 4ad49024a8ccb8a1bee7b58420d5acafd91f4ca6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 *  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 <map>
#include <vector>

#include "api/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);

  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.
  rtc::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.
  rtc::Optional<float> 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<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) {
      Reset();
    }
    void Reset() {
      num_received_packets_ = 0;
      num_lost_packets_ = 0;
    }
    rtc::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) {
      Reset();
    }
    void Reset() {
      num_acked_pairs_ = 0;
      num_recoverable_losses_ = 0;
    }
    rtc::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

#endif  // AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_