blob: e0308d160c5445e3e2a821e611f799466caadd0d [file] [log] [blame]
philipel9981bd92017-09-26 17:16:06 +02001/*
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#include "modules/pacing/packet_queue.h"
12
13#include <algorithm>
14#include <list>
15#include <vector>
16
17#include "modules/include/module_common_types.h"
18#include "modules/pacing/alr_detector.h"
19#include "modules/pacing/bitrate_prober.h"
20#include "modules/pacing/interval_budget.h"
21#include "modules/utility/include/process_thread.h"
22#include "rtc_base/checks.h"
23#include "rtc_base/logging.h"
24#include "system_wrappers/include/clock.h"
25#include "system_wrappers/include/field_trial.h"
26
27namespace webrtc {
28
29PacketQueue::Packet::Packet(RtpPacketSender::Priority priority,
30 uint32_t ssrc,
31 uint16_t seq_number,
32 int64_t capture_time_ms,
33 int64_t enqueue_time_ms,
34 size_t length_in_bytes,
35 bool retransmission,
36 uint64_t enqueue_order)
37 : priority(priority),
38 ssrc(ssrc),
39 sequence_number(seq_number),
40 capture_time_ms(capture_time_ms),
41 enqueue_time_ms(enqueue_time_ms),
42 sum_paused_ms(0),
43 bytes(length_in_bytes),
44 retransmission(retransmission),
45 enqueue_order(enqueue_order) {}
46
philipelccdfcca2017-10-23 12:42:17 +020047PacketQueue::Packet::Packet(const Packet& other) = default;
48
philipel9981bd92017-09-26 17:16:06 +020049PacketQueue::Packet::~Packet() {}
50
51PacketQueue::PacketQueue(const Clock* clock)
52 : bytes_(0),
53 clock_(clock),
54 queue_time_sum_(0),
55 time_last_updated_(clock_->TimeInMilliseconds()),
56 paused_(false) {}
57
58PacketQueue::~PacketQueue() {}
59
60void PacketQueue::Push(const Packet& packet) {
philipel9981bd92017-09-26 17:16:06 +020061 UpdateQueueTime(packet.enqueue_time_ms);
62
63 // Store packet in list, use pointers in priority queue for cheaper moves.
64 // Packets have a handle to its own iterator in the list, for easy removal
65 // when popping from queue.
66 packet_list_.push_front(packet);
67 std::list<Packet>::iterator it = packet_list_.begin();
68 it->this_it = it; // Handle for direct removal from list.
69 prio_queue_.push(&(*it)); // Pointer into list.
70 bytes_ += packet.bytes;
71}
72
73const PacketQueue::Packet& PacketQueue::BeginPop() {
74 const PacketQueue::Packet& packet = *prio_queue_.top();
75 prio_queue_.pop();
76 return packet;
77}
78
79void PacketQueue::CancelPop(const PacketQueue::Packet& packet) {
80 prio_queue_.push(&(*packet.this_it));
81}
82
83void PacketQueue::FinalizePop(const PacketQueue::Packet& packet) {
philipel9981bd92017-09-26 17:16:06 +020084 bytes_ -= packet.bytes;
85 int64_t packet_queue_time_ms = time_last_updated_ - packet.enqueue_time_ms;
86 RTC_DCHECK_LE(packet.sum_paused_ms, packet_queue_time_ms);
87 packet_queue_time_ms -= packet.sum_paused_ms;
88 RTC_DCHECK_LE(packet_queue_time_ms, queue_time_sum_);
89 queue_time_sum_ -= packet_queue_time_ms;
90 packet_list_.erase(packet.this_it);
91 RTC_DCHECK_EQ(packet_list_.size(), prio_queue_.size());
92 if (packet_list_.empty())
93 RTC_DCHECK_EQ(0, queue_time_sum_);
94}
95
96bool PacketQueue::Empty() const {
97 return prio_queue_.empty();
98}
99
100size_t PacketQueue::SizeInPackets() const {
101 return prio_queue_.size();
102}
103
104uint64_t PacketQueue::SizeInBytes() const {
105 return bytes_;
106}
107
108int64_t PacketQueue::OldestEnqueueTimeMs() const {
109 auto it = packet_list_.rbegin();
110 if (it == packet_list_.rend())
111 return 0;
112 return it->enqueue_time_ms;
113}
114
115void PacketQueue::UpdateQueueTime(int64_t timestamp_ms) {
116 RTC_DCHECK_GE(timestamp_ms, time_last_updated_);
117 if (timestamp_ms == time_last_updated_)
118 return;
119
120 int64_t delta_ms = timestamp_ms - time_last_updated_;
121
122 if (paused_) {
123 // Increase per-packet accumulators of time spent in queue while paused,
124 // so that we can disregard that when subtracting main accumulator when
125 // popping packet from the queue.
126 for (auto& it : packet_list_) {
127 it.sum_paused_ms += delta_ms;
128 }
129 } else {
130 // Use packet packet_list_.size() not prio_queue_.size() here, as there
131 // might be an outstanding element popped from prio_queue_ currently in
132 // the SendPacket() call, while packet_list_ will always be correct.
133 queue_time_sum_ += delta_ms * packet_list_.size();
134 }
135 time_last_updated_ = timestamp_ms;
136}
137
138void PacketQueue::SetPauseState(bool paused, int64_t timestamp_ms) {
139 if (paused_ == paused)
140 return;
141 UpdateQueueTime(timestamp_ms);
142 paused_ = paused;
143}
144
145int64_t PacketQueue::AverageQueueTimeMs() const {
146 if (prio_queue_.empty())
147 return 0;
148 return queue_time_sum_ / packet_list_.size();
149}
150
philipel9981bd92017-09-26 17:16:06 +0200151} // namespace webrtc