diff options
Diffstat (limited to 'webrtc/modules/pacing/bitrate_prober.cc')
-rw-r--r-- | webrtc/modules/pacing/bitrate_prober.cc | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/webrtc/modules/pacing/bitrate_prober.cc b/webrtc/modules/pacing/bitrate_prober.cc new file mode 100644 index 0000000000..bbbe54f54e --- /dev/null +++ b/webrtc/modules/pacing/bitrate_prober.cc @@ -0,0 +1,129 @@ +/* + * 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/modules/pacing/include/paced_sender.h" +#include "webrtc/system_wrappers/include/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 + +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_ > PacedSender::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 |