tor-browser

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

tmmbr_help.cc (6325B)


      1 /*
      2 *  Copyright (c) 2012 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/rtp_rtcp/source/tmmbr_help.h"
     12 
     13 #include <cstddef>
     14 #include <cstdint>
     15 #include <limits>
     16 #include <vector>
     17 
     18 #include "absl/algorithm/container.h"
     19 #include "modules/rtp_rtcp/source/rtcp_packet/tmmb_item.h"
     20 #include "rtc_base/checks.h"
     21 
     22 namespace webrtc {
     23 std::vector<rtcp::TmmbItem> TMMBRHelp::FindBoundingSet(
     24    std::vector<rtcp::TmmbItem> candidates) {
     25  // Filter out candidates with 0 bitrate.
     26  for (auto it = candidates.begin(); it != candidates.end();) {
     27    if (!it->bitrate_bps())
     28      it = candidates.erase(it);
     29    else
     30      ++it;
     31  }
     32 
     33  if (candidates.size() <= 1)
     34    return candidates;
     35 
     36  size_t num_candidates = candidates.size();
     37 
     38  // 1. Sort by increasing packet overhead.
     39  absl::c_sort(candidates,
     40               [](const rtcp::TmmbItem& lhs, const rtcp::TmmbItem& rhs) {
     41                 return lhs.packet_overhead() < rhs.packet_overhead();
     42               });
     43 
     44  // 2. For tuples with same overhead, keep the one with the lowest bitrate.
     45  for (auto it = candidates.begin(); it != candidates.end();) {
     46    RTC_DCHECK(it->bitrate_bps());
     47    auto current_min = it;
     48    auto next_it = it + 1;
     49    // Use fact candidates are sorted by overhead, so candidates with same
     50    // overhead are adjusted.
     51    while (next_it != candidates.end() &&
     52           next_it->packet_overhead() == current_min->packet_overhead()) {
     53      if (next_it->bitrate_bps() < current_min->bitrate_bps()) {
     54        current_min->set_bitrate_bps(0);
     55        current_min = next_it;
     56      } else {
     57        next_it->set_bitrate_bps(0);
     58      }
     59      ++next_it;
     60      --num_candidates;
     61    }
     62    it = next_it;
     63  }
     64 
     65  // 3. Select and remove tuple with lowest bitrate.
     66  // (If more than 1, choose the one with highest overhead).
     67  auto min_bitrate_it = candidates.end();
     68  for (auto it = candidates.begin(); it != candidates.end(); ++it) {
     69    if (it->bitrate_bps()) {
     70      min_bitrate_it = it;
     71      break;
     72    }
     73  }
     74 
     75  for (auto it = min_bitrate_it; it != candidates.end(); ++it) {
     76    if (it->bitrate_bps() &&
     77        it->bitrate_bps() <= min_bitrate_it->bitrate_bps()) {
     78      // Get min bitrate.
     79      min_bitrate_it = it;
     80    }
     81  }
     82 
     83  std::vector<rtcp::TmmbItem> bounding_set;
     84  bounding_set.reserve(num_candidates);
     85  std::vector<float> intersection(num_candidates);
     86  std::vector<float> max_packet_rate(num_candidates);
     87 
     88  // First member of selected list.
     89  bounding_set.push_back(*min_bitrate_it);
     90  intersection[0] = 0;
     91  // Calculate its maximum packet rate (where its line crosses x-axis).
     92  if (bounding_set.back().packet_overhead() == 0) {
     93    // Avoid division by zero.
     94    max_packet_rate[0] = std::numeric_limits<float>::max();
     95  } else {
     96    max_packet_rate[0] =
     97        bounding_set.back().bitrate_bps() /
     98        static_cast<float>(bounding_set.back().packet_overhead());
     99  }
    100  // Remove from candidate list.
    101  min_bitrate_it->set_bitrate_bps(0);
    102  --num_candidates;
    103 
    104  // 4. Discard from candidate list all tuple with lower overhead
    105  // (next tuple must be steeper).
    106  for (auto it = candidates.begin(); it != candidates.end(); ++it) {
    107    if (it->bitrate_bps() &&
    108        it->packet_overhead() < bounding_set.front().packet_overhead()) {
    109      it->set_bitrate_bps(0);
    110      --num_candidates;
    111    }
    112  }
    113 
    114  bool get_new_candidate = true;
    115  rtcp::TmmbItem cur_candidate;
    116  while (num_candidates > 0) {
    117    if (get_new_candidate) {
    118      // 5. Remove first remaining tuple from candidate list.
    119      for (auto it = candidates.begin(); it != candidates.end(); ++it) {
    120        if (it->bitrate_bps()) {
    121          cur_candidate = *it;
    122          it->set_bitrate_bps(0);
    123          break;
    124        }
    125      }
    126    }
    127 
    128    // 6. Calculate packet rate and intersection of the current
    129    // line with line of last tuple in selected list.
    130    RTC_DCHECK_NE(cur_candidate.packet_overhead(),
    131                  bounding_set.back().packet_overhead());
    132    float packet_rate = static_cast<float>(cur_candidate.bitrate_bps() -
    133                                           bounding_set.back().bitrate_bps()) /
    134                        (cur_candidate.packet_overhead() -
    135                         bounding_set.back().packet_overhead());
    136 
    137    // 7. If the packet rate is equal or lower than intersection of
    138    //    last tuple in selected list,
    139    //    remove last tuple in selected list & go back to step 6.
    140    if (packet_rate <= intersection[bounding_set.size() - 1]) {
    141      // Remove last tuple and goto step 6.
    142      bounding_set.pop_back();
    143      get_new_candidate = false;
    144    } else {
    145      // 8. If packet rate is lower than maximum packet rate of
    146      // last tuple in selected list, add current tuple to selected
    147      // list.
    148      if (packet_rate < max_packet_rate[bounding_set.size() - 1]) {
    149        bounding_set.push_back(cur_candidate);
    150        intersection[bounding_set.size() - 1] = packet_rate;
    151        uint16_t packet_overhead = bounding_set.back().packet_overhead();
    152        RTC_DCHECK_NE(packet_overhead, 0);
    153        max_packet_rate[bounding_set.size() - 1] =
    154            bounding_set.back().bitrate_bps() /
    155            static_cast<float>(packet_overhead);
    156      }
    157      --num_candidates;
    158      get_new_candidate = true;
    159    }
    160 
    161    // 9. Go back to step 5 if any tuple remains in candidate list.
    162  }
    163  RTC_DCHECK(!bounding_set.empty());
    164  return bounding_set;
    165 }
    166 
    167 bool TMMBRHelp::IsOwner(const std::vector<rtcp::TmmbItem>& bounding,
    168                        uint32_t ssrc) {
    169  for (const rtcp::TmmbItem& item : bounding) {
    170    if (item.ssrc() == ssrc) {
    171      return true;
    172    }
    173  }
    174  return false;
    175 }
    176 
    177 uint64_t TMMBRHelp::CalcMinBitrateBps(
    178    const std::vector<rtcp::TmmbItem>& candidates) {
    179  RTC_DCHECK(!candidates.empty());
    180  uint64_t min_bitrate_bps = std::numeric_limits<uint64_t>::max();
    181  for (const rtcp::TmmbItem& item : candidates)
    182    if (item.bitrate_bps() < min_bitrate_bps)
    183      min_bitrate_bps = item.bitrate_bps();
    184  return min_bitrate_bps;
    185 }
    186 }  // namespace webrtc