philipel | 881829b | 2017-10-13 13:27:23 +0200 | [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 | |
Sebastian Jansson | b537496 | 2018-02-07 13:26:38 +0100 | [diff] [blame] | 11 | #ifndef MODULES_PACING_ROUND_ROBIN_PACKET_QUEUE_H_ |
| 12 | #define MODULES_PACING_ROUND_ROBIN_PACKET_QUEUE_H_ |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 13 | |
Yves Gerey | 988cc08 | 2018-10-23 12:03:01 +0200 | [diff] [blame] | 14 | #include <stddef.h> |
| 15 | #include <stdint.h> |
Jonas Olsson | a4d8737 | 2019-07-05 19:08:33 +0200 | [diff] [blame] | 16 | |
Sebastian Jansson | 60570dc | 2018-09-13 17:11:06 +0200 | [diff] [blame] | 17 | #include <list> |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 18 | #include <map> |
Erik Språng | 58ee187 | 2019-06-18 16:20:11 +0200 | [diff] [blame] | 19 | #include <memory> |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 20 | #include <queue> |
| 21 | #include <set> |
| 22 | |
Yves Gerey | 988cc08 | 2018-10-23 12:03:01 +0200 | [diff] [blame] | 23 | #include "absl/types/optional.h" |
Erik Språng | 7702c8a | 2019-07-30 22:36:02 +0200 | [diff] [blame] | 24 | #include "api/transport/webrtc_key_value_config.h" |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 25 | #include "api/units/data_size.h" |
| 26 | #include "api/units/time_delta.h" |
| 27 | #include "api/units/timestamp.h" |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 28 | #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
Erik Språng | 58ee187 | 2019-06-18 16:20:11 +0200 | [diff] [blame] | 29 | #include "modules/rtp_rtcp/source/rtp_packet_to_send.h" |
Yves Gerey | 988cc08 | 2018-10-23 12:03:01 +0200 | [diff] [blame] | 30 | #include "system_wrappers/include/clock.h" |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 31 | |
| 32 | namespace webrtc { |
| 33 | |
Sebastian Jansson | 60570dc | 2018-09-13 17:11:06 +0200 | [diff] [blame] | 34 | class RoundRobinPacketQueue { |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 35 | public: |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 36 | RoundRobinPacketQueue(Timestamp start_time, |
Erik Språng | 7702c8a | 2019-07-30 22:36:02 +0200 | [diff] [blame] | 37 | const WebRtcKeyValueConfig* field_trials); |
Sebastian Jansson | 60570dc | 2018-09-13 17:11:06 +0200 | [diff] [blame] | 38 | ~RoundRobinPacketQueue(); |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 39 | |
Erik Språng | f660e81 | 2019-09-01 12:26:44 +0000 | [diff] [blame] | 40 | struct QueuedPacket { |
| 41 | public: |
| 42 | QueuedPacket( |
| 43 | int priority, |
| 44 | RtpPacketToSend::Type type, |
| 45 | uint32_t ssrc, |
| 46 | uint16_t seq_number, |
| 47 | int64_t capture_time_ms, |
| 48 | Timestamp enqueue_time, |
| 49 | DataSize size, |
| 50 | bool retransmission, |
| 51 | uint64_t enqueue_order, |
| 52 | std::multiset<Timestamp>::iterator enqueue_time_it, |
| 53 | absl::optional<std::list<std::unique_ptr<RtpPacketToSend>>::iterator> |
| 54 | packet_it); |
| 55 | QueuedPacket(const QueuedPacket& rhs); |
| 56 | ~QueuedPacket(); |
| 57 | |
| 58 | bool operator<(const QueuedPacket& other) const; |
| 59 | |
| 60 | int priority() const { return priority_; } |
| 61 | RtpPacketToSend::Type type() const { return type_; } |
| 62 | uint32_t ssrc() const { return ssrc_; } |
| 63 | uint16_t sequence_number() const { return sequence_number_; } |
| 64 | int64_t capture_time_ms() const { return capture_time_ms_; } |
| 65 | Timestamp enqueue_time() const { return enqueue_time_; } |
| 66 | DataSize size() const { return size_; } |
| 67 | bool is_retransmission() const { return retransmission_; } |
| 68 | uint64_t enqueue_order() const { return enqueue_order_; } |
| 69 | std::unique_ptr<RtpPacketToSend> ReleasePacket(); |
| 70 | |
| 71 | // For internal use. |
| 72 | absl::optional<std::list<std::unique_ptr<RtpPacketToSend>>::iterator> |
| 73 | PacketIterator() const { |
| 74 | return packet_it_; |
| 75 | } |
| 76 | std::multiset<Timestamp>::iterator EnqueueTimeIterator() const { |
| 77 | return enqueue_time_it_; |
| 78 | } |
| 79 | void SubtractPauseTime(TimeDelta pause_time_sum); |
| 80 | |
| 81 | private: |
| 82 | RtpPacketToSend::Type type_; |
| 83 | int priority_; |
| 84 | uint32_t ssrc_; |
| 85 | uint16_t sequence_number_; |
| 86 | int64_t capture_time_ms_; // Absolute time of frame capture. |
| 87 | Timestamp enqueue_time_; // Absolute time of pacer queue entry. |
| 88 | DataSize size_; |
| 89 | bool retransmission_; |
| 90 | uint64_t enqueue_order_; |
| 91 | std::multiset<Timestamp>::iterator enqueue_time_it_; |
| 92 | // Iterator into |rtp_packets_| where the memory for RtpPacket is owned, |
| 93 | // if applicable. |
| 94 | absl::optional<std::list<std::unique_ptr<RtpPacketToSend>>::iterator> |
| 95 | packet_it_; |
| 96 | }; |
| 97 | |
| 98 | void Push(int priority, |
| 99 | RtpPacketToSend::Type type, |
| 100 | uint32_t ssrc, |
| 101 | uint16_t seq_number, |
| 102 | int64_t capture_time_ms, |
| 103 | Timestamp enqueue_time, |
| 104 | DataSize size, |
| 105 | bool retransmission, |
| 106 | uint64_t enqueue_order); |
Erik Språng | 58ee187 | 2019-06-18 16:20:11 +0200 | [diff] [blame] | 107 | void Push(int priority, |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 108 | Timestamp enqueue_time, |
Erik Språng | 58ee187 | 2019-06-18 16:20:11 +0200 | [diff] [blame] | 109 | uint64_t enqueue_order, |
| 110 | std::unique_ptr<RtpPacketToSend> packet); |
Erik Språng | f660e81 | 2019-09-01 12:26:44 +0000 | [diff] [blame] | 111 | QueuedPacket* BeginPop(); |
| 112 | void CancelPop(); |
| 113 | void FinalizePop(); |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 114 | |
Sebastian Jansson | 60570dc | 2018-09-13 17:11:06 +0200 | [diff] [blame] | 115 | bool Empty() const; |
| 116 | size_t SizeInPackets() const; |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 117 | DataSize Size() const; |
Erik Språng | eb48799 | 2019-11-14 14:15:15 +0100 | [diff] [blame] | 118 | bool NextPacketIsAudio() const; |
Sebastian Jansson | 60570dc | 2018-09-13 17:11:06 +0200 | [diff] [blame] | 119 | |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 120 | Timestamp OldestEnqueueTime() const; |
| 121 | TimeDelta AverageQueueTime() const; |
| 122 | void UpdateQueueTime(Timestamp now); |
| 123 | void SetPauseState(bool paused, Timestamp now); |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 124 | |
Sebastian Jansson | b537496 | 2018-02-07 13:26:38 +0100 | [diff] [blame] | 125 | private: |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 126 | struct StreamPrioKey { |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 127 | StreamPrioKey(int priority, DataSize size) |
| 128 | : priority(priority), size(size) {} |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 129 | |
| 130 | bool operator<(const StreamPrioKey& other) const { |
| 131 | if (priority != other.priority) |
| 132 | return priority < other.priority; |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 133 | return size < other.size; |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 134 | } |
| 135 | |
Erik Språng | 58ee187 | 2019-06-18 16:20:11 +0200 | [diff] [blame] | 136 | const int priority; |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 137 | const DataSize size; |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 138 | }; |
| 139 | |
| 140 | struct Stream { |
| 141 | Stream(); |
Mirko Bonadei | b471c90 | 2018-07-18 14:11:27 +0200 | [diff] [blame] | 142 | Stream(const Stream&); |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 143 | |
| 144 | virtual ~Stream(); |
| 145 | |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 146 | DataSize size; |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 147 | uint32_t ssrc; |
Erik Språng | 58ee187 | 2019-06-18 16:20:11 +0200 | [diff] [blame] | 148 | std::priority_queue<QueuedPacket> packet_queue; |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 149 | |
| 150 | // Whenever a packet is inserted for this stream we check if |priority_it| |
| 151 | // points to an element in |stream_priorities_|, and if it does it means |
| 152 | // this stream has already been scheduled, and if the scheduled priority is |
| 153 | // lower than the priority of the incoming packet we reschedule this stream |
| 154 | // with the higher priority. |
| 155 | std::multimap<StreamPrioKey, uint32_t>::iterator priority_it; |
| 156 | }; |
| 157 | |
Erik Språng | f660e81 | 2019-09-01 12:26:44 +0000 | [diff] [blame] | 158 | void Push(QueuedPacket packet); |
Erik Språng | 58ee187 | 2019-06-18 16:20:11 +0200 | [diff] [blame] | 159 | |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 160 | Stream* GetHighestPriorityStream(); |
| 161 | |
| 162 | // Just used to verify correctness. |
| 163 | bool IsSsrcScheduled(uint32_t ssrc) const; |
| 164 | |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 165 | Timestamp time_last_updated_; |
Erik Språng | f660e81 | 2019-09-01 12:26:44 +0000 | [diff] [blame] | 166 | absl::optional<QueuedPacket> pop_packet_; |
| 167 | absl::optional<Stream*> pop_stream_; |
philipel | ccdfcca | 2017-10-23 12:42:17 +0200 | [diff] [blame] | 168 | |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 169 | bool paused_; |
| 170 | size_t size_packets_; |
| 171 | DataSize size_; |
| 172 | DataSize max_size_; |
| 173 | TimeDelta queue_time_sum_; |
| 174 | TimeDelta pause_time_sum_; |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 175 | |
| 176 | // A map of streams used to prioritize from which stream to send next. We use |
| 177 | // a multimap instead of a priority_queue since the priority of a stream can |
| 178 | // change as a new packet is inserted, and a multimap allows us to remove and |
| 179 | // then reinsert a StreamPrioKey if the priority has increased. |
| 180 | std::multimap<StreamPrioKey, uint32_t> stream_priorities_; |
| 181 | |
| 182 | // A map of SSRCs to Streams. |
| 183 | std::map<uint32_t, Stream> streams_; |
| 184 | |
| 185 | // The enqueue time of every packet currently in the queue. Used to figure out |
| 186 | // the age of the oldest packet in the queue. |
Erik Språng | 82d75a6 | 2019-08-09 22:44:47 +0200 | [diff] [blame] | 187 | std::multiset<Timestamp> enqueue_times_; |
Erik Språng | 58ee187 | 2019-06-18 16:20:11 +0200 | [diff] [blame] | 188 | |
| 189 | // List of RTP packets to be sent, not necessarily in the order they will be |
| 190 | // sent. PacketInfo.packet_it will point to an entry in this list, or the |
| 191 | // end iterator of this list if queue does not have direct ownership of the |
| 192 | // packet. |
| 193 | std::list<std::unique_ptr<RtpPacketToSend>> rtp_packets_; |
Erik Språng | f660e81 | 2019-09-01 12:26:44 +0000 | [diff] [blame] | 194 | |
| 195 | const bool send_side_bwe_with_overhead_; |
philipel | 881829b | 2017-10-13 13:27:23 +0200 | [diff] [blame] | 196 | }; |
| 197 | } // namespace webrtc |
| 198 | |
Sebastian Jansson | b537496 | 2018-02-07 13:26:38 +0100 | [diff] [blame] | 199 | #endif // MODULES_PACING_ROUND_ROBIN_PACKET_QUEUE_H_ |