tor-browser

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

active_decode_targets_helper.cc (4669B)


      1 /*
      2 *  Copyright (c) 2020 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/active_decode_targets_helper.h"
     12 
     13 #include <bitset>
     14 #include <cstddef>
     15 #include <cstdint>
     16 
     17 #include "api/array_view.h"
     18 #include "rtc_base/checks.h"
     19 #include "rtc_base/logging.h"
     20 
     21 namespace webrtc {
     22 namespace {
     23 
     24 // Returns mask of ids of chains previous frame is part of.
     25 // Assumes for each chain frames are seen in order and no frame on any chain is
     26 // missing. That assumptions allows a simple detection when previous frame is
     27 // part of a chain.
     28 std::bitset<32> LastSendOnChain(int frame_diff,
     29                                ArrayView<const int> chain_diffs) {
     30  std::bitset<32> bitmask = 0;
     31  for (size_t i = 0; i < chain_diffs.size(); ++i) {
     32    if (frame_diff == chain_diffs[i]) {
     33      bitmask.set(i);
     34    }
     35  }
     36  return bitmask;
     37 }
     38 
     39 // Returns bitmask with first `num` bits set to 1.
     40 std::bitset<32> AllActive(size_t num) {
     41  RTC_DCHECK_LE(num, 32);
     42  return (~uint32_t{0}) >> (32 - num);
     43 }
     44 
     45 // Returns bitmask of chains that protect at least one active decode target.
     46 std::bitset<32> ActiveChains(
     47    ArrayView<const int> decode_target_protected_by_chain,
     48    int num_chains,
     49    std::bitset<32> active_decode_targets) {
     50  std::bitset<32> active_chains = 0;
     51  for (size_t dt = 0; dt < decode_target_protected_by_chain.size(); ++dt) {
     52    if (dt < active_decode_targets.size() && !active_decode_targets[dt]) {
     53      continue;
     54    }
     55    int chain_idx = decode_target_protected_by_chain[dt];
     56    RTC_DCHECK_LT(chain_idx, num_chains);
     57    active_chains.set(chain_idx);
     58  }
     59  return active_chains;
     60 }
     61 
     62 }  // namespace
     63 
     64 void ActiveDecodeTargetsHelper::OnFrame(
     65    ArrayView<const int> decode_target_protected_by_chain,
     66    std::bitset<32> active_decode_targets,
     67    bool is_keyframe,
     68    int64_t frame_id,
     69    ArrayView<const int> chain_diffs) {
     70  const int num_chains = chain_diffs.size();
     71  if (num_chains == 0) {
     72    // Avoid printing the warning
     73    // when already printed the warning for the same active decode targets, or
     74    // when active_decode_targets are not changed from it's default value of
     75    // all are active, including non-existent decode targets.
     76    if (last_active_decode_targets_ != active_decode_targets &&
     77        !active_decode_targets.all()) {
     78      RTC_LOG(LS_WARNING) << "No chains are configured, but some decode "
     79                             "targets might be inactive. Unsupported.";
     80    }
     81    last_active_decode_targets_ = active_decode_targets;
     82    return;
     83  }
     84  const size_t num_decode_targets = decode_target_protected_by_chain.size();
     85  RTC_DCHECK_GT(num_decode_targets, 0);
     86  std::bitset<32> all_decode_targets = AllActive(num_decode_targets);
     87  // Default value for active_decode_targets is 'all are active', i.e. all bits
     88  // are set. Default value is set before number of decode targets is known.
     89  // It is up to this helper to make the value cleaner and unset unused bits.
     90  active_decode_targets &= all_decode_targets;
     91 
     92  if (is_keyframe) {
     93    // Key frame resets the state.
     94    last_active_decode_targets_ = all_decode_targets;
     95    last_active_chains_ = AllActive(num_chains);
     96    unsent_on_chain_.reset();
     97  } else {
     98    // Update state assuming previous frame was sent.
     99    unsent_on_chain_ &=
    100        ~LastSendOnChain(frame_id - last_frame_id_, chain_diffs);
    101  }
    102  // Save for the next call to OnFrame.
    103  // Though usually `frame_id == last_frame_id_ + 1`, it might not be so when
    104  // frame id space is shared by several simulcast rtp streams.
    105  last_frame_id_ = frame_id;
    106 
    107  if (active_decode_targets == last_active_decode_targets_) {
    108    return;
    109  }
    110  last_active_decode_targets_ = active_decode_targets;
    111 
    112  if (active_decode_targets.none()) {
    113    RTC_LOG(LS_ERROR) << "It is invalid to produce a frame (" << frame_id
    114                      << ") while there are no active decode targets";
    115    return;
    116  }
    117  last_active_chains_ = ActiveChains(decode_target_protected_by_chain,
    118                                     num_chains, active_decode_targets);
    119  // Frames that are part of inactive chains might not be produced by the
    120  // encoder. Thus stop sending `active_decode_target` bitmask when it is sent
    121  // on all active chains rather than on all chains.
    122  unsent_on_chain_ = last_active_chains_;
    123  RTC_DCHECK(!unsent_on_chain_.none());
    124 }
    125 
    126 }  // namespace webrtc