blob: 3cee8e177d14b64f4363ff685e98a7c64041c413 [file] [log] [blame]
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +00001/*
2 * Copyright (c) 2012 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 "webrtc/modules/pacing/include/paced_sender.h"
12
13#include <assert.h>
14
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +000015#include "webrtc/modules/interface/module_common_types.h"
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +000016#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +000017#include "webrtc/system_wrappers/interface/trace_event.h"
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +000018
19namespace {
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +000020// Time limit in milliseconds between packet bursts.
21const int kMinPacketLimitMs = 5;
22
23// Upper cap on process interval, in case process has not been called in a long
24// time.
25const int kMaxIntervalTimeMs = 30;
26
27// Max time that the first packet in the queue can sit in the queue if no
28// packets are sent, regardless of buffer state. In practice only in effect at
29// low bitrates (less than 320 kbits/s).
30const int kMaxQueueTimeWithoutSendingMs = 30;
31} // namespace
32
33namespace webrtc {
34
pwestin@webrtc.org52aa0192013-04-25 17:35:56 +000035bool PacedSender::PacketList::empty() const {
36 return packet_list_.empty();
37}
38
39PacedSender::Packet PacedSender::PacketList::front() const {
40 return packet_list_.front();
41}
42
43void PacedSender::PacketList::pop_front() {
44 PacedSender::Packet& packet = packet_list_.front();
pwestin@webrtc.org0f298102013-05-06 16:37:22 +000045 uint16_t sequence_number = packet.sequence_number_;
pwestin@webrtc.org52aa0192013-04-25 17:35:56 +000046 packet_list_.pop_front();
pwestin@webrtc.org0f298102013-05-06 16:37:22 +000047 sequence_number_set_.erase(sequence_number);
pwestin@webrtc.org52aa0192013-04-25 17:35:56 +000048}
49
50void PacedSender::PacketList::push_back(const PacedSender::Packet& packet) {
51 if (sequence_number_set_.find(packet.sequence_number_) ==
52 sequence_number_set_.end()) {
53 // Don't insert duplicates.
54 packet_list_.push_back(packet);
55 sequence_number_set_.insert(packet.sequence_number_);
56 }
57}
58
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +000059PacedSender::PacedSender(Callback* callback, int target_bitrate_kbps,
60 float pace_multiplier)
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +000061 : callback_(callback),
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +000062 pace_multiplier_(pace_multiplier),
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +000063 enable_(false),
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +000064 paused_(false),
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +000065 critsect_(CriticalSectionWrapper::CreateCriticalSection()),
66 target_bitrate_kbytes_per_s_(target_bitrate_kbps >> 3), // Divide by 8.
67 bytes_remaining_interval_(0),
68 padding_bytes_remaining_interval_(0),
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +000069 time_last_update_(TickTime::Now()),
70 capture_time_ms_last_queued_(0),
71 capture_time_ms_last_sent_(0) {
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +000072 UpdateBytesPerInterval(kMinPacketLimitMs);
73}
74
75PacedSender::~PacedSender() {
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +000076}
77
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +000078void PacedSender::Pause() {
79 CriticalSectionScoped cs(critsect_.get());
80 paused_ = true;
81}
82
83void PacedSender::Resume() {
84 CriticalSectionScoped cs(critsect_.get());
85 paused_ = false;
86}
87
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +000088void PacedSender::SetStatus(bool enable) {
89 CriticalSectionScoped cs(critsect_.get());
90 enable_ = enable;
91}
92
93void PacedSender::UpdateBitrate(int target_bitrate_kbps) {
94 CriticalSectionScoped cs(critsect_.get());
95 target_bitrate_kbytes_per_s_ = target_bitrate_kbps >> 3; // Divide by 8.
96}
97
98bool PacedSender::SendPacket(Priority priority, uint32_t ssrc,
99 uint16_t sequence_number, int64_t capture_time_ms, int bytes) {
100 CriticalSectionScoped cs(critsect_.get());
101
102 if (!enable_) {
103 UpdateState(bytes);
104 return true; // We can send now.
105 }
stefan@webrtc.orgbfacda62013-03-27 16:36:01 +0000106 if (capture_time_ms < 0) {
107 capture_time_ms = TickTime::MillisecondTimestamp();
108 }
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000109 if (paused_) {
110 // Queue all packets when we are paused.
111 switch (priority) {
112 case kHighPriority:
113 high_priority_packets_.push_back(
114 Packet(ssrc, sequence_number, capture_time_ms, bytes));
115 break;
116 case kNormalPriority:
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000117 if (capture_time_ms > capture_time_ms_last_queued_) {
118 capture_time_ms_last_queued_ = capture_time_ms;
119 TRACE_EVENT_ASYNC_BEGIN1("webrtc_rtp", "PacedSend", capture_time_ms,
120 "capture_time_ms", capture_time_ms);
121 }
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000122 case kLowPriority:
123 // Queue the low priority packets in the normal priority queue when we
124 // are paused to avoid starvation.
125 normal_priority_packets_.push_back(
126 Packet(ssrc, sequence_number, capture_time_ms, bytes));
127 break;
128 }
129 return false;
130 }
131
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000132 switch (priority) {
133 case kHighPriority:
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000134 if (high_priority_packets_.empty() &&
135 bytes_remaining_interval_ > 0) {
136 UpdateState(bytes);
137 return true; // We can send now.
138 }
139 high_priority_packets_.push_back(
140 Packet(ssrc, sequence_number, capture_time_ms, bytes));
141 return false;
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000142 case kNormalPriority:
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000143 if (high_priority_packets_.empty() &&
144 normal_priority_packets_.empty() &&
145 bytes_remaining_interval_ > 0) {
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000146 UpdateState(bytes);
147 return true; // We can send now.
148 }
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000149 if (capture_time_ms > capture_time_ms_last_queued_) {
150 capture_time_ms_last_queued_ = capture_time_ms;
151 TRACE_EVENT_ASYNC_BEGIN1("webrtc_rtp", "PacedSend", capture_time_ms,
152 "capture_time_ms", capture_time_ms);
153 }
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000154 normal_priority_packets_.push_back(
155 Packet(ssrc, sequence_number, capture_time_ms, bytes));
156 return false;
157 case kLowPriority:
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000158 if (high_priority_packets_.empty() &&
159 normal_priority_packets_.empty() &&
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000160 low_priority_packets_.empty() &&
161 bytes_remaining_interval_ > 0) {
162 UpdateState(bytes);
163 return true; // We can send now.
164 }
165 low_priority_packets_.push_back(
166 Packet(ssrc, sequence_number, capture_time_ms, bytes));
167 return false;
168 }
169 return false;
170}
171
stefan@webrtc.orgbfacda62013-03-27 16:36:01 +0000172int PacedSender::QueueInMs() const {
173 CriticalSectionScoped cs(critsect_.get());
174 int64_t now_ms = TickTime::MillisecondTimestamp();
175 int64_t oldest_packet_capture_time = now_ms;
176 if (!high_priority_packets_.empty()) {
177 oldest_packet_capture_time = std::min(
178 oldest_packet_capture_time,
179 high_priority_packets_.front().capture_time_ms_);
180 }
181 if (!normal_priority_packets_.empty()) {
182 oldest_packet_capture_time = std::min(
183 oldest_packet_capture_time,
184 normal_priority_packets_.front().capture_time_ms_);
185 }
186 if (!low_priority_packets_.empty()) {
187 oldest_packet_capture_time = std::min(
188 oldest_packet_capture_time,
189 low_priority_packets_.front().capture_time_ms_);
190 }
191 return now_ms - oldest_packet_capture_time;
192}
193
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000194int32_t PacedSender::TimeUntilNextProcess() {
195 CriticalSectionScoped cs(critsect_.get());
196 int64_t elapsed_time_ms =
197 (TickTime::Now() - time_last_update_).Milliseconds();
198 if (elapsed_time_ms <= 0) {
199 return kMinPacketLimitMs;
200 }
201 if (elapsed_time_ms >= kMinPacketLimitMs) {
202 return 0;
203 }
204 return kMinPacketLimitMs - elapsed_time_ms;
205}
206
207int32_t PacedSender::Process() {
208 TickTime now = TickTime::Now();
209 CriticalSectionScoped cs(critsect_.get());
210 int elapsed_time_ms = (now - time_last_update_).Milliseconds();
211 time_last_update_ = now;
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000212 if (!paused_ && elapsed_time_ms > 0) {
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000213 uint32_t delta_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms);
214 UpdateBytesPerInterval(delta_time_ms);
215 uint32_t ssrc;
216 uint16_t sequence_number;
217 int64_t capture_time_ms;
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000218 Priority priority;
219 bool last_packet;
220 while (GetNextPacket(&ssrc, &sequence_number, &capture_time_ms,
221 &priority, &last_packet)) {
222 if (priority == kNormalPriority) {
223 if (capture_time_ms > capture_time_ms_last_sent_) {
224 capture_time_ms_last_sent_ = capture_time_ms;
225 } else if (capture_time_ms == capture_time_ms_last_sent_ &&
226 last_packet) {
227 TRACE_EVENT_ASYNC_END0("webrtc_rtp", "PacedSend", capture_time_ms);
228 }
229 }
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000230 critsect_->Leave();
231 callback_->TimeToSendPacket(ssrc, sequence_number, capture_time_ms);
232 critsect_->Enter();
233 }
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000234 if (high_priority_packets_.empty() &&
235 normal_priority_packets_.empty() &&
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000236 low_priority_packets_.empty() &&
237 padding_bytes_remaining_interval_ > 0) {
238 critsect_->Leave();
239 callback_->TimeToSendPadding(padding_bytes_remaining_interval_);
240 critsect_->Enter();
241 padding_bytes_remaining_interval_ = 0;
242 bytes_remaining_interval_ -= padding_bytes_remaining_interval_;
243 }
244 }
245 return 0;
246}
247
248// MUST have critsect_ when calling.
249void PacedSender::UpdateBytesPerInterval(uint32_t delta_time_ms) {
250 uint32_t bytes_per_interval = target_bitrate_kbytes_per_s_ * delta_time_ms;
251
252 if (bytes_remaining_interval_ < 0) {
253 // We overused last interval, compensate this interval.
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000254 bytes_remaining_interval_ += pace_multiplier_ * bytes_per_interval;
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000255 } else {
256 // If we underused last interval we can't use it this interval.
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000257 bytes_remaining_interval_ = pace_multiplier_ * bytes_per_interval;
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000258 }
259 if (padding_bytes_remaining_interval_ < 0) {
260 // We overused last interval, compensate this interval.
261 padding_bytes_remaining_interval_ += bytes_per_interval;
262 } else {
263 // If we underused last interval we can't use it this interval.
264 padding_bytes_remaining_interval_ = bytes_per_interval;
265 }
266}
267
268// MUST have critsect_ when calling.
269bool PacedSender::GetNextPacket(uint32_t* ssrc, uint16_t* sequence_number,
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000270 int64_t* capture_time_ms, Priority* priority,
271 bool* last_packet) {
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000272 if (bytes_remaining_interval_ <= 0) {
273 // All bytes consumed for this interval.
274 // Check if we have not sent in a too long time.
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000275 if ((TickTime::Now() - time_last_send_).Milliseconds() >
276 kMaxQueueTimeWithoutSendingMs) {
277 if (!high_priority_packets_.empty()) {
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000278 *priority = kHighPriority;
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000279 GetNextPacketFromList(&high_priority_packets_, ssrc, sequence_number,
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000280 capture_time_ms, last_packet);
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000281 return true;
282 }
283 if (!normal_priority_packets_.empty()) {
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000284 *priority = kNormalPriority;
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000285 GetNextPacketFromList(&normal_priority_packets_, ssrc, sequence_number,
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000286 capture_time_ms, last_packet);
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000287 return true;
288 }
289 }
290 return false;
291 }
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000292 if (!high_priority_packets_.empty()) {
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000293 *priority = kHighPriority;
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000294 GetNextPacketFromList(&high_priority_packets_, ssrc, sequence_number,
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000295 capture_time_ms, last_packet);
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000296 return true;
297 }
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000298 if (!normal_priority_packets_.empty()) {
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000299 *priority = kNormalPriority;
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000300 GetNextPacketFromList(&normal_priority_packets_, ssrc, sequence_number,
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000301 capture_time_ms, last_packet);
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000302 return true;
303 }
304 if (!low_priority_packets_.empty()) {
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000305 *priority = kLowPriority;
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000306 GetNextPacketFromList(&low_priority_packets_, ssrc, sequence_number,
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000307 capture_time_ms, last_packet);
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000308 return true;
309 }
310 return false;
311}
312
pwestin@webrtc.org52aa0192013-04-25 17:35:56 +0000313void PacedSender::GetNextPacketFromList(PacketList* list,
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000314 uint32_t* ssrc, uint16_t* sequence_number, int64_t* capture_time_ms,
315 bool* last_packet) {
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000316 Packet packet = list->front();
317 UpdateState(packet.bytes_);
318 *sequence_number = packet.sequence_number_;
319 *ssrc = packet.ssrc_;
320 *capture_time_ms = packet.capture_time_ms_;
321 list->pop_front();
pwestin@webrtc.org52b4e882013-05-02 19:02:17 +0000322 *last_packet = list->empty() ||
323 list->front().capture_time_ms_ > *capture_time_ms;
pwestin@webrtc.orgdb418562013-03-22 23:39:29 +0000324}
325
pwestin@webrtc.orgb5180172012-11-09 20:56:23 +0000326// MUST have critsect_ when calling.
327void PacedSender::UpdateState(int num_bytes) {
328 time_last_send_ = TickTime::Now();
329 bytes_remaining_interval_ -= num_bytes;
330 padding_bytes_remaining_interval_ -= num_bytes;
331}
332
333} // namespace webrtc