Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(511)

Unified Diff: webrtc/modules/pacing/paced_sender.cc

Issue 1412293003: Allow pacer to boost bitrate in order to meet time constraints. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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));

Powered by Google App Engine
This is Rietveld 408576698