Files
platform-external-webrtc/webrtc/modules/pacing/bitrate_prober.cc
kwiberg af476c737f RTC_[D]CHECK_op: Remove "u" suffix on integer constants
There's no longer any need to make the two arguments have the same
signedness, so we can drop the "u" suffix on literal integer
arguments.

NOPRESUBMIT=true
BUG=webrtc:6645

Review-Url: https://codereview.webrtc.org/2535593002
Cr-Commit-Position: refs/heads/master@{#15280}
2016-11-28 23:21:51 +00:00

169 lines
5.5 KiB
C++

/*
* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/pacing/bitrate_prober.h"
#include <algorithm>
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/modules/pacing/paced_sender.h"
namespace webrtc {
namespace {
// Inactivity threshold above which probing is restarted.
constexpr int kInactivityThresholdMs = 5000;
// A minimum interval between probes to allow scheduling to be feasible.
constexpr int kMinProbeDeltaMs = 1;
int ComputeDeltaFromBitrate(size_t probe_size, uint32_t bitrate_bps) {
RTC_CHECK_GT(bitrate_bps, 0);
// Compute the time delta needed to send probe_size bytes at bitrate_bps
// bps. Result is in milliseconds.
return static_cast<int>((1000ll * probe_size * 8) / bitrate_bps);
}
} // namespace
BitrateProber::BitrateProber()
: probing_state_(ProbingState::kDisabled),
probe_size_last_sent_(0),
time_last_probe_sent_ms_(-1),
next_cluster_id_(0) {
SetEnabled(true);
}
void BitrateProber::SetEnabled(bool enable) {
if (enable) {
if (probing_state_ == ProbingState::kDisabled) {
probing_state_ = ProbingState::kInactive;
LOG(LS_INFO) << "Bandwidth probing enabled, set to inactive";
}
} else {
probing_state_ = ProbingState::kDisabled;
LOG(LS_INFO) << "Bandwidth probing disabled";
}
}
bool BitrateProber::IsProbing() const {
return probing_state_ == ProbingState::kActive;
}
void BitrateProber::OnIncomingPacket(size_t packet_size) {
// Don't initialize probing unless we have something large enough to start
// probing.
if (probing_state_ == ProbingState::kInactive &&
!clusters_.empty() &&
packet_size >= PacedSender::kMinProbePacketSize) {
probing_state_ = ProbingState::kActive;
}
}
void BitrateProber::CreateProbeCluster(int bitrate_bps, int num_probes) {
RTC_DCHECK(probing_state_ != ProbingState::kDisabled);
ProbeCluster cluster;
cluster.max_probes = num_probes;
cluster.probe_bitrate_bps = bitrate_bps;
cluster.id = next_cluster_id_++;
clusters_.push(cluster);
LOG(LS_INFO) << "Probe cluster (bitrate:probes): ("
<< cluster.probe_bitrate_bps << ":" << cluster.max_probes
<< ") ";
if (probing_state_ != ProbingState::kActive)
probing_state_ = ProbingState::kInactive;
}
void BitrateProber::ResetState() {
time_last_probe_sent_ms_ = -1;
probe_size_last_sent_ = 0;
// Recreate all probing clusters.
std::queue<ProbeCluster> clusters;
clusters.swap(clusters_);
while (!clusters.empty()) {
CreateProbeCluster(clusters.front().probe_bitrate_bps,
clusters.front().max_probes);
clusters.pop();
}
// If its enabled, reset to inactive.
if (probing_state_ != ProbingState::kDisabled)
probing_state_ = ProbingState::kInactive;
}
int BitrateProber::TimeUntilNextProbe(int64_t now_ms) {
// Probing is not active or probing is already complete.
if (probing_state_ != ProbingState::kActive || clusters_.empty())
return -1;
// time_last_probe_sent_ms_ of -1 indicates no probes have yet been sent.
int64_t elapsed_time_ms;
if (time_last_probe_sent_ms_ == -1) {
elapsed_time_ms = 0;
} else {
elapsed_time_ms = now_ms - time_last_probe_sent_ms_;
}
// If no probes have been sent for a while, abort current probing and
// reset.
if (elapsed_time_ms > kInactivityThresholdMs) {
ResetState();
return -1;
}
// We will send the first probe packet immediately if no packet has been
// sent before.
int time_until_probe_ms = 0;
if (probe_size_last_sent_ != 0 && probing_state_ == ProbingState::kActive) {
int next_delta_ms = ComputeDeltaFromBitrate(
probe_size_last_sent_, clusters_.front().probe_bitrate_bps);
time_until_probe_ms = next_delta_ms - elapsed_time_ms;
// If we have waited more than 3 ms for a new packet to probe with we will
// consider this probing session over.
const int kMaxProbeDelayMs = 3;
if (next_delta_ms < kMinProbeDeltaMs ||
time_until_probe_ms < -kMaxProbeDelayMs) {
probing_state_ = ProbingState::kSuspended;
LOG(LS_INFO) << "Delta too small or missed probing accurately, suspend";
time_until_probe_ms = 0;
}
}
return std::max(time_until_probe_ms, 0);
}
int BitrateProber::CurrentClusterId() const {
RTC_DCHECK(!clusters_.empty());
RTC_DCHECK(ProbingState::kActive == probing_state_);
return clusters_.front().id;
}
// Probe size is recommended based on the probe bitrate required. We choose
// a minimum of twice |kMinProbeDeltaMs| interval to allow scheduling to be
// feasible.
size_t BitrateProber::RecommendedMinProbeSize() const {
RTC_DCHECK(!clusters_.empty());
return clusters_.front().probe_bitrate_bps * 2 * kMinProbeDeltaMs /
(8 * 1000);
}
void BitrateProber::ProbeSent(int64_t now_ms, size_t bytes) {
RTC_DCHECK(probing_state_ == ProbingState::kActive);
RTC_DCHECK_GT(bytes, 0);
probe_size_last_sent_ = bytes;
time_last_probe_sent_ms_ = now_ms;
if (!clusters_.empty()) {
ProbeCluster* cluster = &clusters_.front();
++cluster->sent_probes;
if (cluster->sent_probes == cluster->max_probes)
clusters_.pop();
if (clusters_.empty())
probing_state_ = ProbingState::kSuspended;
}
}
} // namespace webrtc