blob: 99f27c864f30a5e2e92c2c95f52d2a5da6e19b4a [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
47PacketQueue::Packet::~Packet() {}
48
49PacketQueue::PacketQueue(const Clock* clock)
50 : bytes_(0),
51 clock_(clock),
52 queue_time_sum_(0),
53 time_last_updated_(clock_->TimeInMilliseconds()),
54 paused_(false) {}
55
56PacketQueue::~PacketQueue() {}
57
58void PacketQueue::Push(const Packet& packet) {
philipel9981bd92017-09-26 17:16:06 +020059 UpdateQueueTime(packet.enqueue_time_ms);
60
61 // Store packet in list, use pointers in priority queue for cheaper moves.
62 // Packets have a handle to its own iterator in the list, for easy removal
63 // when popping from queue.
64 packet_list_.push_front(packet);
65 std::list<Packet>::iterator it = packet_list_.begin();
66 it->this_it = it; // Handle for direct removal from list.
67 prio_queue_.push(&(*it)); // Pointer into list.
68 bytes_ += packet.bytes;
69}
70
71const PacketQueue::Packet& PacketQueue::BeginPop() {
72 const PacketQueue::Packet& packet = *prio_queue_.top();
73 prio_queue_.pop();
74 return packet;
75}
76
77void PacketQueue::CancelPop(const PacketQueue::Packet& packet) {
78 prio_queue_.push(&(*packet.this_it));
79}
80
81void PacketQueue::FinalizePop(const PacketQueue::Packet& packet) {
philipel9981bd92017-09-26 17:16:06 +020082 bytes_ -= packet.bytes;
83 int64_t packet_queue_time_ms = time_last_updated_ - packet.enqueue_time_ms;
84 RTC_DCHECK_LE(packet.sum_paused_ms, packet_queue_time_ms);
85 packet_queue_time_ms -= packet.sum_paused_ms;
86 RTC_DCHECK_LE(packet_queue_time_ms, queue_time_sum_);
87 queue_time_sum_ -= packet_queue_time_ms;
88 packet_list_.erase(packet.this_it);
89 RTC_DCHECK_EQ(packet_list_.size(), prio_queue_.size());
90 if (packet_list_.empty())
91 RTC_DCHECK_EQ(0, queue_time_sum_);
92}
93
94bool PacketQueue::Empty() const {
95 return prio_queue_.empty();
96}
97
98size_t PacketQueue::SizeInPackets() const {
99 return prio_queue_.size();
100}
101
102uint64_t PacketQueue::SizeInBytes() const {
103 return bytes_;
104}
105
106int64_t PacketQueue::OldestEnqueueTimeMs() const {
107 auto it = packet_list_.rbegin();
108 if (it == packet_list_.rend())
109 return 0;
110 return it->enqueue_time_ms;
111}
112
113void PacketQueue::UpdateQueueTime(int64_t timestamp_ms) {
114 RTC_DCHECK_GE(timestamp_ms, time_last_updated_);
115 if (timestamp_ms == time_last_updated_)
116 return;
117
118 int64_t delta_ms = timestamp_ms - time_last_updated_;
119
120 if (paused_) {
121 // Increase per-packet accumulators of time spent in queue while paused,
122 // so that we can disregard that when subtracting main accumulator when
123 // popping packet from the queue.
124 for (auto& it : packet_list_) {
125 it.sum_paused_ms += delta_ms;
126 }
127 } else {
128 // Use packet packet_list_.size() not prio_queue_.size() here, as there
129 // might be an outstanding element popped from prio_queue_ currently in
130 // the SendPacket() call, while packet_list_ will always be correct.
131 queue_time_sum_ += delta_ms * packet_list_.size();
132 }
133 time_last_updated_ = timestamp_ms;
134}
135
136void PacketQueue::SetPauseState(bool paused, int64_t timestamp_ms) {
137 if (paused_ == paused)
138 return;
139 UpdateQueueTime(timestamp_ms);
140 paused_ = paused;
141}
142
143int64_t PacketQueue::AverageQueueTimeMs() const {
144 if (prio_queue_.empty())
145 return 0;
146 return queue_time_sum_ / packet_list_.size();
147}
148
philipel9981bd92017-09-26 17:16:06 +0200149} // namespace webrtc