blob: 7e73210327be9eb6ace3ee31652b1e20134c28f1 [file] [log] [blame]
minyue435ddf92017-01-23 08:07:05 -08001/*
2 * Copyright (c) 2017 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
Fredrik Solenberga8b7c7f2018-01-17 11:18:31 +010011#ifndef AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_
12#define AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_
minyue435ddf92017-01-23 08:07:05 -080013
14#include <map>
Fredrik Solenberga8b7c7f2018-01-17 11:18:31 +010015#include <vector>
minyue435ddf92017-01-23 08:07:05 -080016
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020017#include "api/optional.h"
18#include "modules/include/module_common_types.h"
minyue435ddf92017-01-23 08:07:05 -080019
20namespace webrtc {
21
22namespace rtcp {
23class TransportFeedback;
24}
25
elad.alon92e448d2017-03-21 07:31:35 -070026struct PacketFeedback;
27
minyue435ddf92017-01-23 08:07:05 -080028class TransportFeedbackPacketLossTracker final {
29 public:
elad.alon3f9b12d2017-03-15 07:38:13 -070030 // * We count up to |max_window_size_ms| from the sent
31 // time of the latest acked packet for the calculation of the metrics.
elad.alond83b9672017-02-01 08:36:09 -080032 // * PLR (packet-loss-rate) is reliably computable once the statuses of
elad.alon7af93572017-03-03 10:51:35 -080033 // |plr_min_num_acked_packets| packets are known.
elad.alond83b9672017-02-01 08:36:09 -080034 // * RPLR (recoverable-packet-loss-rate) is reliably computable once the
elad.alon7af93572017-03-03 10:51:35 -080035 // statuses of |rplr_min_num_acked_pairs| pairs are known.
elad.alon3f9b12d2017-03-15 07:38:13 -070036 TransportFeedbackPacketLossTracker(int64_t max_window_size_ms,
elad.alon7af93572017-03-03 10:51:35 -080037 size_t plr_min_num_acked_packets,
38 size_t rplr_min_num_acked_pairs);
39
elad.alon3f9b12d2017-03-15 07:38:13 -070040 void OnPacketAdded(uint16_t seq_num, int64_t send_time_ms);
minyue435ddf92017-01-23 08:07:05 -080041
elad.alond12a8e12017-03-23 11:04:48 -070042 void OnPacketFeedbackVector(
elad.alon92e448d2017-03-21 07:31:35 -070043 const std::vector<PacketFeedback>& packet_feedbacks_vector);
minyue435ddf92017-01-23 08:07:05 -080044
elad.alond83b9672017-02-01 08:36:09 -080045 // Returns the packet loss rate, if the window has enough packet statuses to
46 // reliably compute it. Otherwise, returns empty.
47 rtc::Optional<float> GetPacketLossRate() const;
48
49 // Returns the first-order-FEC recoverable packet loss rate, if the window has
50 // enough status pairs to reliably compute it. Otherwise, returns empty.
51 rtc::Optional<float> GetRecoverablePacketLossRate() const;
minyue435ddf92017-01-23 08:07:05 -080052
53 // Verifies that the internal states are correct. Only used for tests.
54 void Validate() const;
55
56 private:
elad.alon7af93572017-03-03 10:51:35 -080057 // When a packet is sent, we memorize its association with the stream by
58 // marking it as (sent-but-so-far-) unacked. If we ever receive a feedback
59 // that reports it as received/lost, we update the state and
60 // metrics accordingly.
61
62 enum class PacketStatus { Unacked = 0, Received = 1, Lost = 2 };
elad.alon3f9b12d2017-03-15 07:38:13 -070063 struct SentPacket {
64 SentPacket(int64_t send_time_ms, PacketStatus status)
65 : send_time_ms(send_time_ms), status(status) {}
66 int64_t send_time_ms;
67 PacketStatus status;
68 };
69 typedef std::map<uint16_t, SentPacket> SentPacketStatusMap;
70 typedef SentPacketStatusMap::const_iterator ConstPacketStatusIterator;
minyue435ddf92017-01-23 08:07:05 -080071
72 void Reset();
elad.alond83b9672017-02-01 08:36:09 -080073
minyue435ddf92017-01-23 08:07:05 -080074 // ReferenceSequenceNumber() provides a sequence number that defines the
75 // order of packet reception info stored in |packet_status_window_|. In
76 // particular, given any sequence number |x|,
77 // (2^16 + x - ref_seq_num_) % 2^16 defines its actual position in
78 // |packet_status_window_|.
79 uint16_t ReferenceSequenceNumber() const;
elad.alon7af93572017-03-03 10:51:35 -080080 uint16_t NewestSequenceNumber() const;
elad.alon3f9b12d2017-03-15 07:38:13 -070081 void UpdatePacketStatus(SentPacketStatusMap::iterator it,
82 PacketStatus new_status);
minyue435ddf92017-01-23 08:07:05 -080083 void RemoveOldestPacketStatus();
elad.alond83b9672017-02-01 08:36:09 -080084
elad.alon7af93572017-03-03 10:51:35 -080085 void UpdateMetrics(ConstPacketStatusIterator it,
86 bool apply /* false = undo */);
87 void UpdatePlr(ConstPacketStatusIterator it, bool apply /* false = undo */);
88 void UpdateRplr(ConstPacketStatusIterator it, bool apply /* false = undo */);
elad.alond83b9672017-02-01 08:36:09 -080089
elad.alon7af93572017-03-03 10:51:35 -080090 ConstPacketStatusIterator PreviousPacketStatus(
91 ConstPacketStatusIterator it) const;
92 ConstPacketStatusIterator NextPacketStatus(
93 ConstPacketStatusIterator it) const;
minyue435ddf92017-01-23 08:07:05 -080094
elad.alon3f9b12d2017-03-15 07:38:13 -070095 const int64_t max_window_size_ms_;
elad.alon7af93572017-03-03 10:51:35 -080096 size_t acked_packets_;
minyue435ddf92017-01-23 08:07:05 -080097
elad.alon3f9b12d2017-03-15 07:38:13 -070098 SentPacketStatusMap packet_status_window_;
minyue435ddf92017-01-23 08:07:05 -080099 // |ref_packet_status_| points to the oldest item in |packet_status_window_|.
elad.alon7af93572017-03-03 10:51:35 -0800100 ConstPacketStatusIterator ref_packet_status_;
minyue435ddf92017-01-23 08:07:05 -0800101
elad.alond83b9672017-02-01 08:36:09 -0800102 // Packet-loss-rate calculation (lost / all-known-packets).
103 struct PlrState {
elad.alon7af93572017-03-03 10:51:35 -0800104 explicit PlrState(size_t min_num_acked_packets)
105 : min_num_acked_packets_(min_num_acked_packets) {
elad.alond83b9672017-02-01 08:36:09 -0800106 Reset();
107 }
108 void Reset() {
109 num_received_packets_ = 0;
110 num_lost_packets_ = 0;
111 }
112 rtc::Optional<float> GetMetric() const;
elad.alon7af93572017-03-03 10:51:35 -0800113 const size_t min_num_acked_packets_;
elad.alond83b9672017-02-01 08:36:09 -0800114 size_t num_received_packets_;
115 size_t num_lost_packets_;
116 } plr_state_;
117
118 // Recoverable packet loss calculation (first-order-FEC recoverable).
119 struct RplrState {
elad.alon7af93572017-03-03 10:51:35 -0800120 explicit RplrState(size_t min_num_acked_pairs)
121 : min_num_acked_pairs_(min_num_acked_pairs) {
elad.alond83b9672017-02-01 08:36:09 -0800122 Reset();
123 }
124 void Reset() {
elad.alon7af93572017-03-03 10:51:35 -0800125 num_acked_pairs_ = 0;
elad.alond83b9672017-02-01 08:36:09 -0800126 num_recoverable_losses_ = 0;
127 }
128 rtc::Optional<float> GetMetric() const;
129 // Recoverable packets are those which were lost, but immediately followed
130 // by a properly received packet. If that second packet carried FEC,
131 // the data from the former (lost) packet could be recovered.
132 // The RPLR is calculated as the fraction of such pairs (lost-received) out
133 // of all pairs of consecutive acked packets.
elad.alon7af93572017-03-03 10:51:35 -0800134 const size_t min_num_acked_pairs_;
135 size_t num_acked_pairs_;
elad.alond83b9672017-02-01 08:36:09 -0800136 size_t num_recoverable_losses_;
137 } rplr_state_;
minyue435ddf92017-01-23 08:07:05 -0800138};
139
140} // namespace webrtc
141
Fredrik Solenberga8b7c7f2018-01-17 11:18:31 +0100142#endif // AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_