Files
platform-external-webrtc/webrtc/modules/pacing/bitrate_prober.cc
stefan fe0c90501b Improve probing by ignoring small packets which otherwise break the mechanism.
These small packets are common for H.264 where the first packet of an IDR
contains the parameter sets.

BUG=4806

Review URL: https://codereview.webrtc.org/1221943002

Cr-Commit-Position: refs/heads/master@{#9639}
2015-07-27 10:13:35 +00:00

131 lines
4.3 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 <assert.h>
#include <algorithm>
#include <limits>
#include <sstream>
#include "webrtc/system_wrappers/interface/logging.h"
namespace webrtc {
namespace {
int ComputeDeltaFromBitrate(size_t packet_size, int bitrate_bps) {
assert(bitrate_bps > 0);
// Compute the time delta needed to send packet_size bytes at bitrate_bps
// bps. Result is in milliseconds.
return static_cast<int>(1000ll * static_cast<int64_t>(packet_size) * 8ll /
bitrate_bps);
}
} // namespace
const size_t BitrateProber::kMinProbePacketSize = 200;
BitrateProber::BitrateProber()
: probing_state_(kDisabled),
packet_size_last_send_(0),
time_last_send_ms_(-1) {
}
void BitrateProber::SetEnabled(bool enable) {
if (enable) {
if (probing_state_ == kDisabled) {
probing_state_ = kAllowedToProbe;
LOG(LS_INFO) << "Initial bandwidth probing enabled";
}
} else {
probing_state_ = kDisabled;
LOG(LS_INFO) << "Initial bandwidth probing disabled";
}
}
bool BitrateProber::IsProbing() const {
return probing_state_ == kProbing;
}
void BitrateProber::MaybeInitializeProbe(int bitrate_bps) {
if (probing_state_ != kAllowedToProbe)
return;
probe_bitrates_.clear();
// Max number of packets used for probing.
const int kMaxNumProbes = 2;
const int kPacketsPerProbe = 5;
const float kProbeBitrateMultipliers[kMaxNumProbes] = {3, 6};
int bitrates_bps[kMaxNumProbes];
std::stringstream bitrate_log;
bitrate_log << "Start probing for bandwidth, bitrates:";
for (int i = 0; i < kMaxNumProbes; ++i) {
bitrates_bps[i] = kProbeBitrateMultipliers[i] * bitrate_bps;
bitrate_log << " " << bitrates_bps[i];
// We need one extra to get 5 deltas for the first probe.
if (i == 0)
probe_bitrates_.push_back(bitrates_bps[i]);
for (int j = 0; j < kPacketsPerProbe; ++j)
probe_bitrates_.push_back(bitrates_bps[i]);
}
bitrate_log << ", num packets: " << probe_bitrates_.size();
LOG(LS_INFO) << bitrate_log.str().c_str();
probing_state_ = kProbing;
}
int BitrateProber::TimeUntilNextProbe(int64_t now_ms) {
if (probing_state_ != kDisabled && probe_bitrates_.empty()) {
probing_state_ = kWait;
}
if (probe_bitrates_.empty()) {
// No probe started, or waiting for next probe.
return -1;
}
int64_t elapsed_time_ms = now_ms - time_last_send_ms_;
// We will send the first probe packet immediately if no packet has been
// sent before.
int time_until_probe_ms = 0;
if (packet_size_last_send_ > kMinProbePacketSize &&
probing_state_ == kProbing) {
int next_delta_ms = ComputeDeltaFromBitrate(packet_size_last_send_,
probe_bitrates_.front());
time_until_probe_ms = next_delta_ms - elapsed_time_ms;
// There is no point in trying to probe with less than 1 ms between packets
// as it essentially means trying to probe at infinite bandwidth.
const int kMinProbeDeltaMs = 1;
// 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) {
// We currently disable probing after the first probe, as we only want
// to probe at the beginning of a connection. We should set this to
// kWait if we later want to probe periodically.
probing_state_ = kWait;
LOG(LS_INFO) << "Next delta too small, stop probing.";
time_until_probe_ms = 0;
}
}
return std::max(time_until_probe_ms, 0);
}
size_t BitrateProber::RecommendedPacketSize() const {
return packet_size_last_send_;
}
void BitrateProber::PacketSent(int64_t now_ms, size_t packet_size) {
assert(packet_size > 0);
packet_size_last_send_ = packet_size;
time_last_send_ms_ = now_ms;
if (probing_state_ != kProbing)
return;
if (!probe_bitrates_.empty())
probe_bitrates_.pop_front();
}
} // namespace webrtc