Commit 1f663f57 authored by hubbe's avatar hubbe Committed by Commit bot

Cast: Make pacing controllable by the extension

Use are brand-spanking-new options dictionary to be able to configure
the target and max burst size for the pacer. This should allow us to do
some basic experiments to determine if pacing is really helpful and what
the optimal batch size actually is.

Review URL: https://codereview.chromium.org/567853002

Cr-Commit-Position: refs/heads/master@{#294657}
parent 5652d00e
......@@ -14,6 +14,20 @@
namespace media {
namespace cast {
namespace {
int LookupOptionWithDefault(const base::DictionaryValue& options,
const std::string& path,
int default_value) {
int ret;
if (options.GetInteger(path, &ret)) {
return ret;
} else {
return default_value;
}
};
} // namespace
scoped_ptr<CastTransportSender> CastTransportSender::Create(
net::NetLog* net_log,
base::TickClock* clock,
......@@ -58,7 +72,13 @@ CastTransportSenderImpl::CastTransportSenderImpl(
net::IPEndPoint(),
remote_end_point,
status_callback)),
pacer_(clock,
pacer_(LookupOptionWithDefault(*options.get(),
"pacer_target_burst_size",
kTargetBurstSize),
LookupOptionWithDefault(*options.get(),
"pacer_max_burst_size",
kMaxBurstSize),
clock,
&logging_,
external_transport ? external_transport : transport_.get(),
transport_task_runner),
......
......@@ -54,6 +54,13 @@ class CastTransportSenderImpl : public CastTransportSender {
// This can be a null callback, i.e. if user is not interested in raw events.
// |raw_events_callback_interval|: This can be |base::TimeDelta()| if
// |raw_events_callback| is a null callback.
// |options| contains optional settings for the transport, possible
// keys are:
// "DSCP" (value doesn't matter) - turns DSCP on
// "pacer_target_burst_size": int - specifies how many packets to send
// per 10 ms ideally.
// "pacer_max_burst_size": int - specifies how many pakcets to send
// per 10 ms, max
CastTransportSenderImpl(
net::NetLog* net_log,
base::TickClock* clock,
......
......@@ -18,15 +18,8 @@ static const int64 kPacingIntervalMs = 10;
// Each frame will be split into no more than kPacingMaxBurstsPerFrame
// bursts of packets.
static const size_t kPacingMaxBurstsPerFrame = 3;
static const size_t kTargetBurstSize = 10;
static const size_t kMaxBurstSize = 20;
static const size_t kMaxDedupeWindowMs = 500;
// Number of packets that we keep the information of sent time and sent bytes.
// This number allows 0.5 seconds of history if sending at maximum rate.
static const size_t kPacketHistorySize =
kMaxBurstSize * kMaxDedupeWindowMs / kPacingIntervalMs;
} // namespace
DedupInfo::DedupInfo() : last_byte_acked_for_audio(0) {}
......@@ -42,6 +35,8 @@ PacedSender::PacketSendRecord::PacketSendRecord()
: last_byte_sent(0), last_byte_sent_for_audio(0) {}
PacedSender::PacedSender(
size_t target_burst_size,
size_t max_burst_size,
base::TickClock* clock,
LoggingImpl* logging,
PacketSender* transport,
......@@ -52,9 +47,11 @@ PacedSender::PacedSender(
transport_task_runner_(transport_task_runner),
audio_ssrc_(0),
video_ssrc_(0),
max_burst_size_(kTargetBurstSize),
next_max_burst_size_(kTargetBurstSize),
next_next_max_burst_size_(kTargetBurstSize),
target_burst_size_(target_burst_size),
max_burst_size_(max_burst_size),
current_max_burst_size_(target_burst_size_),
next_max_burst_size_(target_burst_size_),
next_next_max_burst_size_(target_burst_size_),
current_burst_size_(0),
state_(State_Unblocked),
weak_factory_(this) {
......@@ -245,8 +242,8 @@ void PacedSender::SendStoredPackets() {
// which is more bandwidth than the cast library should need, and sending
// out more data per second is unlikely to be helpful.
size_t max_burst_size = std::min(
kMaxBurstSize,
std::max(kTargetBurstSize, size() / kPacingMaxBurstsPerFrame));
max_burst_size_,
std::max(target_burst_size_, size() / kPacingMaxBurstsPerFrame));
// If the queue is long, issue a warning. Try to limit the number of
// warnings issued by only issuing the warning when the burst size
......@@ -255,7 +252,7 @@ void PacedSender::SendStoredPackets() {
LOG(WARNING) << "Packet queue is very long:" << size();
}
max_burst_size_ = std::max(next_max_burst_size_, max_burst_size);
current_max_burst_size_ = std::max(next_max_burst_size_, max_burst_size);
next_max_burst_size_ = std::max(next_next_max_burst_size_, max_burst_size);
next_next_max_burst_size_ = max_burst_size;
}
......@@ -263,7 +260,7 @@ void PacedSender::SendStoredPackets() {
base::Closure cb = base::Bind(&PacedSender::SendStoredPackets,
weak_factory_.GetWeakPtr());
while (!empty()) {
if (current_burst_size_ >= max_burst_size_) {
if (current_burst_size_ >= current_max_burst_size_) {
transport_task_runner_->PostDelayedTask(FROM_HERE,
cb,
burst_end_ - now);
......@@ -304,11 +301,13 @@ void PacedSender::SendStoredPackets() {
}
// Keep ~0.5 seconds of data (1000 packets).
if (send_history_buffer_.size() >= kPacketHistorySize) {
if (send_history_buffer_.size() >=
max_burst_size_ * kMaxDedupeWindowMs / kPacingIntervalMs) {
send_history_.swap(send_history_buffer_);
send_history_buffer_.clear();
}
DCHECK_LE(send_history_buffer_.size(), kPacketHistorySize);
DCHECK_LE(send_history_buffer_.size(),
max_burst_size_ * kMaxDedupeWindowMs / kPacingIntervalMs);
state_ = State_Unblocked;
}
......
......@@ -22,6 +22,10 @@
namespace media {
namespace cast {
// Meant to use as defaults for pacer construction.
static const size_t kTargetBurstSize = 10;
static const size_t kMaxBurstSize = 20;
class LoggingImpl;
// Use std::pair for free comparison operators.
......@@ -78,6 +82,8 @@ class PacedSender : public PacedPacketSender,
// The |external_transport| should only be used by the Cast receiver and for
// testing.
PacedSender(
size_t target_burst_size, // Should normally be kTargetBurstSize.
size_t max_burst_size, // Should normally be kMaxBurstSize.
base::TickClock* clock,
LoggingImpl* logging,
PacketSender* external_transport,
......@@ -185,8 +191,11 @@ class PacedSender : public PacedPacketSender,
// Records the last byte sent for payload with a specific SSRC.
std::map<uint32, int64> last_byte_sent_;
// Maximum burst size for the next three bursts.
size_t target_burst_size_;
size_t max_burst_size_;
// Maximum burst size for the next three bursts.
size_t current_max_burst_size_;
size_t next_max_burst_size_;
size_t next_next_max_burst_size_;
// Number of packets already sent in the current burst.
......
......@@ -65,8 +65,12 @@ class PacedSenderTest : public ::testing::Test {
testing_clock_.Advance(
base::TimeDelta::FromMilliseconds(kStartMillisecond));
task_runner_ = new test::FakeSingleThreadTaskRunner(&testing_clock_);
paced_sender_.reset(new PacedSender(
&testing_clock_, &logging_, &mock_transport_, task_runner_));
paced_sender_.reset(new PacedSender(kTargetBurstSize,
kMaxBurstSize,
&testing_clock_,
&logging_,
&mock_transport_,
task_runner_));
paced_sender_->RegisterAudioSsrc(kAudioSsrc);
paced_sender_->RegisterVideoSsrc(kVideoSsrc);
}
......
......@@ -110,8 +110,12 @@ class RtpPacketizerTest : public ::testing::Test {
config_.payload_type = kPayload;
config_.max_payload_length = kMaxPacketLength;
transport_.reset(new TestRtpPacketTransport(config_));
pacer_.reset(new PacedSender(
&testing_clock_, &logging_, transport_.get(), task_runner_));
pacer_.reset(new PacedSender(kTargetBurstSize,
kMaxBurstSize,
&testing_clock_,
&logging_,
transport_.get(),
task_runner_));
pacer_->RegisterVideoSsrc(config_.ssrc);
rtp_packetizer_.reset(new RtpPacketizer(
pacer_.get(), &packet_storage_, config_));
......
......@@ -31,7 +31,9 @@ CastReceiverImpl::CastReceiverImpl(
const FrameReceiverConfig& video_config,
PacketSender* const packet_sender)
: cast_environment_(cast_environment),
pacer_(cast_environment->Clock(),
pacer_(kTargetBurstSize,
kMaxBurstSize,
cast_environment->Clock(),
cast_environment->Logging(),
packet_sender,
cast_environment->GetTaskRunner(CastEnvironment::MAIN)),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment