Index: webrtc/modules/pacing/paced_sender.cc |
diff --git a/webrtc/modules/pacing/paced_sender.cc b/webrtc/modules/pacing/paced_sender.cc |
index 6a7d19a25169f7d3ca45d7a8057619d35c9aef9f..44126e2edaac11e9b3d42394e28e42c86be0dfc6 100644 |
--- a/webrtc/modules/pacing/paced_sender.cc |
+++ b/webrtc/modules/pacing/paced_sender.cc |
@@ -10,12 +10,11 @@ |
#include "webrtc/modules/pacing/include/paced_sender.h" |
-#include <assert.h> |
- |
#include <map> |
#include <queue> |
#include <set> |
+#include "webrtc/base/checks.h" |
#include "webrtc/modules/interface/module_common_types.h" |
#include "webrtc/modules/pacing/bitrate_prober.h" |
#include "webrtc/system_wrappers/interface/clock.h" |
@@ -147,7 +146,7 @@ class PacketQueue { |
void RemoveFromDupeSet(const Packet& packet) { |
SsrcSeqNoMap::iterator it = dupe_map_.find(packet.ssrc); |
- assert(it != dupe_map_.end()); |
+ RTC_DCHECK(it != dupe_map_.end()); |
it->second.erase(packet.sequence_number); |
if (it->second.empty()) { |
dupe_map_.erase(it); |
@@ -209,6 +208,7 @@ class IntervalBudget { |
}; |
} // namespace paced_sender |
+const int64_t PacedSender::kMaxQueueLengthMs = 2000; |
const float PacedSender::kDefaultPaceMultiplier = 2.5f; |
PacedSender::PacedSender(Clock* clock, |
@@ -225,6 +225,8 @@ PacedSender::PacedSender(Clock* clock, |
padding_budget_(new paced_sender::IntervalBudget(min_bitrate_kbps)), |
prober_(new BitrateProber()), |
bitrate_bps_(1000 * bitrate_kbps), |
+ max_bitrate_kbps_(max_bitrate_kbps), |
+ bitrate_boost_start_us_(-1), |
time_last_update_us_(clock->TimeInMicroseconds()), |
packets_(new paced_sender::PacketQueue()), |
packet_counter_(0) { |
@@ -244,7 +246,7 @@ void PacedSender::Resume() { |
} |
void PacedSender::SetProbingEnabled(bool enabled) { |
- assert(packet_counter_ == 0); |
+ RTC_CHECK_EQ(0u, packet_counter_); |
probing_enabled_ = enabled; |
} |
@@ -252,9 +254,14 @@ void PacedSender::UpdateBitrate(int bitrate_kbps, |
int max_bitrate_kbps, |
int min_bitrate_kbps) { |
CriticalSectionScoped cs(critsect_.get()); |
- media_budget_->set_target_rate_kbps(max_bitrate_kbps); |
+ if (bitrate_boost_start_us_ == -1 || |
+ max_bitrate_kbps > media_budget_->target_rate_kbps()) { |
+ media_budget_->set_target_rate_kbps(max_bitrate_kbps); |
+ bitrate_boost_start_us_ = -1; |
+ } |
padding_budget_->set_target_rate_kbps(min_bitrate_kbps); |
bitrate_bps_ = 1000 * bitrate_kbps; |
+ max_bitrate_kbps_ = max_bitrate_kbps; |
} |
void PacedSender::InsertPacket(RtpPacketSender::Priority priority, |
@@ -265,14 +272,12 @@ void PacedSender::InsertPacket(RtpPacketSender::Priority priority, |
bool retransmission) { |
CriticalSectionScoped cs(critsect_.get()); |
- if (probing_enabled_ && !prober_->IsProbing()) { |
+ if (probing_enabled_ && !prober_->IsProbing()) |
prober_->SetEnabled(true); |
- } |
prober_->MaybeInitializeProbe(bitrate_bps_); |
- if (capture_time_ms < 0) { |
+ if (capture_time_ms < 0) |
capture_time_ms = clock_->TimeInMilliseconds(); |
- } |
packets_->Push(paced_sender::Packet( |
priority, ssrc, sequence_number, capture_time_ms, |
@@ -281,9 +286,8 @@ void PacedSender::InsertPacket(RtpPacketSender::Priority priority, |
int64_t PacedSender::ExpectedQueueTimeMs() const { |
CriticalSectionScoped cs(critsect_.get()); |
- int target_rate = media_budget_->target_rate_kbps(); |
- assert(target_rate > 0); |
- return static_cast<int64_t>(packets_->SizeInBytes() * 8 / target_rate); |
+ RTC_DCHECK_GT(max_bitrate_kbps_, 0); |
+ return static_cast<int64_t>(packets_->SizeInBytes() * 8 / max_bitrate_kbps_); |
} |
size_t PacedSender::QueueSizePackets() const { |
@@ -305,9 +309,8 @@ int64_t PacedSender::TimeUntilNextProcess() { |
CriticalSectionScoped cs(critsect_.get()); |
if (prober_->IsProbing()) { |
int64_t ret = prober_->TimeUntilNextProbe(clock_->TimeInMilliseconds()); |
- if (ret >= 0) { |
+ if (ret >= 0) |
return ret; |
- } |
} |
int64_t elapsed_time_us = clock_->TimeInMicroseconds() - time_last_update_us_; |
int64_t elapsed_time_ms = (elapsed_time_us + 500) / 1000; |
@@ -322,13 +325,34 @@ int32_t PacedSender::Process() { |
if (paused_) |
return 0; |
if (elapsed_time_ms > 0) { |
+ if (bitrate_boost_start_us_ != -1 && |
stefan-webrtc
2015/10/28 15:45:23
Is the bitrate_boost_start_us_ really needed? Can'
sprang_webrtc
2015/11/02 12:17:56
This was how I first implemented it, and it turns
stefan-webrtc
2015/11/10 14:57:02
This isn't correct I think. Those 500 bytes have b
stefan-webrtc
2015/11/10 14:59:44
And something similar could be done when a packet
sprang_webrtc
2015/11/19 10:21:48
This method won't work quite right either, since w
|
+ (now_us - bitrate_boost_start_us_) > kMaxQueueLengthMs * 1000) { |
+ // Boost period is up, reset to nominal bitrate. |
+ media_budget_->set_target_rate_kbps(max_bitrate_kbps_); |
+ bitrate_boost_start_us_ = -1; |
+ } |
+ |
+ int64_t expected_queue_length_ms = |
+ static_cast<int64_t>(packets_->SizeInBytes() * 8 / max_bitrate_kbps_); |
stefan-webrtc
2015/10/28 15:45:23
Call ExpectedQueueTimeMs() instead.
sprang_webrtc
2015/11/02 12:17:56
Sure. Or do we care about recursively taking locks
stefan-webrtc
2015/11/10 14:57:02
I would prefer to not take them recursively. Just
|
+ if (expected_queue_length_ms > kMaxQueueLengthMs) { |
+ // Too much data has been put in the pacer queue, or the target bitrate |
+ // has suddenly decreased, making the expected max pacer delay too long. |
+ // Boost the media target bitrate so that all data should have left the |
+ // queue within kDefaultMaxQueueLengthMs. |
+ int required_bitrate_kbps = |
+ expected_queue_length_ms * max_bitrate_kbps_ / kMaxQueueLengthMs; |
+ if (required_bitrate_kbps > media_budget_->target_rate_kbps()) { |
+ media_budget_->set_target_rate_kbps(required_bitrate_kbps); |
+ bitrate_boost_start_us_ = now_us; |
+ } |
+ } |
+ |
int64_t delta_time_ms = std::min(kMaxIntervalTimeMs, elapsed_time_ms); |
UpdateBytesPerInterval(delta_time_ms); |
} |
while (!packets_->Empty()) { |
- if (media_budget_->bytes_remaining() == 0 && !prober_->IsProbing()) { |
+ if (media_budget_->bytes_remaining() == 0 && !prober_->IsProbing()) |
return 0; |
- } |
// Since we need to release the lock in order to send, we first pop the |
// element from the priority queue but keep it in storage, so that we can |
@@ -337,9 +361,8 @@ int32_t PacedSender::Process() { |
if (SendPacket(packet)) { |
// Send succeeded, remove it from the queue. |
packets_->FinalizePop(packet); |
- if (prober_->IsProbing()) { |
+ if (prober_->IsProbing()) |
return 0; |
- } |
} else { |
// Send failed, put it back into the queue. |
packets_->CancelPop(packet); |
@@ -351,10 +374,11 @@ int32_t PacedSender::Process() { |
return 0; |
size_t padding_needed; |
- if (prober_->IsProbing()) |
+ if (prober_->IsProbing()) { |
padding_needed = prober_->RecommendedPacketSize(); |
- else |
+ } else { |
padding_needed = padding_budget_->bytes_remaining(); |
+ } |
if (padding_needed > 0) |
SendPadding(static_cast<size_t>(padding_needed)); |