tor-browser

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

bitrate_adjuster.cc (6252B)


      1 /*
      2 *  Copyright 2016 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 "common_video/include/bitrate_adjuster.h"
     12 
     13 #include <algorithm>
     14 #include <cmath>
     15 #include <cstddef>
     16 #include <cstdint>
     17 #include <optional>
     18 
     19 #include "rtc_base/logging.h"
     20 #include "rtc_base/synchronization/mutex.h"
     21 #include "rtc_base/time_utils.h"
     22 
     23 namespace webrtc {
     24 
     25 // Update bitrate at most once every second.
     26 const uint32_t BitrateAdjuster::kBitrateUpdateIntervalMs = 1000;
     27 
     28 // Update bitrate at most once every 30 frames.
     29 const uint32_t BitrateAdjuster::kBitrateUpdateFrameInterval = 30;
     30 
     31 // 10 percent of original.
     32 const float BitrateAdjuster::kBitrateTolerancePct = .1f;
     33 
     34 const float BitrateAdjuster::kBytesPerMsToBitsPerSecond = 8 * 1000;
     35 
     36 BitrateAdjuster::BitrateAdjuster(float min_adjusted_bitrate_pct,
     37                                 float max_adjusted_bitrate_pct)
     38    : min_adjusted_bitrate_pct_(min_adjusted_bitrate_pct),
     39      max_adjusted_bitrate_pct_(max_adjusted_bitrate_pct),
     40      bitrate_tracker_(1.5 * kBitrateUpdateIntervalMs,
     41                       kBytesPerMsToBitsPerSecond) {
     42  Reset();
     43 }
     44 
     45 void BitrateAdjuster::SetTargetBitrateBps(uint32_t bitrate_bps) {
     46  MutexLock lock(&mutex_);
     47  // If the change in target bitrate is large, update the adjusted bitrate
     48  // immediately since it's likely we have gained or lost a sizeable amount of
     49  // bandwidth and we'll want to respond quickly.
     50  // If the change in target bitrate fits within the existing tolerance of
     51  // encoder output, wait for the next adjustment time to preserve
     52  // existing penalties and not forcibly reset the adjusted bitrate to target.
     53  // However, if we received many small deltas within an update time
     54  // window and one of them exceeds the tolerance when compared to the last
     55  // target we updated against, treat it as a large change in target bitrate.
     56  if (!IsWithinTolerance(bitrate_bps, target_bitrate_bps_) ||
     57      !IsWithinTolerance(bitrate_bps, last_adjusted_target_bitrate_bps_)) {
     58    adjusted_bitrate_bps_ = bitrate_bps;
     59    last_adjusted_target_bitrate_bps_ = bitrate_bps;
     60  }
     61  target_bitrate_bps_ = bitrate_bps;
     62 }
     63 
     64 uint32_t BitrateAdjuster::GetTargetBitrateBps() const {
     65  MutexLock lock(&mutex_);
     66  return target_bitrate_bps_;
     67 }
     68 
     69 uint32_t BitrateAdjuster::GetAdjustedBitrateBps() const {
     70  MutexLock lock(&mutex_);
     71  return adjusted_bitrate_bps_;
     72 }
     73 
     74 std::optional<uint32_t> BitrateAdjuster::GetEstimatedBitrateBps() {
     75  MutexLock lock(&mutex_);
     76  return bitrate_tracker_.Rate(TimeMillis());
     77 }
     78 
     79 void BitrateAdjuster::Update(size_t frame_size) {
     80  MutexLock lock(&mutex_);
     81  uint32_t current_time_ms = TimeMillis();
     82  bitrate_tracker_.Update(frame_size, current_time_ms);
     83  UpdateBitrate(current_time_ms);
     84 }
     85 
     86 bool BitrateAdjuster::IsWithinTolerance(uint32_t bitrate_bps,
     87                                        uint32_t target_bitrate_bps) {
     88  if (target_bitrate_bps == 0) {
     89    return false;
     90  }
     91  float delta = std::abs(static_cast<float>(bitrate_bps) -
     92                         static_cast<float>(target_bitrate_bps));
     93  float delta_pct = delta / target_bitrate_bps;
     94  return delta_pct < kBitrateTolerancePct;
     95 }
     96 
     97 uint32_t BitrateAdjuster::GetMinAdjustedBitrateBps() const {
     98  return min_adjusted_bitrate_pct_ * target_bitrate_bps_;
     99 }
    100 
    101 uint32_t BitrateAdjuster::GetMaxAdjustedBitrateBps() const {
    102  return max_adjusted_bitrate_pct_ * target_bitrate_bps_;
    103 }
    104 
    105 // Only safe to call this after Update calls have stopped
    106 void BitrateAdjuster::Reset() {
    107  MutexLock lock(&mutex_);
    108  target_bitrate_bps_ = 0;
    109  adjusted_bitrate_bps_ = 0;
    110  last_adjusted_target_bitrate_bps_ = 0;
    111  last_bitrate_update_time_ms_ = 0;
    112  frames_since_last_update_ = 0;
    113  bitrate_tracker_.Reset();
    114 }
    115 
    116 void BitrateAdjuster::UpdateBitrate(uint32_t current_time_ms) {
    117  uint32_t time_since_last_update_ms =
    118      current_time_ms - last_bitrate_update_time_ms_;
    119  // Don't attempt to update bitrate unless enough time and frames have passed.
    120  ++frames_since_last_update_;
    121  if (time_since_last_update_ms < kBitrateUpdateIntervalMs ||
    122      frames_since_last_update_ < kBitrateUpdateFrameInterval) {
    123    return;
    124  }
    125  float target_bitrate_bps = target_bitrate_bps_;
    126  float estimated_bitrate_bps =
    127      bitrate_tracker_.Rate(current_time_ms).value_or(target_bitrate_bps);
    128  float error = target_bitrate_bps - estimated_bitrate_bps;
    129 
    130  // Adjust if we've overshot by any amount or if we've undershot too much.
    131  if (estimated_bitrate_bps > target_bitrate_bps ||
    132      error > kBitrateTolerancePct * target_bitrate_bps) {
    133    // Adjust the bitrate by a fraction of the error.
    134    float adjustment = .5 * error;
    135    float adjusted_bitrate_bps = target_bitrate_bps + adjustment;
    136 
    137    // Clamp the adjustment.
    138    float min_bitrate_bps = GetMinAdjustedBitrateBps();
    139    float max_bitrate_bps = GetMaxAdjustedBitrateBps();
    140    adjusted_bitrate_bps = std::max(adjusted_bitrate_bps, min_bitrate_bps);
    141    adjusted_bitrate_bps = std::min(adjusted_bitrate_bps, max_bitrate_bps);
    142 
    143    // Set the adjustment if it's not already set.
    144    float last_adjusted_bitrate_bps = adjusted_bitrate_bps_;
    145    if (adjusted_bitrate_bps != last_adjusted_bitrate_bps) {
    146      RTC_LOG(LS_VERBOSE) << "Adjusting encoder bitrate:"
    147                             "\n  target_bitrate:"
    148                          << static_cast<uint32_t>(target_bitrate_bps)
    149                          << "\n  estimated_bitrate:"
    150                          << static_cast<uint32_t>(estimated_bitrate_bps)
    151                          << "\n  last_adjusted_bitrate:"
    152                          << static_cast<uint32_t>(last_adjusted_bitrate_bps)
    153                          << "\n  adjusted_bitrate:"
    154                          << static_cast<uint32_t>(adjusted_bitrate_bps);
    155      adjusted_bitrate_bps_ = adjusted_bitrate_bps;
    156    }
    157  }
    158  last_bitrate_update_time_ms_ = current_time_ms;
    159  frames_since_last_update_ = 0;
    160  last_adjusted_target_bitrate_bps_ = target_bitrate_bps_;
    161 }
    162 
    163 }  // namespace webrtc