File: rtp_packet_history.h

package info (click to toggle)
chromium 140.0.7339.127-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,201,772 kB
  • sloc: cpp: 35,093,800; ansic: 7,161,670; javascript: 4,199,694; python: 1,441,798; asm: 949,904; xml: 747,503; pascal: 187,748; perl: 88,691; sh: 88,248; objc: 79,953; sql: 52,714; cs: 44,599; fortran: 24,137; makefile: 22,119; tcl: 15,277; php: 13,980; yacc: 9,000; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (196 lines) | stat: -rw-r--r-- 8,047 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_
#define MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_

#include <cstddef>
#include <cstdint>
#include <deque>
#include <memory>
#include <optional>

#include "api/array_view.h"
#include "api/environment/environment.h"
#include "api/function_view.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread_annotations.h"

namespace webrtc {

class Clock;

class RtpPacketHistory {
 public:
  enum class StorageMode {
    kDisabled,     // Don't store any packets.
    kStoreAndCull  // Store up to `number_to_store` packets, but try to remove
                   // packets as they time out or as signaled as received.
  };

  enum class PaddingMode {
    kDefault,  // Last packet stored in the history that has not yet been
               // culled.
    kRecentLargePacket  // Use the most recent large packet. Packet is kept for
                        // padding even after it has been culled from history.
  };

  // Maximum number of packets we ever allow in the history.
  static constexpr size_t kMaxCapacity = 9600;
  // Maximum number of entries in prioritized queue of padding packets.
  static constexpr size_t kMaxPaddingHistory = 63;
  // Don't remove packets within max(1 second, 3x RTT).
  static constexpr TimeDelta kMinPacketDuration = TimeDelta::Seconds(1);
  static constexpr int kMinPacketDurationRtt = 3;
  // With kStoreAndCull, always remove packets after 3x max(1000ms, 3x rtt).
  static constexpr int kPacketCullingDelayFactor = 3;

  RtpPacketHistory(const Environment& env, PaddingMode padding_mode);

  RtpPacketHistory() = delete;
  RtpPacketHistory(const RtpPacketHistory&) = delete;
  RtpPacketHistory& operator=(const RtpPacketHistory&) = delete;

  ~RtpPacketHistory();

  // Set/get storage mode. Note that setting the state will clear the history,
  // even if setting the same state as is currently used.
  void SetStorePacketsStatus(StorageMode mode, size_t number_to_store);
  StorageMode GetStorageMode() const;

  // Set RTT, used to avoid premature retransmission and to prevent over-writing
  // a packet in the history before we are reasonably sure it has been received.
  void SetRtt(TimeDelta rtt);

  void PutRtpPacket(std::unique_ptr<RtpPacketToSend> packet,
                    Timestamp send_time);

  // Gets stored RTP packet corresponding to the input |sequence number|.
  // Returns nullptr if packet is not found or was (re)sent too recently.
  // If a packet copy is returned, it will be marked as pending transmission but
  // does not update send time, that must be done by MarkPacketAsSent().
  std::unique_ptr<RtpPacketToSend> GetPacketAndMarkAsPending(
      uint16_t sequence_number);

  // In addition to getting packet and marking as sent, this method takes an
  // encapsulator function that takes a reference to the packet and outputs a
  // copy that may be wrapped in a container, eg RTX.
  // If the the encapsulator returns nullptr, the retransmit is aborted and the
  // packet will not be marked as pending.
  std::unique_ptr<RtpPacketToSend> GetPacketAndMarkAsPending(
      uint16_t sequence_number,
      FunctionView<std::unique_ptr<RtpPacketToSend>(const RtpPacketToSend&)>
          encapsulate);

  // Updates the send time for the given packet and increments the transmission
  // counter. Marks the packet as no longer being in the pacer queue.
  void MarkPacketAsSent(uint16_t sequence_number);

  // Returns true if history contains packet with `sequence_number` and it can
  // be retransmitted.
  bool GetPacketState(uint16_t sequence_number) const;

