tor-browser

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

svc_rate_allocator.cc (16742B)


      1 /*
      2 *  Copyright (c) 2018 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/video_coding/svc/svc_rate_allocator.h"
     12 
     13 #include <algorithm>
     14 #include <cmath>
     15 #include <cstddef>
     16 #include <numeric>
     17 #include <optional>
     18 #include <vector>
     19 
     20 #include "absl/container/inlined_vector.h"
     21 #include "api/field_trials_view.h"
     22 #include "api/units/data_rate.h"
     23 #include "api/video/video_bitrate_allocation.h"
     24 #include "api/video/video_bitrate_allocator.h"
     25 #include "api/video/video_codec_constants.h"
     26 #include "api/video/video_codec_type.h"
     27 #include "api/video_codecs/scalability_mode.h"
     28 #include "api/video_codecs/video_codec.h"
     29 #include "modules/video_coding/svc/create_scalability_structure.h"
     30 #include "modules/video_coding/svc/scalable_video_controller.h"
     31 #include "rtc_base/checks.h"
     32 
     33 namespace webrtc {
     34 namespace {
     35 
     36 constexpr float kSpatialLayeringRateScalingFactor = 0.55f;
     37 constexpr float kTemporalLayeringRateScalingFactor = 0.55f;
     38 
     39 struct ActiveSpatialLayers {
     40  size_t first = 0;
     41  size_t num = 0;
     42 };
     43 
     44 ActiveSpatialLayers GetActiveSpatialLayers(const VideoCodec& codec,
     45                                           size_t num_spatial_layers) {
     46  ActiveSpatialLayers active;
     47  for (active.first = 0; active.first < num_spatial_layers; ++active.first) {
     48    if (codec.spatialLayers[active.first].active) {
     49      break;
     50    }
     51  }
     52 
     53  size_t last_active_layer = active.first;
     54  for (; last_active_layer < num_spatial_layers; ++last_active_layer) {
     55    if (!codec.spatialLayers[last_active_layer].active) {
     56      break;
     57    }
     58  }
     59  active.num = last_active_layer - active.first;
     60 
     61  return active;
     62 }
     63 
     64 std::vector<DataRate> AdjustAndVerify(
     65    const VideoCodec& codec,
     66    size_t first_active_layer,
     67    const std::vector<DataRate>& spatial_layer_rates) {
     68  std::vector<DataRate> adjusted_spatial_layer_rates;
     69  // Keep track of rate that couldn't be applied to the previous layer due to
     70  // max bitrate constraint, try to pass it forward to the next one.
     71  DataRate excess_rate = DataRate::Zero();
     72  for (size_t sl_idx = 0; sl_idx < spatial_layer_rates.size(); ++sl_idx) {
     73    DataRate min_rate = DataRate::KilobitsPerSec(
     74        codec.spatialLayers[first_active_layer + sl_idx].minBitrate);
     75    DataRate max_rate = DataRate::KilobitsPerSec(
     76        codec.spatialLayers[first_active_layer + sl_idx].maxBitrate);
     77 
     78    DataRate layer_rate = spatial_layer_rates[sl_idx] + excess_rate;
     79    if (layer_rate < min_rate) {
     80      // Not enough rate to reach min bitrate for desired number of layers,
     81      // abort allocation.
     82      if (spatial_layer_rates.size() == 1) {
     83        return spatial_layer_rates;
     84      }
     85      return adjusted_spatial_layer_rates;
     86    }
     87 
     88    if (layer_rate <= max_rate) {
     89      excess_rate = DataRate::Zero();
     90      adjusted_spatial_layer_rates.push_back(layer_rate);
     91    } else {
     92      excess_rate = layer_rate - max_rate;
     93      adjusted_spatial_layer_rates.push_back(max_rate);
     94    }
     95  }
     96 
     97  return adjusted_spatial_layer_rates;
     98 }
     99 
    100 std::vector<DataRate> SplitBitrate(size_t num_layers,
    101                                   DataRate total_bitrate,
    102                                   float rate_scaling_factor) {
    103  std::vector<DataRate> bitrates;
    104 
    105  double denominator = 0.0;
    106  for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
    107    denominator += std::pow(rate_scaling_factor, layer_idx);
    108  }
    109 
    110  double numerator = std::pow(rate_scaling_factor, num_layers - 1);
    111  for (size_t layer_idx = 0; layer_idx < num_layers; ++layer_idx) {
    112    bitrates.push_back(numerator * total_bitrate / denominator);
    113    numerator /= rate_scaling_factor;
    114  }
    115 
    116  const DataRate sum =
    117      std::accumulate(bitrates.begin(), bitrates.end(), DataRate::Zero());
    118 
    119  // Keep the sum of split bitrates equal to the total bitrate by adding or
    120  // subtracting bits, which were lost due to rounding, to the latest layer.
    121  if (total_bitrate > sum) {
    122    bitrates.back() += total_bitrate - sum;
    123  } else if (total_bitrate < sum) {
    124    bitrates.back() -= sum - total_bitrate;
    125  }
    126 
    127  return bitrates;
    128 }
    129 
    130 VideoBitrateAllocation DistributeAllocationToTemporalLayers(
    131    std::vector<DataRate> spatial_layer_birates,
    132    size_t first_active_layer,
    133    size_t num_temporal_layers) {
    134  // Distribute rate across temporal layers. Allocate more bits to lower
    135  // layers since they are used for prediction of higher layers and their
    136  // references are far apart.
    137  VideoBitrateAllocation bitrate_allocation;
    138  for (size_t sl_idx = 0; sl_idx < spatial_layer_birates.size(); ++sl_idx) {
    139    std::vector<DataRate> temporal_layer_bitrates =
    140        SplitBitrate(num_temporal_layers, spatial_layer_birates[sl_idx],
    141                     kTemporalLayeringRateScalingFactor);
    142 
    143    if (num_temporal_layers == 1) {
    144      bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
    145                                    temporal_layer_bitrates[0].bps());
    146    } else if (num_temporal_layers == 2) {
    147      bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
    148                                    temporal_layer_bitrates[1].bps());
    149      bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 1,
    150                                    temporal_layer_bitrates[0].bps());
    151    } else {
    152      RTC_CHECK_EQ(num_temporal_layers, 3);
    153      // In case of three temporal layers the high layer has two frames and the
    154      // middle layer has one frame within GOP (in between two consecutive low
    155      // layer frames). Thus high layer requires more bits (comparing pure
    156      // bitrate of layer, excluding bitrate of base layers) to keep quality on
    157      // par with lower layers.
    158      bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 0,
    159                                    temporal_layer_bitrates[2].bps());
    160      bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 1,
    161                                    temporal_layer_bitrates[0].bps());
    162      bitrate_allocation.SetBitrate(sl_idx + first_active_layer, 2,
    163                                    temporal_layer_bitrates[1].bps());
    164    }
    165  }
    166 
    167  return bitrate_allocation;
    168 }
    169 
    170 // Returns the minimum bitrate needed for `num_active_layers` spatial layers to
    171 // become active using the configuration specified by `codec`.
    172 DataRate FindLayerTogglingThreshold(const VideoCodec& codec,
    173                                    size_t first_active_layer,
    174                                    size_t num_active_layers) {
    175  if (num_active_layers == 1) {
    176    return DataRate::KilobitsPerSec(codec.spatialLayers[0].minBitrate);
    177  }
    178 
    179  if (codec.mode == VideoCodecMode::kRealtimeVideo) {
    180    DataRate lower_bound = DataRate::Zero();
    181    DataRate upper_bound = DataRate::Zero();
    182    if (num_active_layers > 1) {
    183      for (size_t i = 0; i < num_active_layers - 1; ++i) {
    184        lower_bound += DataRate::KilobitsPerSec(
    185            codec.spatialLayers[first_active_layer + i].minBitrate);
    186        upper_bound += DataRate::KilobitsPerSec(
    187            codec.spatialLayers[first_active_layer + i].maxBitrate);
    188      }
    189    }
    190    upper_bound += DataRate::KilobitsPerSec(
    191        codec.spatialLayers[first_active_layer + num_active_layers - 1]
    192            .minBitrate);
    193 
    194    // Do a binary search until upper and lower bound is the highest bitrate for
    195    // `num_active_layers` - 1 layers and lowest bitrate for `num_active_layers`
    196    // layers respectively.
    197    while (upper_bound - lower_bound > DataRate::BitsPerSec(1)) {
    198      DataRate try_rate = (lower_bound + upper_bound) / 2;
    199      if (AdjustAndVerify(codec, first_active_layer,
    200                          SplitBitrate(num_active_layers, try_rate,
    201                                       kSpatialLayeringRateScalingFactor))
    202              .size() == num_active_layers) {
    203        upper_bound = try_rate;
    204      } else {
    205        lower_bound = try_rate;
    206      }
    207    }
    208    return upper_bound;
    209  } else {
    210    DataRate toggling_rate = DataRate::Zero();
    211    for (size_t i = 0; i < num_active_layers - 1; ++i) {
    212      toggling_rate += DataRate::KilobitsPerSec(
    213          codec.spatialLayers[first_active_layer + i].targetBitrate);
    214    }
    215    toggling_rate += DataRate::KilobitsPerSec(
    216        codec.spatialLayers[first_active_layer + num_active_layers - 1]
    217            .minBitrate);
    218    return toggling_rate;
    219  }
    220 }
    221 
    222 }  // namespace
    223 
    224 SvcRateAllocator::NumLayers SvcRateAllocator::GetNumLayers(
    225    const VideoCodec& codec) {
    226  NumLayers layers;
    227  if (std::optional<ScalabilityMode> scalability_mode =
    228          codec.GetScalabilityMode();
    229      scalability_mode.has_value()) {
    230    if (auto structure = CreateScalabilityStructure(*scalability_mode)) {
    231      ScalableVideoController::StreamLayersConfig config =
    232          structure->StreamConfig();
    233      layers.spatial = config.num_spatial_layers;
    234      layers.temporal = config.num_temporal_layers;
    235      return layers;
    236    }
    237  }
    238  if (codec.codecType == kVideoCodecVP9) {
    239    layers.spatial = codec.VP9().numberOfSpatialLayers;
    240    layers.temporal = codec.VP9().numberOfTemporalLayers;
    241    return layers;
    242  }
    243  layers.spatial = 1;
    244  layers.temporal = 1;
    245  return layers;
    246 }
    247 
    248 SvcRateAllocator::SvcRateAllocator(const VideoCodec& codec,
    249                                   const FieldTrialsView& field_trials)
    250    : codec_(codec),
    251      num_layers_(GetNumLayers(codec)),
    252      cumulative_layer_start_bitrates_(GetLayerStartBitrates(codec)),
    253      last_active_layer_count_(0) {
    254  RTC_DCHECK_GT(num_layers_.spatial, 0);
    255  RTC_DCHECK_LE(num_layers_.spatial, kMaxSpatialLayers);
    256  RTC_DCHECK_GT(num_layers_.temporal, 0);
    257  RTC_DCHECK_LE(num_layers_.temporal, 3);
    258  for (size_t layer_idx = 0; layer_idx < num_layers_.spatial; ++layer_idx) {
    259    // Verify min <= target <= max.
    260    if (codec.spatialLayers[layer_idx].active) {
    261      RTC_DCHECK_GT(codec.spatialLayers[layer_idx].maxBitrate, 0);
    262      RTC_DCHECK_GE(codec.spatialLayers[layer_idx].maxBitrate,
    263                    codec.spatialLayers[layer_idx].minBitrate);
    264      RTC_DCHECK_GE(codec.spatialLayers[layer_idx].targetBitrate,
    265                    codec.spatialLayers[layer_idx].minBitrate);
    266      RTC_DCHECK_GE(codec.spatialLayers[layer_idx].maxBitrate,
    267                    codec.spatialLayers[layer_idx].targetBitrate);
    268    }
    269  }
    270 }
    271 
    272 VideoBitrateAllocation SvcRateAllocator::Allocate(
    273    VideoBitrateAllocationParameters parameters) {
    274  DataRate total_bitrate = parameters.total_bitrate;
    275  if (codec_.maxBitrate != 0) {
    276    total_bitrate =
    277        std::min(total_bitrate, DataRate::KilobitsPerSec(codec_.maxBitrate));
    278  }
    279 
    280  if (codec_.spatialLayers[0].targetBitrate == 0) {
    281    // Delegate rate distribution to encoder wrapper if bitrate thresholds
    282    // are not set.
    283    VideoBitrateAllocation bitrate_allocation;
    284    bitrate_allocation.SetBitrate(0, 0, total_bitrate.bps());
    285    return bitrate_allocation;
    286  }
    287 
    288  const ActiveSpatialLayers active_layers =
    289      GetActiveSpatialLayers(codec_, num_layers_.spatial);
    290  size_t num_spatial_layers = active_layers.num;
    291 
    292  if (num_spatial_layers == 0) {
    293    return VideoBitrateAllocation();  // All layers are deactivated.
    294  }
    295 
    296  // Figure out how many spatial layers should be active.
    297  num_spatial_layers = FindNumEnabledLayers(total_bitrate);
    298  last_active_layer_count_ = num_spatial_layers;
    299 
    300  std::vector<DataRate> spatial_layer_bitrates;
    301  if (codec_.mode == VideoCodecMode::kRealtimeVideo) {
    302    spatial_layer_bitrates = DistributeAllocationToSpatialLayersNormalVideo(
    303        total_bitrate, active_layers.first, num_spatial_layers);
    304  } else {
    305    spatial_layer_bitrates = DistributeAllocationToSpatialLayersScreenSharing(
    306        total_bitrate, active_layers.first, num_spatial_layers);
    307  }
    308 
    309  VideoBitrateAllocation allocation = DistributeAllocationToTemporalLayers(
    310      spatial_layer_bitrates, active_layers.first, num_layers_.temporal);
    311 
    312  allocation.set_bw_limited(num_spatial_layers < active_layers.num);
    313  return allocation;
    314 }
    315 
    316 std::vector<DataRate>
    317 SvcRateAllocator::DistributeAllocationToSpatialLayersNormalVideo(
    318    DataRate total_bitrate,
    319    size_t first_active_layer,
    320    size_t num_spatial_layers) const {
    321  std::vector<DataRate> spatial_layer_rates;
    322  if (num_spatial_layers == 0) {
    323    // Not enough rate for even the base layer. Force allocation at the total
    324    // bitrate anyway.
    325    num_spatial_layers = 1;
    326    spatial_layer_rates.push_back(total_bitrate);
    327    return spatial_layer_rates;
    328  }
    329 
    330  spatial_layer_rates =
    331      AdjustAndVerify(codec_, first_active_layer,
    332                      SplitBitrate(num_spatial_layers, total_bitrate,
    333                                   kSpatialLayeringRateScalingFactor));
    334  RTC_DCHECK_EQ(spatial_layer_rates.size(), num_spatial_layers);
    335  return spatial_layer_rates;
    336 }
    337 
    338 // Bit-rate is allocated in such a way, that the highest enabled layer will have
    339 // between min and max bitrate, and all others will have exactly target
    340 // bit-rate allocated.
    341 std::vector<DataRate>
    342 SvcRateAllocator::DistributeAllocationToSpatialLayersScreenSharing(
    343    DataRate total_bitrate,
    344    size_t first_active_layer,
    345    size_t num_spatial_layers) const {
    346  std::vector<DataRate> spatial_layer_rates;
    347  if (num_spatial_layers == 0 ||
    348      total_bitrate <
    349          DataRate::KilobitsPerSec(
    350              codec_.spatialLayers[first_active_layer].minBitrate)) {
    351    // Always enable at least one layer.
    352    spatial_layer_rates.push_back(total_bitrate);
    353    return spatial_layer_rates;
    354  }
    355 
    356  DataRate allocated_rate = DataRate::Zero();
    357  DataRate top_layer_rate = DataRate::Zero();
    358  size_t sl_idx;
    359  for (sl_idx = first_active_layer;
    360       sl_idx < first_active_layer + num_spatial_layers; ++sl_idx) {
    361    const DataRate min_rate =
    362        DataRate::KilobitsPerSec(codec_.spatialLayers[sl_idx].minBitrate);
    363    const DataRate target_rate =
    364        DataRate::KilobitsPerSec(codec_.spatialLayers[sl_idx].targetBitrate);
    365 
    366    if (allocated_rate + min_rate > total_bitrate) {
    367      // Use stable rate to determine if layer should be enabled.
    368      break;
    369    }
    370 
    371    top_layer_rate = std::min(target_rate, total_bitrate - allocated_rate);
    372    spatial_layer_rates.push_back(top_layer_rate);
    373    allocated_rate += top_layer_rate;
    374  }
    375 
    376  if (sl_idx > 0 && total_bitrate - allocated_rate > DataRate::Zero()) {
    377    // Add leftover to the last allocated layer.
    378    top_layer_rate = std::min(
    379        top_layer_rate + (total_bitrate - allocated_rate),
    380        DataRate::KilobitsPerSec(codec_.spatialLayers[sl_idx - 1].maxBitrate));
    381    spatial_layer_rates.back() = top_layer_rate;
    382  }
    383 
    384  return spatial_layer_rates;
    385 }
    386 
    387 size_t SvcRateAllocator::FindNumEnabledLayers(DataRate target_rate) const {
    388  if (cumulative_layer_start_bitrates_.empty()) {
    389    return 0;
    390  }
    391 
    392  size_t num_enabled_layers = 0;
    393  for (DataRate start_rate : cumulative_layer_start_bitrates_) {
    394    // First layer is always enabled.
    395    if (num_enabled_layers == 0 || start_rate <= target_rate) {
    396      ++num_enabled_layers;
    397    } else {
    398      break;
    399    }
    400  }
    401 
    402  return num_enabled_layers;
    403 }
    404 
    405 DataRate SvcRateAllocator::GetMaxBitrate(const VideoCodec& codec) {
    406  const NumLayers num_layers = GetNumLayers(codec);
    407  const ActiveSpatialLayers active_layers =
    408      GetActiveSpatialLayers(codec, num_layers.spatial);
    409 
    410  DataRate max_bitrate = DataRate::Zero();
    411  for (size_t sl_idx = 0; sl_idx < active_layers.num; ++sl_idx) {
    412    max_bitrate += DataRate::KilobitsPerSec(
    413        codec.spatialLayers[active_layers.first + sl_idx].maxBitrate);
    414  }
    415 
    416  if (codec.maxBitrate != 0) {
    417    max_bitrate =
    418        std::min(max_bitrate, DataRate::KilobitsPerSec(codec.maxBitrate));
    419  }
    420 
    421  return max_bitrate;
    422 }
    423 
    424 DataRate SvcRateAllocator::GetPaddingBitrate(const VideoCodec& codec) {
    425  auto start_bitrate = GetLayerStartBitrates(codec);
    426  if (start_bitrate.empty()) {
    427    return DataRate::Zero();  // All layers are deactivated.
    428  }
    429 
    430  return start_bitrate.back();
    431 }
    432 
    433 absl::InlinedVector<DataRate, kMaxSpatialLayers>
    434 SvcRateAllocator::GetLayerStartBitrates(const VideoCodec& codec) {
    435  absl::InlinedVector<DataRate, kMaxSpatialLayers> start_bitrates;
    436  const NumLayers num_layers = GetNumLayers(codec);
    437  const ActiveSpatialLayers active_layers =
    438      GetActiveSpatialLayers(codec, num_layers.spatial);
    439  DataRate last_rate = DataRate::Zero();
    440  for (size_t i = 1; i <= active_layers.num; ++i) {
    441    DataRate layer_toggling_rate =
    442        FindLayerTogglingThreshold(codec, active_layers.first, i);
    443    start_bitrates.push_back(layer_toggling_rate);
    444    RTC_DCHECK_LE(last_rate, layer_toggling_rate);
    445    last_rate = layer_toggling_rate;
    446  }
    447  return start_bitrates;
    448 }
    449 
    450 }  // namespace webrtc