packet_arrival_history.cc (4329B)
1 /* 2 * Copyright (c) 2022 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 11 #include "modules/audio_coding/neteq/packet_arrival_history.h" 12 13 #include <algorithm> 14 #include <cstdint> 15 16 #include "api/neteq/tick_timer.h" 17 #include "rtc_base/checks.h" 18 19 namespace webrtc { 20 21 PacketArrivalHistory::PacketArrivalHistory(const TickTimer* tick_timer, 22 int window_size_ms) 23 : tick_timer_(tick_timer), window_size_ms_(window_size_ms) {} 24 25 bool PacketArrivalHistory::Insert(uint32_t rtp_timestamp, 26 int packet_length_samples) { 27 int64_t arrival_timestamp = 28 tick_timer_->ticks() * tick_timer_->ms_per_tick() * sample_rate_khz_; 29 PacketArrival packet(timestamp_unwrapper_.Unwrap(rtp_timestamp), 30 arrival_timestamp, packet_length_samples); 31 if (IsObsolete(packet)) { 32 return false; 33 } 34 if (Contains(packet)) { 35 return false; 36 } 37 history_.emplace(packet.rtp_timestamp, packet); 38 if (packet != history_.rbegin()->second) { 39 // Packet was reordered. 40 return true; 41 } 42 // Remove old packets. 43 while (IsObsolete(history_.begin()->second)) { 44 if (history_.begin()->second == min_packet_arrivals_.front()) { 45 min_packet_arrivals_.pop_front(); 46 } 47 if (history_.begin()->second == max_packet_arrivals_.front()) { 48 max_packet_arrivals_.pop_front(); 49 } 50 history_.erase(history_.begin()); 51 } 52 // Ensure ordering constraints. 53 while (!min_packet_arrivals_.empty() && 54 packet <= min_packet_arrivals_.back()) { 55 min_packet_arrivals_.pop_back(); 56 } 57 while (!max_packet_arrivals_.empty() && 58 packet >= max_packet_arrivals_.back()) { 59 max_packet_arrivals_.pop_back(); 60 } 61 min_packet_arrivals_.push_back(packet); 62 max_packet_arrivals_.push_back(packet); 63 return true; 64 } 65 66 void PacketArrivalHistory::Reset() { 67 history_.clear(); 68 min_packet_arrivals_.clear(); 69 max_packet_arrivals_.clear(); 70 timestamp_unwrapper_.Reset(); 71 } 72 73 int PacketArrivalHistory::GetDelayMs(uint32_t rtp_timestamp) const { 74 int64_t unwrapped_rtp_timestamp = 75 timestamp_unwrapper_.PeekUnwrap(rtp_timestamp); 76 int64_t current_timestamp = 77 tick_timer_->ticks() * tick_timer_->ms_per_tick() * sample_rate_khz_; 78 PacketArrival packet(unwrapped_rtp_timestamp, current_timestamp, 79 /*duration_ms=*/0); 80 return GetPacketArrivalDelayMs(packet); 81 } 82 83 int PacketArrivalHistory::GetMaxDelayMs() const { 84 if (max_packet_arrivals_.empty()) { 85 return 0; 86 } 87 return GetPacketArrivalDelayMs(max_packet_arrivals_.front()); 88 } 89 90 bool PacketArrivalHistory::IsNewestRtpTimestamp(uint32_t rtp_timestamp) const { 91 if (history_.empty()) { 92 return true; 93 } 94 int64_t unwrapped_rtp_timestamp = 95 timestamp_unwrapper_.PeekUnwrap(rtp_timestamp); 96 return unwrapped_rtp_timestamp == history_.rbegin()->second.rtp_timestamp; 97 } 98 99 int PacketArrivalHistory::GetPacketArrivalDelayMs( 100 const PacketArrival& packet_arrival) const { 101 if (min_packet_arrivals_.empty()) { 102 return 0; 103 } 104 RTC_DCHECK_NE(sample_rate_khz_, 0); 105 // TODO(jakobi): Timestamps are first converted to millis for bit-exactness. 106 return std::max<int>( 107 packet_arrival.arrival_timestamp / sample_rate_khz_ - 108 min_packet_arrivals_.front().arrival_timestamp / sample_rate_khz_ - 109 (packet_arrival.rtp_timestamp / sample_rate_khz_ - 110 min_packet_arrivals_.front().rtp_timestamp / sample_rate_khz_), 111 0); 112 } 113 114 bool PacketArrivalHistory::IsObsolete( 115 const PacketArrival& packet_arrival) const { 116 if (history_.empty()) { 117 return false; 118 } 119 return packet_arrival.rtp_timestamp + window_size_ms_ * sample_rate_khz_ < 120 history_.rbegin()->second.rtp_timestamp; 121 } 122 123 bool PacketArrivalHistory::Contains(const PacketArrival& packet_arrival) const { 124 auto it = history_.upper_bound(packet_arrival.rtp_timestamp); 125 if (it == history_.begin()) { 126 return false; 127 } 128 --it; 129 return it->second.contains(packet_arrival); 130 } 131 132 } // namespace webrtc