minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 1 | /* |
| 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 Solenberg | a8b7c7f | 2018-01-17 11:18:31 +0100 | [diff] [blame] | 11 | #ifndef AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_ |
| 12 | #define AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_ |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 13 | |
| 14 | #include <map> |
Fredrik Solenberg | a8b7c7f | 2018-01-17 11:18:31 +0100 | [diff] [blame] | 15 | #include <vector> |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 16 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 17 | #include "api/optional.h" |
| 18 | #include "modules/include/module_common_types.h" |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 19 | |
| 20 | namespace webrtc { |
| 21 | |
| 22 | namespace rtcp { |
| 23 | class TransportFeedback; |
| 24 | } |
| 25 | |
elad.alon | 92e448d | 2017-03-21 07:31:35 -0700 | [diff] [blame] | 26 | struct PacketFeedback; |
| 27 | |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 28 | class TransportFeedbackPacketLossTracker final { |
| 29 | public: |
elad.alon | 3f9b12d | 2017-03-15 07:38:13 -0700 | [diff] [blame] | 30 | // * 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.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 32 | // * PLR (packet-loss-rate) is reliably computable once the statuses of |
elad.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 33 | // |plr_min_num_acked_packets| packets are known. |
elad.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 34 | // * RPLR (recoverable-packet-loss-rate) is reliably computable once the |
elad.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 35 | // statuses of |rplr_min_num_acked_pairs| pairs are known. |
elad.alon | 3f9b12d | 2017-03-15 07:38:13 -0700 | [diff] [blame] | 36 | TransportFeedbackPacketLossTracker(int64_t max_window_size_ms, |
elad.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 37 | size_t plr_min_num_acked_packets, |
| 38 | size_t rplr_min_num_acked_pairs); |
| 39 | |
elad.alon | 3f9b12d | 2017-03-15 07:38:13 -0700 | [diff] [blame] | 40 | void OnPacketAdded(uint16_t seq_num, int64_t send_time_ms); |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 41 | |
elad.alon | d12a8e1 | 2017-03-23 11:04:48 -0700 | [diff] [blame] | 42 | void OnPacketFeedbackVector( |
elad.alon | 92e448d | 2017-03-21 07:31:35 -0700 | [diff] [blame] | 43 | const std::vector<PacketFeedback>& packet_feedbacks_vector); |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 44 | |
elad.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 45 | // 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; |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 52 | |
| 53 | // Verifies that the internal states are correct. Only used for tests. |
| 54 | void Validate() const; |
| 55 | |
| 56 | private: |
elad.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 57 | // 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.alon | 3f9b12d | 2017-03-15 07:38:13 -0700 | [diff] [blame] | 63 | 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; |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 71 | |
| 72 | void Reset(); |
elad.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 73 | |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 74 | // 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.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 80 | uint16_t NewestSequenceNumber() const; |
elad.alon | 3f9b12d | 2017-03-15 07:38:13 -0700 | [diff] [blame] | 81 | void UpdatePacketStatus(SentPacketStatusMap::iterator it, |
| 82 | PacketStatus new_status); |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 83 | void RemoveOldestPacketStatus(); |
elad.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 84 | |
elad.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 85 | 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.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 89 | |
elad.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 90 | ConstPacketStatusIterator PreviousPacketStatus( |
| 91 | ConstPacketStatusIterator it) const; |
| 92 | ConstPacketStatusIterator NextPacketStatus( |
| 93 | ConstPacketStatusIterator it) const; |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 94 | |
elad.alon | 3f9b12d | 2017-03-15 07:38:13 -0700 | [diff] [blame] | 95 | const int64_t max_window_size_ms_; |
elad.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 96 | size_t acked_packets_; |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 97 | |
elad.alon | 3f9b12d | 2017-03-15 07:38:13 -0700 | [diff] [blame] | 98 | SentPacketStatusMap packet_status_window_; |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 99 | // |ref_packet_status_| points to the oldest item in |packet_status_window_|. |
elad.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 100 | ConstPacketStatusIterator ref_packet_status_; |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 101 | |
elad.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 102 | // Packet-loss-rate calculation (lost / all-known-packets). |
| 103 | struct PlrState { |
elad.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 104 | explicit PlrState(size_t min_num_acked_packets) |
| 105 | : min_num_acked_packets_(min_num_acked_packets) { |
elad.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 106 | Reset(); |
| 107 | } |
| 108 | void Reset() { |
| 109 | num_received_packets_ = 0; |
| 110 | num_lost_packets_ = 0; |
| 111 | } |
| 112 | rtc::Optional<float> GetMetric() const; |
elad.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 113 | const size_t min_num_acked_packets_; |
elad.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 114 | 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.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 120 | explicit RplrState(size_t min_num_acked_pairs) |
| 121 | : min_num_acked_pairs_(min_num_acked_pairs) { |
elad.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 122 | Reset(); |
| 123 | } |
| 124 | void Reset() { |
elad.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 125 | num_acked_pairs_ = 0; |
elad.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 126 | 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.alon | 7af9357 | 2017-03-03 10:51:35 -0800 | [diff] [blame] | 134 | const size_t min_num_acked_pairs_; |
| 135 | size_t num_acked_pairs_; |
elad.alon | d83b967 | 2017-02-01 08:36:09 -0800 | [diff] [blame] | 136 | size_t num_recoverable_losses_; |
| 137 | } rplr_state_; |
minyue | 435ddf9 | 2017-01-23 08:07:05 -0800 | [diff] [blame] | 138 | }; |
| 139 | |
| 140 | } // namespace webrtc |
| 141 | |
Fredrik Solenberg | a8b7c7f | 2018-01-17 11:18:31 +0100 | [diff] [blame] | 142 | #endif // AUDIO_TRANSPORT_FEEDBACK_PACKET_LOSS_TRACKER_H_ |