  // Get the packet (if any) from the history, that is deemed most likely to
  // the remote side. This is calculated from heuristics such as packet age
  // and times retransmitted. Updated the send time of the packet, so is not
  // a const method.
  std::unique_ptr<RtpPacketToSend> GetPayloadPaddingPacket();

  // Same as GetPayloadPaddingPacket(void), but adds an encapsulation
  // that can be used for instance to encapsulate the packet in an RTX
  // container, or to abort getting the packet if the function returns
  // nullptr.
  std::unique_ptr<RtpPacketToSend> GetPayloadPaddingPacket(
      FunctionView<std::unique_ptr<RtpPacketToSend>(const RtpPacketToSend&)>
          encapsulate);

  // Cull packets that have been acknowledged as received by the remote end.
  void CullAcknowledgedPackets(ArrayView<const uint16_t> sequence_numbers);

  // Remove all pending packets from the history, but keep storage mode and
  // capacity.
  void Clear();

 private:
  class StoredPacket {
   public:
    StoredPacket() = default;
    StoredPacket(std::unique_ptr<RtpPacketToSend> packet,
                 Timestamp send_time,
                 uint64_t insert_order);
    StoredPacket(StoredPacket&&);
    StoredPacket& operator=(StoredPacket&&);
    ~StoredPacket();

    uint64_t insert_order() const { return insert_order_; }
    size_t times_retransmitted() const { return times_retransmitted_; }
    void IncrementTimesRetransmitted();

    // The time of last transmission, including retransmissions.
    Timestamp send_time() const { return send_time_; }
    void set_send_time(Timestamp value) { send_time_ = value; }

    // The actual packet.
    std::unique_ptr<RtpPacketToSend> packet_;

    // True if the packet is currently in the pacer queue pending transmission.
    bool pending_transmission_;

   private:
    Timestamp send_time_ = Timestamp::Zero();

    // Unique number per StoredPacket, incremented by one for each added
    // packet. Used to sort on insert order.
    uint64_t insert_order_;

    // Number of times RE-transmitted, ie excluding the first transmission.
    size_t times_retransmitted_;
  };

  // Helper method to check if packet has too recently been sent.
  bool VerifyRtt(const StoredPacket& packet) const
      RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
  void Reset() RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
  void CullOldPackets() RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
  // Removes the packet from the history, and context/mapping that has been
  // stored. Returns the RTP packet instance contained within the StoredPacket.
  std::unique_ptr<RtpPacketToSend> RemovePacket(int packet_index)
      RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
  int GetPacketIndex(uint16_t sequence_number) const
      RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);
  StoredPacket* GetStoredPacket(uint16_t sequence_number)
      RTC_EXCLUSIVE_LOCKS_REQUIRED(lock_);

  Clock* const clock_;
  const PaddingMode padding_mode_;
  mutable Mutex lock_;
  size_t number_to_store_ RTC_GUARDED_BY(lock_);
  StorageMode mode_ RTC_GUARDED_BY(lock_);
  TimeDelta rtt_ RTC_GUARDED_BY(lock_);

  // Queue of stored packets, ordered by sequence number, with older packets in
  // the front and new packets being added to the back. Note that there may be
  // wrap-arounds so the back may have a lower sequence number.
  // Packets may also be removed out-of-order, in which case there will be
  // instances of StoredPacket with `packet_` set to nullptr. The first and last
  // entry in the queue will however always be populated.
  std::deque<StoredPacket> packet_history_ RTC_GUARDED_BY(lock_);

  // Total number of packets with inserted.
  uint64_t packets_inserted_ RTC_GUARDED_BY(lock_);

  std::optional<RtpPacketToSend> large_payload_packet_ RTC_GUARDED_BY(lock_);
};
}  // namespace webrtc
#endif  // MODULES_RTP_RTCP_SOURCE_RTP_PACKET_HISTORY_H_