2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
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.
11 #include "webrtc/modules/pacing/include/paced_sender.h"
15 #include "webrtc/modules/interface/module_common_types.h"
16 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
17 #include "webrtc/system_wrappers/interface/trace_event.h"
20 // Time limit in milliseconds between packet bursts.
21 const int kMinPacketLimitMs = 5;
23 // Upper cap on process interval, in case process has not been called in a long
25 const int kMaxIntervalTimeMs = 30;
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).
30 const int kMaxQueueTimeWithoutSendingMs = 30;
36 namespace paced_sender {
38 Packet(uint32_t ssrc, uint16_t seq_number, int64_t capture_time_ms,
41 sequence_number_(seq_number),
42 capture_time_ms_(capture_time_ms),
43 bytes_(length_in_bytes) {
46 uint16_t sequence_number_;
47 int64_t capture_time_ms_;
51 // STL list style class which prevents duplicates in the list.
57 return packet_list_.empty();
60 Packet front() const {
61 return packet_list_.front();
65 Packet& packet = packet_list_.front();
66 uint16_t sequence_number = packet.sequence_number_;
67 packet_list_.pop_front();
68 sequence_number_set_.erase(sequence_number);
71 void push_back(const Packet& packet) {
72 if (sequence_number_set_.find(packet.sequence_number_) ==
73 sequence_number_set_.end()) {
74 // Don't insert duplicates.
75 packet_list_.push_back(packet);
76 sequence_number_set_.insert(packet.sequence_number_);
81 std::list<Packet> packet_list_;
82 std::set<uint16_t> sequence_number_set_;
85 class IntervalBudget {
87 explicit IntervalBudget(int initial_target_rate_kbps)
88 : target_rate_kbps_(initial_target_rate_kbps),
89 bytes_remaining_(0) {}
91 void set_target_rate_kbps(int target_rate_kbps) {
92 target_rate_kbps_ = target_rate_kbps;
95 void IncreaseBudget(int delta_time_ms) {
96 int bytes = target_rate_kbps_ * delta_time_ms / 8;
97 if (bytes_remaining_ < 0) {
98 // We overused last interval, compensate this interval.
99 bytes_remaining_ = bytes_remaining_ + bytes;
101 // If we underused last interval we can't use it this interval.
102 bytes_remaining_ = bytes;
106 void UseBudget(int bytes) {
107 bytes_remaining_ = std::max(bytes_remaining_ - bytes,
108 -100 * target_rate_kbps_ / 8);
111 int bytes_remaining() const { return bytes_remaining_; }
114 int target_rate_kbps_;
115 int bytes_remaining_;
117 } // namespace paced_sender
119 PacedSender::PacedSender(Callback* callback, int target_bitrate_kbps,
120 float pace_multiplier)
121 : callback_(callback),
122 pace_multiplier_(pace_multiplier),
125 critsect_(CriticalSectionWrapper::CreateCriticalSection()),
126 media_budget_(new paced_sender::IntervalBudget(
127 pace_multiplier_ * target_bitrate_kbps)),
128 padding_budget_(new paced_sender::IntervalBudget(0)),
129 // No padding until UpdateBitrate is called.
130 pad_up_to_bitrate_budget_(new paced_sender::IntervalBudget(0)),
131 time_last_update_(TickTime::Now()),
132 capture_time_ms_last_queued_(0),
133 capture_time_ms_last_sent_(0),
134 high_priority_packets_(new paced_sender::PacketList),
135 normal_priority_packets_(new paced_sender::PacketList),
136 low_priority_packets_(new paced_sender::PacketList) {
137 UpdateBytesPerInterval(kMinPacketLimitMs);
140 PacedSender::~PacedSender() {
143 void PacedSender::Pause() {
144 CriticalSectionScoped cs(critsect_.get());
148 void PacedSender::Resume() {
149 CriticalSectionScoped cs(critsect_.get());
153 void PacedSender::SetStatus(bool enable) {
154 CriticalSectionScoped cs(critsect_.get());
158 bool PacedSender::Enabled() const {
159 CriticalSectionScoped cs(critsect_.get());
163 void PacedSender::UpdateBitrate(int target_bitrate_kbps,
164 int max_padding_bitrate_kbps,
165 int pad_up_to_bitrate_kbps) {
166 CriticalSectionScoped cs(critsect_.get());
167 media_budget_->set_target_rate_kbps(pace_multiplier_ * target_bitrate_kbps);
168 padding_budget_->set_target_rate_kbps(max_padding_bitrate_kbps);
169 pad_up_to_bitrate_budget_->set_target_rate_kbps(pad_up_to_bitrate_kbps);
172 bool PacedSender::SendPacket(Priority priority, uint32_t ssrc,
173 uint16_t sequence_number, int64_t capture_time_ms, int bytes) {
174 CriticalSectionScoped cs(critsect_.get());
177 return true; // We can send now.
179 if (capture_time_ms < 0) {
180 capture_time_ms = TickTime::MillisecondTimestamp();
182 if (priority != kHighPriority &&
183 capture_time_ms > capture_time_ms_last_queued_) {
184 capture_time_ms_last_queued_ = capture_time_ms;
185 TRACE_EVENT_ASYNC_BEGIN1("webrtc_rtp", "PacedSend", capture_time_ms,
186 "capture_time_ms", capture_time_ms);
188 paced_sender::PacketList* packet_list = NULL;
191 packet_list = high_priority_packets_.get();
193 case kNormalPriority:
194 packet_list = normal_priority_packets_.get();
197 packet_list = low_priority_packets_.get();
200 packet_list->push_back(paced_sender::Packet(ssrc, sequence_number,
201 capture_time_ms, bytes));
205 int PacedSender::QueueInMs() const {
206 CriticalSectionScoped cs(critsect_.get());
207 int64_t now_ms = TickTime::MillisecondTimestamp();
208 int64_t oldest_packet_capture_time = now_ms;
209 if (!high_priority_packets_->empty()) {
210 oldest_packet_capture_time = std::min(
211 oldest_packet_capture_time,
212 high_priority_packets_->front().capture_time_ms_);
214 if (!normal_priority_packets_->empty()) {
215 oldest_packet_capture_time = std::min(
216 oldest_packet_capture_time,
217 normal_priority_packets_->front().capture_time_ms_);
219 if (!low_priority_packets_->empty()) {
220 oldest_packet_capture_time = std::min(
221 oldest_packet_capture_time,
222 low_priority_packets_->front().capture_time_ms_);
224 return now_ms - oldest_packet_capture_time;
227 int32_t PacedSender::TimeUntilNextProcess() {
228 CriticalSectionScoped cs(critsect_.get());
229 int64_t elapsed_time_ms =
230 (TickTime::Now() - time_last_update_).Milliseconds();
231 if (elapsed_time_ms <= 0) {
232 return kMinPacketLimitMs;
234 if (elapsed_time_ms >= kMinPacketLimitMs) {
237 return kMinPacketLimitMs - elapsed_time_ms;
240 int32_t PacedSender::Process() {
241 TickTime now = TickTime::Now();
242 CriticalSectionScoped cs(critsect_.get());
243 int elapsed_time_ms = (now - time_last_update_).Milliseconds();
244 time_last_update_ = now;
249 if (elapsed_time_ms > 0) {
250 uint32_t delta_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms);
251 UpdateBytesPerInterval(delta_time_ms);
254 uint16_t sequence_number;
255 int64_t capture_time_ms;
256 paced_sender::PacketList* packet_list;
257 while (ShouldSendNextPacket(&packet_list)) {
258 GetNextPacketFromList(packet_list, &ssrc, &sequence_number,
262 const bool success = callback_->TimeToSendPacket(ssrc, sequence_number,
265 // If packet cannot be sent then keep it in packet list and exit early.
266 // There's no need to send more packets.
270 packet_list->pop_front();
271 const bool last_packet = packet_list->empty() ||
272 packet_list->front().capture_time_ms_ > capture_time_ms;
273 if (packet_list != high_priority_packets_.get()) {
274 if (capture_time_ms > capture_time_ms_last_sent_) {
275 capture_time_ms_last_sent_ = capture_time_ms;
276 } else if (capture_time_ms == capture_time_ms_last_sent_ &&
278 TRACE_EVENT_ASYNC_END0("webrtc_rtp", "PacedSend", capture_time_ms);
282 if (high_priority_packets_->empty() &&
283 normal_priority_packets_->empty() &&
284 low_priority_packets_->empty() &&
285 padding_budget_->bytes_remaining() > 0 &&
286 pad_up_to_bitrate_budget_->bytes_remaining() > 0) {
287 int padding_needed = std::min(
288 padding_budget_->bytes_remaining(),
289 pad_up_to_bitrate_budget_->bytes_remaining());
291 int bytes_sent = callback_->TimeToSendPadding(padding_needed);
293 media_budget_->UseBudget(bytes_sent);
294 padding_budget_->UseBudget(bytes_sent);
295 pad_up_to_bitrate_budget_->UseBudget(bytes_sent);
301 // MUST have critsect_ when calling.
302 void PacedSender::UpdateBytesPerInterval(uint32_t delta_time_ms) {
303 media_budget_->IncreaseBudget(delta_time_ms);
304 padding_budget_->IncreaseBudget(delta_time_ms);
305 pad_up_to_bitrate_budget_->IncreaseBudget(delta_time_ms);
308 // MUST have critsect_ when calling.
309 bool PacedSender::ShouldSendNextPacket(paced_sender::PacketList** packet_list) {
310 if (media_budget_->bytes_remaining() <= 0) {
311 // All bytes consumed for this interval.
312 // Check if we have not sent in a too long time.
313 if ((TickTime::Now() - time_last_send_).Milliseconds() >
314 kMaxQueueTimeWithoutSendingMs) {
315 if (!high_priority_packets_->empty()) {
316 *packet_list = high_priority_packets_.get();
319 if (!normal_priority_packets_->empty()) {
320 *packet_list = normal_priority_packets_.get();
326 if (!high_priority_packets_->empty()) {
327 *packet_list = high_priority_packets_.get();
330 if (!normal_priority_packets_->empty()) {
331 *packet_list = normal_priority_packets_.get();
334 if (!low_priority_packets_->empty()) {
335 *packet_list = low_priority_packets_.get();
341 void PacedSender::GetNextPacketFromList(paced_sender::PacketList* packets,
342 uint32_t* ssrc, uint16_t* sequence_number, int64_t* capture_time_ms) {
343 paced_sender::Packet packet = packets->front();
344 UpdateMediaBytesSent(packet.bytes_);
345 *sequence_number = packet.sequence_number_;
346 *ssrc = packet.ssrc_;
347 *capture_time_ms = packet.capture_time_ms_;
350 // MUST have critsect_ when calling.
351 void PacedSender::UpdateMediaBytesSent(int num_bytes) {
352 time_last_send_ = TickTime::Now();
353 media_budget_->UseBudget(num_bytes);
354 pad_up_to_bitrate_budget_->UseBudget(num_bytes);
357 } // namespace webrtc