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 | |
| 11 | #ifndef MODULES_PACING_PACKET_QUEUE2_H_ |
| 12 | #define MODULES_PACING_PACKET_QUEUE2_H_ |
| 13 | |
| 14 | #include <map> |
| 15 | #include <queue> |
| 16 | #include <set> |
| 17 | |
| 18 | #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
| 19 | |
| 20 | namespace webrtc { |
| 21 | |
| 22 | class PacketQueue2 { |
| 23 | public: |
| 24 | explicit PacketQueue2(const Clock* clock); |
| 25 | virtual ~PacketQueue2(); |
| 26 | |
| 27 | struct Packet { |
| 28 | Packet(RtpPacketSender::Priority priority, |
| 29 | uint32_t ssrc, |
| 30 | uint16_t seq_number, |
| 31 | int64_t capture_time_ms, |
| 32 | int64_t enqueue_time_ms, |
| 33 | size_t length_in_bytes, |
| 34 | bool retransmission, |
| 35 | uint64_t enqueue_order); |
| 36 | |
| 37 | Packet(const Packet& other); |
| 38 | |
| 39 | virtual ~Packet(); |
| 40 | |
| 41 | bool operator<(const Packet& other) const { |
| 42 | if (priority != other.priority) |
| 43 | return priority > other.priority; |
| 44 | if (retransmission != other.retransmission) |
| 45 | return other.retransmission; |
| 46 | |
| 47 | return enqueue_order > other.enqueue_order; |
| 48 | } |
| 49 | |
| 50 | RtpPacketSender::Priority priority; |
| 51 | uint32_t ssrc; |
| 52 | uint16_t sequence_number; |
| 53 | int64_t capture_time_ms; // Absolute time of frame capture. |
| 54 | int64_t enqueue_time_ms; // Absolute time of pacer queue entry. |
| 55 | size_t bytes; |
| 56 | bool retransmission; |
| 57 | uint64_t enqueue_order; |
| 58 | std::multiset<int64_t>::iterator enqueue_time_it; |
| 59 | }; |
| 60 | |
| 61 | void Push(const Packet& packet); |
| 62 | const Packet& Top(); |
| 63 | void Pop(); |
| 64 | |
| 65 | bool Empty() const; |
| 66 | size_t SizeInPackets() const; |
| 67 | uint64_t SizeInBytes() const; |
| 68 | |
| 69 | int64_t OldestEnqueueTimeMs() const; |
| 70 | int64_t AverageQueueTimeMs() const; |
| 71 | void UpdateQueueTime(int64_t timestamp_ms); |
| 72 | void SetPauseState(bool paused, int64_t timestamp_ms); |
| 73 | |
| 74 | struct StreamPrioKey { |
| 75 | StreamPrioKey() = default; |
| 76 | StreamPrioKey(RtpPacketSender::Priority priority, int64_t bytes) |
| 77 | : priority(priority), bytes(bytes) {} |
| 78 | |
| 79 | bool operator<(const StreamPrioKey& other) const { |
| 80 | if (priority != other.priority) |
| 81 | return priority < other.priority; |
| 82 | return bytes > other.bytes; |
| 83 | } |
| 84 | |
| 85 | const RtpPacketSender::Priority priority; |
| 86 | const size_t bytes; |
| 87 | }; |
| 88 | |
| 89 | struct Stream { |
| 90 | Stream(); |
| 91 | |
| 92 | virtual ~Stream(); |
| 93 | |
| 94 | size_t bytes; |
| 95 | uint32_t ssrc; |
| 96 | std::priority_queue<Packet> packet_queue; |
| 97 | |
| 98 | // Whenever a packet is inserted for this stream we check if |priority_it| |
| 99 | // points to an element in |stream_priorities_|, and if it does it means |
| 100 | // this stream has already been scheduled, and if the scheduled priority is |
| 101 | // lower than the priority of the incoming packet we reschedule this stream |
| 102 | // with the higher priority. |
| 103 | std::multimap<StreamPrioKey, uint32_t>::iterator priority_it; |
| 104 | }; |
| 105 | |
| 106 | private: |
| 107 | static constexpr size_t kMaxLeadingBytes = 1400; |
| 108 | |
| 109 | Stream* GetHighestPriorityStream(); |
| 110 | |
| 111 | // Just used to verify correctness. |
| 112 | bool IsSsrcScheduled(uint32_t ssrc) const; |
| 113 | |
| 114 | const Clock* const clock_; |
| 115 | bool paused_ = false; |
| 116 | size_t size_packets_ = 0; |
| 117 | size_t size_bytes_ = 0; |
| 118 | size_t max_bytes_ = kMaxLeadingBytes; |
| 119 | int64_t time_last_updated_; |
| 120 | int64_t queue_time_sum_ms_ = 0; |
| 121 | int64_t pause_time_sum_ms_ = 0; |
| 122 | |
| 123 | // A map of streams used to prioritize from which stream to send next. We use |
| 124 | // a multimap instead of a priority_queue since the priority of a stream can |
| 125 | // change as a new packet is inserted, and a multimap allows us to remove and |
| 126 | // then reinsert a StreamPrioKey if the priority has increased. |
| 127 | std::multimap<StreamPrioKey, uint32_t> stream_priorities_; |
| 128 | |
| 129 | // A map of SSRCs to Streams. |
| 130 | std::map<uint32_t, Stream> streams_; |
| 131 | |
| 132 | // The enqueue time of every packet currently in the queue. Used to figure out |
| 133 | // the age of the oldest packet in the queue. |
| 134 | std::multiset<int64_t> enqueue_times_; |
| 135 | }; |
| 136 | } // namespace webrtc |
| 137 | |
| 138 | #endif // MODULES_PACING_PACKET_QUEUE2_H_ |