1 /* 2 * Copyright (c) 2012 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 #ifndef MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ 12 #define MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ 13 14 #include <deque> 15 #include <map> 16 #include <memory> 17 #include <set> 18 #include <utility> 19 #include <vector> 20 21 #include "api/function_view.h" 22 #include "api/units/time_delta.h" 23 #include "api/units/timestamp.h" 24 #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" 25 #include "rtc_base/synchronization/mutex.h" 26 #include "rtc_base/thread_annotations.h" 27 28 namespace webrtc { 29 30 class Clock; 31 class RtpPacketToSend; 32 33 class RtpPacketHistory { 34 public: 35 enum class StorageMode { 36 kDisabled, // Don't store any packets. 37 kStoreAndCull // Store up to `number_to_store` packets, but try to remove 38 // packets as they time out or as signaled as received. 39 }; 40 41 // Maximum number of packets we ever allow in the history. 42 static constexpr size_t kMaxCapacity = 9600; 43 // Maximum number of entries in prioritized queue of padding packets. 44 static constexpr size_t kMaxPaddingHistory = 63; 45 // Don't remove packets within max(1 second, 3x RTT). 46 static constexpr TimeDelta kMinPacketDuration = TimeDelta::Seconds(1); 47 static constexpr int kMinPacketDurationRtt = 3; 48 // With kStoreAndCull, always remove packets after 3x max(1000ms, 3x rtt). 49 static constexpr int kPacketCullingDelayFactor = 3; 50 51 RtpPacketHistory(Clock* clock, bool enable_padding_prio); 52 53 RtpPacketHistory() = delete; 54 RtpPacketHistory(const RtpPacketHistory&) = delete; 55 RtpPacketHistory& operator=(const RtpPacketHistory&) = delete; 56 57 ~RtpPacketHistory(); 58 59 // Set/get storage mode. Note that setting the state will clear the history, 60 // even if setting the same state as is currently used. 61 void SetStorePacketsStatus(StorageMode mode, size_t number_to_store); 62 StorageMode GetStorageMode() const; 63 64 // Set RTT, used to avoid premature retransmission and to prevent over-writing 65 // a packet in the history before we are reasonably sure it has been received. 66 void SetRtt(TimeDelta rtt); 67 68 void PutRtpPacket(std::unique_ptr<RtpPacketToSend> packet, 69 Timestamp send_time); 70 71 // Gets stored RTP packet corresponding to the input |sequence number|. 72 // Returns nullptr if packet is not found or was (re)sent too recently. 73 // If a packet copy is returned, it will be marked as pending transmission but 74 // does not update send time, that must be done by MarkPacketAsSent(). 75 std::unique_ptr<RtpPacketToSend> GetPacketAndMarkAsPending( 76 uint16_t sequence_number); 77 78 // In addition to getting packet and marking as sent, this method takes an 79 // encapsulator function that takes a reference to the packet and outputs a 80 // copy that may be wrapped in a container, eg RTX. 81 // If the the encapsulator returns nullptr, the retransmit is aborted and the 82 // packet will not be marked as pending. 83 std::unique_ptr<RtpPacketToSend> GetPacketAndMarkAsPending( 84 uint16_t sequence_number, 85 rtc::FunctionView<std::unique_ptr<RtpPacketToSend>( 86 const RtpPacketToSend&)> encapsulate); 87 88 // Updates the send time for the given packet and increments the transmission 89 // counter. Marks the packet as no longer being in the pacer queue. 90 void MarkPacketAsSent(uint16_t sequence_number); 91 92 // Returns true if history contains packet with `sequence_number` and it can 93 // be retransmitted. 94 bool GetPacketState(uint16_t sequence_number) const; 95 96 // Get the packet (if any) from the history, that is deemed most likely to 97 // the remote side. This is calculated from heuristics such as packet age 98 // and times retransmitted. Updated the send time of the packet, so is not 99 // a const method. 100 std::unique_ptr<RtpPacketToSend> GetPayloadPaddingPacket(); 101 102 // Same as GetPayloadPaddingPacket(void), but adds an encapsulation 103 // that can be used for instance to encapsulate the packet in an RTX 104 // container, or to abort getting the packet if the function returns 105 // nullptr. 106 std::unique_ptr<RtpPacketToSend> GetPayloadPaddingPacket( 107 rtc::FunctionView<std::unique_ptr<RtpPacketToSend>( 108 const RtpPacketToSend&)> encapsulate); 109 110 // Cull packets that have been acknowledged as received by the remote end. 111 void CullAcknowledgedPackets(rtc::ArrayView<const uint16_t> sequence_numbers); 112 113 // Remove all pending packets from the history, but keep storage mode and 114 // capacity. 115 void Clear(); 116 117 private: 118 struct MoreUseful; 119 class StoredPacket; 120 using PacketPrioritySet = std::set<StoredPacket*, MoreUseful>; 121 122 class StoredPacket { 123 public: 124 StoredPacket() = default; 125 StoredPacket(std::unique_ptr<RtpPacketToSend> packet, 126 Timestamp send_time, 127 uint64_t insert_order); 128 StoredPacket(StoredPacket&&); 129 StoredPacket& operator=(StoredPacket&&); 130 ~StoredPacket(); 131 insert_order()132 uint64_t insert_order() const { return insert_order_; } times_retransmitted()133 size_t times_retransmitted() const { return times_retransmitted_; } 134 void IncrementTimesRetransmitted(PacketPrioritySet* priority_set); 135 136 // The time of last transmission, including retransmissions. send_time()137 Timestamp send_time() const { return send_time_; } set_send_time(Timestamp value)138 void set_send_time(Timestamp value) { send_time_ = value; } 139 140 // The actual packet. 141 std::unique_ptr<RtpPacketToSend> packet_; 142 143 // True if the packet is currently in the pacer queue pending transmission. 144 bool pending_transmission_; 145 146 private: 147 Timestamp send_time_ = Timestamp::Zero(); 148 149 // Unique number per StoredPacket, incremented by one for each added 150 // packet. Used to sort on insert order. 151 uint64_t insert_order_; 152 153 // Number of times RE-transmitted, ie excluding the first transmission. 154 size_t times_retransmitted_; 155 }; 156 struct MoreUseful { 157 bool operator()(StoredPacket* lhs, StoredPacket* rhs) const; 158 }; 159 160 // Helper method to check if packet has too recently been sent. 161 bool VerifyRtt(const StoredPacket& packet) const 162 RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_); 163 void Reset() RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_); 164 void CullOldPackets() RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_); 165 // Removes the packet from the history, and context/mapping that has been 166 // stored. Returns the RTP packet instance contained within the StoredPacket. 167 std::unique_ptr<RtpPacketToSend> RemovePacket(int packet_index) 168 RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_); 169 int GetPacketIndex(uint16_t sequence_number) const 170 RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_); 171 StoredPacket* GetStoredPacket(uint16_t sequence_number) 172 RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_); 173 174 Clock* const clock_; 175 const bool enable_padding_prio_; 176 mutable Mutex lock_; 177 size_t number_to_store_ RTC_GUARDED_BY(lock_); 178 StorageMode mode_ RTC_GUARDED_BY(lock_); 179 TimeDelta rtt_ RTC_GUARDED_BY(lock_); 180 181 // Queue of stored packets, ordered by sequence number, with older packets in 182 // the front and new packets being added to the back. Note that there may be 183 // wrap-arounds so the back may have a lower sequence number. 184 // Packets may also be removed out-of-order, in which case there will be 185 // instances of StoredPacket with `packet_` set to nullptr. The first and last 186 // entry in the queue will however always be populated. 187 std::deque<StoredPacket> packet_history_ RTC_GUARDED_BY(lock_); 188 189 // Total number of packets with inserted. 190 uint64_t packets_inserted_ RTC_GUARDED_BY(lock_); 191 // Objects from `packet_history_` ordered by "most likely to be useful", used 192 // in GetPayloadPaddingPacket(). 193 PacketPrioritySet padding_priority_ RTC_GUARDED_BY(lock_); 194 }; 195 } // namespace webrtc 196 #endif // MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_ 197