tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

bitrate_prober.cc (7448B)


      1 /*
      2 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/pacing/bitrate_prober.h"
     12 
     13 #include <algorithm>
     14 #include <cstddef>
     15 #include <optional>
     16 
     17 #include "api/field_trials_view.h"
     18 #include "api/transport/network_types.h"
     19 #include "api/units/data_rate.h"
     20 #include "api/units/data_size.h"
     21 #include "api/units/time_delta.h"
     22 #include "api/units/timestamp.h"
     23 #include "rtc_base/checks.h"
     24 #include "rtc_base/experiments/field_trial_parser.h"
     25 #include "rtc_base/logging.h"
     26 
     27 namespace webrtc {
     28 
     29 namespace {
     30 constexpr TimeDelta kProbeClusterTimeout = TimeDelta::Seconds(5);
     31 constexpr size_t kMaxPendingProbeClusters = 5;
     32 
     33 }  // namespace
     34 
     35 BitrateProberConfig::BitrateProberConfig(
     36    const FieldTrialsView* key_value_config)
     37    : max_probe_delay("max_probe_delay", TimeDelta::Millis(10)),
     38      min_packet_size("min_packet_size", DataSize::Bytes(200)) {
     39  ParseFieldTrial({&max_probe_delay, &min_packet_size},
     40                  key_value_config->Lookup("WebRTC-Bwe-ProbingBehavior"));
     41 }
     42 
     43 BitrateProber::BitrateProber(const FieldTrialsView& field_trials)
     44    : probing_state_(ProbingState::kDisabled),
     45      next_probe_time_(Timestamp::PlusInfinity()),
     46      config_(&field_trials) {
     47  SetEnabled(true);
     48 }
     49 
     50 void BitrateProber::SetEnabled(bool enable) {
     51  if (enable) {
     52    if (probing_state_ == ProbingState::kDisabled) {
     53      probing_state_ = ProbingState::kInactive;
     54      RTC_LOG(LS_INFO) << "Bandwidth probing enabled, set to inactive";
     55    }
     56  } else {
     57    probing_state_ = ProbingState::kDisabled;
     58    RTC_LOG(LS_INFO) << "Bandwidth probing disabled";
     59  }
     60 }
     61 
     62 void BitrateProber::SetAllowProbeWithoutMediaPacket(bool allow) {
     63  config_.allow_start_probing_immediately = allow;
     64  MaybeSetActiveState(/*packet_size=*/DataSize::Zero());
     65 }
     66 
     67 void BitrateProber::MaybeSetActiveState(DataSize packet_size) {
     68  if (ReadyToSetActiveState(packet_size)) {
     69    next_probe_time_ = Timestamp::MinusInfinity();
     70    probing_state_ = ProbingState::kActive;
     71  }
     72 }
     73 
     74 bool BitrateProber::ReadyToSetActiveState(DataSize packet_size) const {
     75  if (clusters_.empty()) {
     76    RTC_DCHECK(probing_state_ == ProbingState::kDisabled ||
     77               probing_state_ == ProbingState::kInactive);
     78    return false;
     79  }
     80  switch (probing_state_) {
     81    case ProbingState::kDisabled:
     82    case ProbingState::kActive:
     83      return false;
     84    case ProbingState::kInactive:
     85      if (config_.allow_start_probing_immediately) {
     86        return true;
     87      }
     88      // If config_.min_packet_size > 0, a "large enough" packet must be
     89      // sent first, before a probe can be generated and sent. Otherwise,
     90      // send the probe asap.
     91      return packet_size >=
     92             std::min(RecommendedMinProbeSize(), config_.min_packet_size.Get());
     93  }
     94 }
     95 
     96 void BitrateProber::OnIncomingPacket(DataSize packet_size) {
     97  MaybeSetActiveState(packet_size);
     98 }
     99 
    100 void BitrateProber::CreateProbeCluster(
    101    const ProbeClusterConfig& cluster_config) {
    102  RTC_DCHECK(probing_state_ != ProbingState::kDisabled);
    103  RTC_DCHECK(cluster_config.min_probe_delta > TimeDelta::Zero());
    104 
    105  while (!clusters_.empty() &&
    106         (cluster_config.at_time - clusters_.front().requested_at >
    107              kProbeClusterTimeout ||
    108          clusters_.size() > kMaxPendingProbeClusters)) {
    109    clusters_.pop();
    110  }
    111 
    112  ProbeCluster cluster;
    113  cluster.requested_at = cluster_config.at_time;
    114  cluster.pace_info.probe_cluster_min_probes =
    115      cluster_config.target_probe_count;
    116  cluster.pace_info.probe_cluster_min_bytes =
    117      (cluster_config.target_data_rate * cluster_config.target_duration)
    118          .bytes();
    119  RTC_DCHECK_GE(cluster.pace_info.probe_cluster_min_bytes, 0);
    120  cluster.min_probe_delta = cluster_config.min_probe_delta;
    121  cluster.pace_info.send_bitrate = cluster_config.target_data_rate;
    122  cluster.pace_info.probe_cluster_id = cluster_config.id;
    123  clusters_.push(cluster);
    124 
    125  MaybeSetActiveState(/*packet_size=*/DataSize::Zero());
    126 
    127  RTC_DCHECK(probing_state_ == ProbingState::kActive ||
    128             probing_state_ == ProbingState::kInactive);
    129 
    130  RTC_LOG(LS_INFO) << "Probe cluster (bitrate_bps:min bytes:min packets): ("
    131                   << cluster.pace_info.send_bitrate << ":"
    132                   << cluster.pace_info.probe_cluster_min_bytes << ":"
    133                   << cluster.pace_info.probe_cluster_min_probes << ", "
    134                   << (probing_state_ == ProbingState::kInactive ? "Inactive"
    135                                                                 : "Active")
    136                   << ")";
    137 }
    138 
    139 Timestamp BitrateProber::NextProbeTime(Timestamp /* now */) const {
    140  // Probing is not active or probing is already complete.
    141  if (probing_state_ != ProbingState::kActive || clusters_.empty()) {
    142    return Timestamp::PlusInfinity();
    143  }
    144 
    145  return next_probe_time_;
    146 }
    147 
    148 std::optional<PacedPacketInfo> BitrateProber::CurrentCluster(Timestamp now) {
    149  if (clusters_.empty() || probing_state_ != ProbingState::kActive) {
    150    return std::nullopt;
    151  }
    152 
    153  if (next_probe_time_.IsFinite() &&
    154      now - next_probe_time_ > config_.max_probe_delay.Get()) {
    155    RTC_DLOG(LS_WARNING) << "Probe delay too high"
    156                            " (next_ms:"
    157                         << next_probe_time_.ms() << ", now_ms: " << now.ms()
    158                         << "), discarding probe cluster.";
    159    clusters_.pop();
    160    if (clusters_.empty()) {
    161      probing_state_ = ProbingState::kInactive;
    162      return std::nullopt;
    163    }
    164  }
    165 
    166  PacedPacketInfo info = clusters_.front().pace_info;
    167  info.probe_cluster_bytes_sent = clusters_.front().sent_bytes;
    168  return info;
    169 }
    170 
    171 DataSize BitrateProber::RecommendedMinProbeSize() const {
    172  if (clusters_.empty()) {
    173    return DataSize::Zero();
    174  }
    175  DataRate send_rate = clusters_.front().pace_info.send_bitrate;
    176  return send_rate * clusters_.front().min_probe_delta;
    177 }
    178 
    179 void BitrateProber::ProbeSent(Timestamp now, DataSize size) {
    180  RTC_DCHECK(probing_state_ == ProbingState::kActive);
    181  RTC_DCHECK(!size.IsZero());
    182 
    183  if (!clusters_.empty()) {
    184    ProbeCluster* cluster = &clusters_.front();
    185    if (cluster->sent_probes == 0) {
    186      RTC_DCHECK(cluster->started_at.IsInfinite());
    187      cluster->started_at = now;
    188    }
    189    cluster->sent_bytes += size.bytes<int>();
    190    cluster->sent_probes += 1;
    191    next_probe_time_ = CalculateNextProbeTime(*cluster);
    192    if (cluster->sent_bytes >= cluster->pace_info.probe_cluster_min_bytes &&
    193        cluster->sent_probes >= cluster->pace_info.probe_cluster_min_probes) {
    194      clusters_.pop();
    195    }
    196    if (clusters_.empty()) {
    197      probing_state_ = ProbingState::kInactive;
    198    }
    199  }
    200 }
    201 
    202 Timestamp BitrateProber::CalculateNextProbeTime(
    203    const ProbeCluster& cluster) const {
    204  RTC_CHECK_GT(cluster.pace_info.send_bitrate.bps(), 0);
    205  RTC_CHECK(cluster.started_at.IsFinite());
    206 
    207  // Compute the time delta from the cluster start to ensure probe bitrate stays
    208  // close to the target bitrate. Result is in milliseconds.
    209  DataSize sent_bytes = DataSize::Bytes(cluster.sent_bytes);
    210  DataRate send_bitrate = cluster.pace_info.send_bitrate;
    211 
    212  TimeDelta delta = sent_bytes / send_bitrate;
    213  return cluster.started_at + delta;
    214 }
    215 
    216 }  // namespace webrtc