Index: webrtc/voice_engine/transport_feedback_packet_loss_tracker.cc |
diff --git a/webrtc/voice_engine/transport_feedback_packet_loss_tracker.cc b/webrtc/voice_engine/transport_feedback_packet_loss_tracker.cc |
index becf9646098a2f76b7739683bf945e586a54e1e5..c05b044814d9f5a2916d985d40a1a7f8da7fe9ff 100644 |
--- a/webrtc/voice_engine/transport_feedback_packet_loss_tracker.cc |
+++ b/webrtc/voice_engine/transport_feedback_packet_loss_tracker.cc |
@@ -21,26 +21,40 @@ namespace { |
constexpr uint16_t kSeqNumHalf = 0x8000u; |
constexpr uint16_t kSeqNumQuarter = kSeqNumHalf / 2; |
constexpr size_t kMaxConsecutiveOldReports = 4; |
+ |
+void UpdateCounter(size_t* counter, bool increment) { |
+ if (increment) { |
+ RTC_DCHECK_LT(*counter, std::numeric_limits<std::size_t>::max()); |
+ ++(*counter); |
+ } else { |
+ RTC_DCHECK_GT(*counter, 0); |
+ --(*counter); |
+ } |
+} |
+ |
} // namespace |
namespace webrtc { |
TransportFeedbackPacketLossTracker::TransportFeedbackPacketLossTracker( |
- size_t min_window_size, |
- size_t max_window_size) |
- : min_window_size_(min_window_size), |
- max_window_size_(max_window_size), |
- ref_packet_status_(packet_status_window_.begin()) { |
- RTC_DCHECK_GT(min_window_size, 0); |
- RTC_DCHECK_GE(max_window_size_, min_window_size_); |
- RTC_DCHECK_LE(max_window_size_, kSeqNumHalf); |
+ size_t max_window_size, |
+ size_t plr_min_num_packets, |
+ size_t rplr_min_num_pairs) |
+ : max_window_size_(max_window_size), |
+ ref_packet_status_(packet_status_window_.begin()), |
+ plr_state_(plr_min_num_packets), |
+ rplr_state_(rplr_min_num_pairs) { |
+ RTC_DCHECK_GT(plr_min_num_packets, 0); |
+ RTC_DCHECK_GE(max_window_size, plr_min_num_packets); |
+ RTC_DCHECK_LE(max_window_size, kSeqNumHalf); |
+ RTC_DCHECK_GT(rplr_min_num_pairs, 0); |
+ RTC_DCHECK_GT(max_window_size, rplr_min_num_pairs); |
Reset(); |
} |
void TransportFeedbackPacketLossTracker::Reset() { |
- num_received_packets_ = 0; |
- num_lost_packets_ = 0; |
- num_consecutive_losses_ = 0; |
+ plr_state_.Reset(); |
+ rplr_state_.Reset(); |
num_consecutive_old_reports_ = 0; |
packet_status_window_.clear(); |
ref_packet_status_ = packet_status_window_.begin(); |
@@ -104,16 +118,14 @@ void TransportFeedbackPacketLossTracker::OnReceivedTransportFeedback( |
} |
} |
-bool TransportFeedbackPacketLossTracker::GetPacketLossRates( |
- float* packet_loss_rate, |
- float* consecutive_packet_loss_rate) const { |
- const size_t total = num_lost_packets_ + num_received_packets_; |
- if (total < min_window_size_) |
- return false; |
- *packet_loss_rate = static_cast<float>(num_lost_packets_) / total; |
- *consecutive_packet_loss_rate = |
- static_cast<float>(num_consecutive_losses_) / total; |
- return true; |
+rtc::Optional<float> |
+TransportFeedbackPacketLossTracker::GetPacketLossRate() const { |
+ return plr_state_.GetMetric(); |
+} |
+ |
+rtc::Optional<float> |
+TransportFeedbackPacketLossTracker::GetRecoverablePacketLossRate() const { |
+ return rplr_state_.GetMetric(); |
} |
void TransportFeedbackPacketLossTracker::InsertPacketStatus(uint16_t seq_num, |
@@ -124,7 +136,7 @@ void TransportFeedbackPacketLossTracker::InsertPacketStatus(uint16_t seq_num, |
if (!ret.first->second && received) { |
// If older status said that the packet was lost but newer one says it |
// is received, we take the newer one. |
- UndoPacketStatus(ret.first); |
+ UpdateMetrics(ret.first, false); |
ret.first->second = received; |
} else { |
// If the value is unchanged or if older status said that the packet was |
@@ -132,66 +144,63 @@ void TransportFeedbackPacketLossTracker::InsertPacketStatus(uint16_t seq_num, |
return; |
} |
} |
- ApplyPacketStatus(ret.first); |
+ UpdateMetrics(ret.first, true); |
if (packet_status_window_.size() == 1) |
ref_packet_status_ = ret.first; |
} |
void TransportFeedbackPacketLossTracker::RemoveOldestPacketStatus() { |
- UndoPacketStatus(ref_packet_status_); |
+ UpdateMetrics(ref_packet_status_, false); |
const auto it = ref_packet_status_; |
ref_packet_status_ = NextPacketStatus(it); |
packet_status_window_.erase(it); |
} |
-void TransportFeedbackPacketLossTracker::ApplyPacketStatus( |
- PacketStatusIterator it) { |
+void TransportFeedbackPacketLossTracker::UpdateMetrics( |
+ PacketStatusIterator it, |
+ bool apply /* false = undo */) { |
RTC_DCHECK(it != packet_status_window_.end()); |
+ UpdatePlr(it, apply); |
+ UpdateRplr(it, apply); |
+} |
+ |
+void TransportFeedbackPacketLossTracker::UpdatePlr( |
+ PacketStatusIterator it, |
+ bool apply /* false = undo */) { |
+ // Record or undo reception status of currently handled packet. |
if (it->second) { |
- ++num_received_packets_; |
+ UpdateCounter(&plr_state_.num_received_packets_, apply); |
} else { |
- ++num_lost_packets_; |
- const auto& next = NextPacketStatus(it); |
- if (next != packet_status_window_.end() && |
- next->first == static_cast<uint16_t>(it->first + 1) && !next->second) { |
- // Feedback shows that the next packet has been lost. Since this |
- // packet is lost, we increase the consecutive loss counter. |
- ++num_consecutive_losses_; |
- } |
- if (it != ref_packet_status_) { |
- const auto& pre = PreviousPacketStatus(it); |
- if (pre->first == static_cast<uint16_t>(it->first - 1) && !pre->second) { |
- // Feedback shows that the previous packet has been lost. Since this |
- // packet is lost, we increase the consecutive loss counter. |
- ++num_consecutive_losses_; |
- } |
- } |
+ UpdateCounter(&plr_state_.num_lost_packets_, apply); |
} |
} |
-void TransportFeedbackPacketLossTracker::UndoPacketStatus( |
- PacketStatusIterator it) { |
- RTC_DCHECK(it != packet_status_window_.end()); |
- if (it->second) { |
- RTC_DCHECK_GT(num_received_packets_, 0); |
- --num_received_packets_; |
- } else { |
- RTC_DCHECK_GT(num_lost_packets_, 0); |
- --num_lost_packets_; |
- const auto& next = NextPacketStatus(it); |
- if (next != packet_status_window_.end() && |
- next->first == static_cast<uint16_t>(it->first + 1) && !next->second) { |
- RTC_DCHECK_GT(num_consecutive_losses_, 0); |
- --num_consecutive_losses_; |
- } |
- if (it != ref_packet_status_) { |
- const auto& pre = PreviousPacketStatus(it); |
- if (pre->first == static_cast<uint16_t>(it->first - 1) && !pre->second) { |
- RTC_DCHECK_GT(num_consecutive_losses_, 0); |
- --num_consecutive_losses_; |
+void TransportFeedbackPacketLossTracker::UpdateRplr( |
+ PacketStatusIterator it, |
+ bool apply /* false = undo */) { |
+ // Previous packet and current packet might compose a known pair. |
+ // If so, the RPLR state needs to be updated accordingly. |
+ if (it != ref_packet_status_) { |
+ const auto& prev = PreviousPacketStatus(it); |
+ if (prev->first == static_cast<uint16_t>(it->first - 1)) { |
+ UpdateCounter(&rplr_state_.num_known_pairs_, apply); |
+ if (!prev->second && it->second) { |
+ UpdateCounter( |
+ &rplr_state_.num_recoverable_losses_, apply); |
} |
} |
} |
+ |
+ // Current packet and next packet might compose a pair. |
+ // If so, the RPLR state needs to be updated accordingly. |
+ const auto& next = NextPacketStatus(it); |
+ if (next != packet_status_window_.end() && |
+ next->first == static_cast<uint16_t>(it->first + 1)) { |
+ UpdateCounter(&rplr_state_.num_known_pairs_, apply); |
+ if (!it->second && next->second) { |
+ UpdateCounter(&rplr_state_.num_recoverable_losses_, apply); |
+ } |
+ } |
} |
TransportFeedbackPacketLossTracker::PacketStatusIterator |
@@ -236,42 +245,70 @@ TransportFeedbackPacketLossTracker::NextPacketStatus(PacketStatusIterator it) { |
// to unit test. |
void TransportFeedbackPacketLossTracker::Validate() const { // Testing only! |
RTC_CHECK_LE(packet_status_window_.size(), max_window_size_); |
- RTC_CHECK_GE(num_lost_packets_, num_consecutive_losses_); |
RTC_CHECK_EQ(packet_status_window_.size(), |
- num_lost_packets_ + num_received_packets_); |
+ plr_state_.num_lost_packets_ + plr_state_.num_received_packets_); |
+ RTC_CHECK_LE(rplr_state_.num_recoverable_losses_, |
+ rplr_state_.num_known_pairs_); |
+ RTC_CHECK_LE(rplr_state_.num_known_pairs_, |
+ packet_status_window_.size() - 1); |
size_t received_packets = 0; |
size_t lost_packets = 0; |
- size_t consecutive_losses = 0; |
+ size_t known_status_pairs = 0; |
+ size_t recoverable_losses = 0; |
if (!packet_status_window_.empty()) { |
PacketStatusIterator it = ref_packet_status_; |
- bool pre_lost = false; |
- uint16_t pre_seq_num = it->first - 1; |
do { |
if (it->second) { |
++received_packets; |
} else { |
++lost_packets; |
- if (pre_lost && pre_seq_num == static_cast<uint16_t>(it->first - 1)) |
- ++consecutive_losses; |
+ } |
+ |
+ auto next = std::next(it); |
+ if (next == packet_status_window_.end()) |
+ next = packet_status_window_.begin(); |
+ |
+ if (next != ref_packet_status_ && |
+ next->first == static_cast<uint16_t>(it->first + 1)) { |
+ ++known_status_pairs; |
+ if (!it->second && next->second) |
+ ++recoverable_losses; |
} |
RTC_CHECK_LT(ForwardDiff(ReferenceSequenceNumber(), it->first), |
kSeqNumHalf); |
- pre_lost = !it->second; |
- pre_seq_num = it->first; |
- |
- ++it; |
- if (it == packet_status_window_.end()) |
- it = packet_status_window_.begin(); |
+ it = next; |
} while (it != ref_packet_status_); |
} |
- RTC_CHECK_EQ(num_received_packets_, received_packets); |
- RTC_CHECK_EQ(num_lost_packets_, lost_packets); |
- RTC_CHECK_EQ(num_consecutive_losses_, consecutive_losses); |
+ RTC_CHECK_EQ(plr_state_.num_received_packets_, received_packets); |
+ RTC_CHECK_EQ(plr_state_.num_lost_packets_, lost_packets); |
+ RTC_CHECK_EQ(rplr_state_.num_known_pairs_, known_status_pairs); |
+ RTC_CHECK_EQ(rplr_state_.num_recoverable_losses_, recoverable_losses); |
+} |
+ |
+rtc::Optional<float> |
+TransportFeedbackPacketLossTracker::PlrState::GetMetric() const { |
+ const size_t total = num_lost_packets_ + num_received_packets_; |
+ if (total < min_num_packets_) { |
+ return rtc::Optional<float>(); |
+ } else { |
+ return rtc::Optional<float>( |
+ static_cast<float>(num_lost_packets_) / total); |
+ } |
+} |
+ |
+rtc::Optional<float> |
+TransportFeedbackPacketLossTracker::RplrState::GetMetric() const { |
+ if (num_known_pairs_ < min_num_pairs_) { |
+ return rtc::Optional<float>(); |
+ } else { |
+ return rtc::Optional<float>( |
+ static_cast<float>(num_recoverable_losses_) / num_known_pairs_); |
+ } |
} |
} // namespace webrtc |