tor-browser

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

screenshare_layers.cc (23886B)


      1 /* Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
      2 *
      3 *  Use of this source code is governed by a BSD-style license
      4 *  that can be found in the LICENSE file in the root of the source
      5 *  tree. An additional intellectual property rights grant can be found
      6 *  in the file PATENTS.  All contributing project authors may
      7 *  be found in the AUTHORS file in the root of the source tree.
      8 */
      9 
     10 #include "modules/video_coding/codecs/vp8/screenshare_layers.h"
     11 
     12 #include <algorithm>
     13 #include <cstdint>
     14 #include <cstdlib>
     15 #include <memory>
     16 #include <optional>
     17 #include <vector>
     18 
     19 #include "api/environment/environment.h"
     20 #include "api/transport/rtp/dependency_descriptor.h"
     21 #include "api/video_codecs/video_encoder.h"
     22 #include "api/video_codecs/vp8_frame_buffer_controller.h"
     23 #include "api/video_codecs/vp8_frame_config.h"
     24 #include "api/video_codecs/vp8_temporal_layers.h"
     25 #include "common_video/generic_frame_descriptor/generic_frame_info.h"
     26 #include "modules/video_coding/codecs/interface/common_constants.h"
     27 #include "modules/video_coding/codecs/vp8/include/temporal_layers_checker.h"
     28 #include "modules/video_coding/include/video_codec_interface.h"
     29 #include "rtc_base/checks.h"
     30 #include "rtc_base/logging.h"
     31 #include "system_wrappers/include/metrics.h"
     32 
     33 namespace webrtc {
     34 namespace {
     35 using BufferFlags = Vp8FrameConfig::BufferFlags;
     36 
     37 constexpr BufferFlags kNone = Vp8FrameConfig::BufferFlags::kNone;
     38 constexpr BufferFlags kReference = Vp8FrameConfig::BufferFlags::kReference;
     39 constexpr BufferFlags kUpdate = Vp8FrameConfig::BufferFlags::kUpdate;
     40 constexpr BufferFlags kReferenceAndUpdate =
     41    Vp8FrameConfig::BufferFlags::kReferenceAndUpdate;
     42 
     43 constexpr int kOneSecond90Khz = 90000;
     44 constexpr int kMinTimeBetweenSyncs = kOneSecond90Khz * 2;
     45 constexpr int kMaxTimeBetweenSyncs = kOneSecond90Khz * 4;
     46 constexpr int kQpDeltaThresholdForSync = 8;
     47 constexpr int kMinBitrateKbpsForQpBoost = 500;
     48 constexpr auto kSwitch = DecodeTargetIndication::kSwitch;
     49 }  // namespace
     50 
     51 const double ScreenshareLayers::kMaxTL0FpsReduction = 2.5;
     52 const double ScreenshareLayers::kAcceptableTargetOvershoot = 2.0;
     53 
     54 // Always emit a frame with certain interval, even if bitrate targets have
     55 // been exceeded. This prevents needless keyframe requests.
     56 const int ScreenshareLayers::kMaxFrameIntervalMs = 2750;
     57 
     58 ScreenshareLayers::ScreenshareLayers(const Environment& env,
     59                                     int num_temporal_layers)
     60    : env_(env),
     61      number_of_temporal_layers_(
     62          std::min(kMaxNumTemporalLayers, num_temporal_layers)),
     63      active_layer_(-1),
     64      last_timestamp_(-1),
     65      last_sync_timestamp_(-1),
     66      last_emitted_tl0_timestamp_(-1),
     67      last_frame_time_ms_(-1),
     68      max_debt_bytes_(0),
     69      encode_framerate_(1000.0f, 1000.0f),  // 1 second window, second scale.
     70      bitrate_updated_(false),
     71      checker_(TemporalLayersChecker::CreateTemporalLayersChecker(
     72          Vp8TemporalLayersType::kBitrateDynamic,
     73          num_temporal_layers)) {
     74  RTC_CHECK_GT(number_of_temporal_layers_, 0);
     75  RTC_CHECK_LE(number_of_temporal_layers_, kMaxNumTemporalLayers);
     76 }
     77 
     78 ScreenshareLayers::~ScreenshareLayers() {
     79  UpdateHistograms();
     80 }
     81 
     82 void ScreenshareLayers::SetQpLimits(size_t stream_index,
     83                                    int min_qp,
     84                                    int max_qp) {
     85  RTC_DCHECK_LT(stream_index, StreamCount());
     86  // 0 < min_qp <= max_qp
     87  RTC_DCHECK_LT(0, min_qp);
     88  RTC_DCHECK_LE(min_qp, max_qp);
     89 
     90  RTC_DCHECK_EQ(min_qp_.has_value(), max_qp_.has_value());
     91  if (!min_qp_.has_value()) {
     92    min_qp_ = min_qp;
     93    max_qp_ = max_qp;
     94  } else {
     95    RTC_DCHECK_EQ(min_qp, min_qp_.value());
     96    RTC_DCHECK_EQ(max_qp, max_qp_.value());
     97  }
     98 }
     99 
    100 size_t ScreenshareLayers::StreamCount() const {
    101  return 1;
    102 }
    103 
    104 bool ScreenshareLayers::SupportsEncoderFrameDropping(
    105    size_t stream_index) const {
    106  RTC_DCHECK_LT(stream_index, StreamCount());
    107  // Frame dropping is handled internally by this class.
    108  return false;
    109 }
    110 
    111 Vp8FrameConfig ScreenshareLayers::NextFrameConfig(size_t stream_index,
    112                                                  uint32_t timestamp) {
    113  RTC_DCHECK_LT(stream_index, StreamCount());
    114 
    115  auto it = pending_frame_configs_.find(timestamp);
    116  if (it != pending_frame_configs_.end()) {
    117    // Drop and re-encode, reuse the previous config.
    118    return it->second.frame_config;
    119  }
    120 
    121  if (number_of_temporal_layers_ <= 1) {
    122    // No flags needed for 1 layer screenshare.
    123    // TODO(pbos): Consider updating only last, and not all buffers.
    124    DependencyInfo dependency_info{
    125        "S", {kReferenceAndUpdate, kReferenceAndUpdate, kReferenceAndUpdate}};
    126    pending_frame_configs_[timestamp] = dependency_info;
    127    return dependency_info.frame_config;
    128  }
    129 
    130  const int64_t now_ms = env_.clock().TimeInMilliseconds();
    131 
    132  int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(timestamp);
    133  int64_t ts_diff;
    134  if (last_timestamp_ == -1) {
    135    ts_diff = kOneSecond90Khz / capture_framerate_.value_or(*target_framerate_);
    136  } else {
    137    ts_diff = unwrapped_timestamp - last_timestamp_;
    138  }
    139 
    140  if (target_framerate_) {
    141    // If input frame rate exceeds target frame rate, either over a one second
    142    // averaging window, or if frame interval is below 90% of desired value,
    143    // drop frame.
    144    if (encode_framerate_.Rate(now_ms).value_or(0) > *target_framerate_)
    145      return Vp8FrameConfig(kNone, kNone, kNone);
    146 
    147    // Primarily check if frame interval is too short using frame timestamps,
    148    // as if they are correct they won't be affected by queuing in webrtc.
    149    const int64_t expected_frame_interval_90khz =
    150        kOneSecond90Khz / *target_framerate_;
    151    if (last_timestamp_ != -1 && ts_diff > 0) {
    152      if (ts_diff < 85 * expected_frame_interval_90khz / 100) {
    153        return Vp8FrameConfig(kNone, kNone, kNone);
    154      }
    155    } else {
    156      // Timestamps looks off, use realtime clock here instead.
    157      const int64_t expected_frame_interval_ms = 1000 / *target_framerate_;
    158      if (last_frame_time_ms_ != -1 &&
    159          now_ms - last_frame_time_ms_ <
    160              (85 * expected_frame_interval_ms) / 100) {
    161        return Vp8FrameConfig(kNone, kNone, kNone);
    162      }
    163    }
    164  }
    165 
    166  if (stats_.first_frame_time_ms_ == -1)
    167    stats_.first_frame_time_ms_ = now_ms;
    168 
    169  // Make sure both frame droppers leak out bits.
    170  layers_[0].UpdateDebt(ts_diff / 90);
    171  layers_[1].UpdateDebt(ts_diff / 90);
    172  last_timestamp_ = timestamp;
    173  last_frame_time_ms_ = now_ms;
    174 
    175  TemporalLayerState layer_state = TemporalLayerState::kDrop;
    176 
    177  if (active_layer_ == -1 ||
    178      layers_[active_layer_].state != TemporalLayer::State::kDropped) {
    179    if (last_emitted_tl0_timestamp_ != -1 &&
    180        (unwrapped_timestamp - last_emitted_tl0_timestamp_) / 90 >
    181            kMaxFrameIntervalMs) {
    182      // Too long time has passed since the last frame was emitted, cancel
    183      // enough debt to allow a single frame.
    184      layers_[0].debt_bytes_ = max_debt_bytes_ - 1;
    185    }
    186    if (layers_[0].debt_bytes_ > max_debt_bytes_) {
    187      // Must drop TL0, encode TL1 instead.
    188      if (layers_[1].debt_bytes_ > max_debt_bytes_) {
    189        // Must drop both TL0 and TL1.
    190        active_layer_ = -1;
    191      } else {
    192        active_layer_ = 1;
    193      }
    194    } else {
    195      active_layer_ = 0;
    196    }
    197  }
    198 
    199  switch (active_layer_) {
    200    case 0:
    201      layer_state = TemporalLayerState::kTl0;
    202      last_emitted_tl0_timestamp_ = unwrapped_timestamp;
    203      break;
    204    case 1:
    205      if (layers_[1].state != TemporalLayer::State::kDropped) {
    206        if (TimeToSync(unwrapped_timestamp) ||
    207            layers_[1].state == TemporalLayer::State::kKeyFrame) {
    208          last_sync_timestamp_ = unwrapped_timestamp;
    209          layer_state = TemporalLayerState::kTl1Sync;
    210        } else {
    211          layer_state = TemporalLayerState::kTl1;
    212        }
    213      } else {
    214        layer_state = last_sync_timestamp_ == unwrapped_timestamp
    215                          ? TemporalLayerState::kTl1Sync
    216                          : TemporalLayerState::kTl1;
    217      }
    218      break;
    219    case -1:
    220      layer_state = TemporalLayerState::kDrop;
    221      ++stats_.num_dropped_frames_;
    222      break;
    223    default:
    224      RTC_DCHECK_NOTREACHED();
    225  }
    226 
    227  DependencyInfo dependency_info;
    228  // TODO(pbos): Consider referencing but not updating the 'alt' buffer for all
    229  // layers.
    230  switch (layer_state) {
    231    case TemporalLayerState::kDrop:
    232      dependency_info = {"", {kNone, kNone, kNone}};
    233      break;
    234    case TemporalLayerState::kTl0:
    235      // TL0 only references and updates 'last'.
    236      dependency_info = {"SS", {kReferenceAndUpdate, kNone, kNone}};
    237      dependency_info.frame_config.packetizer_temporal_idx = 0;
    238      break;
    239    case TemporalLayerState::kTl1:
    240      // TL1 references both 'last' and 'golden' but only updates 'golden'.
    241      dependency_info = {"-R", {kReference, kReferenceAndUpdate, kNone}};
    242      dependency_info.frame_config.packetizer_temporal_idx = 1;
    243      break;
    244    case TemporalLayerState::kTl1Sync:
    245      // Predict from only TL0 to allow participants to switch to the high
    246      // bitrate stream. Updates 'golden' so that TL1 can continue to refer to
    247      // and update 'golden' from this point on.
    248      dependency_info = {"-S", {kReference, kUpdate, kNone}};
    249      dependency_info.frame_config.packetizer_temporal_idx = 1;
    250      dependency_info.frame_config.layer_sync = true;
    251      break;
    252  }
    253 
    254  pending_frame_configs_[timestamp] = dependency_info;
    255  return dependency_info.frame_config;
    256 }
    257 
    258 void ScreenshareLayers::OnRatesUpdated(
    259    size_t stream_index,
    260    const std::vector<uint32_t>& bitrates_bps,
    261    int framerate_fps) {
    262  RTC_DCHECK_LT(stream_index, StreamCount());
    263  RTC_DCHECK_GT(framerate_fps, 0);
    264  RTC_DCHECK_GE(bitrates_bps.size(), 1);
    265  RTC_DCHECK_LE(bitrates_bps.size(), 2);
    266 
    267  // `bitrates_bps` uses individual rates per layer, but we want to use the
    268  // accumulated rate here.
    269  uint32_t tl0_kbps = bitrates_bps[0] / 1000;
    270  uint32_t tl1_kbps = tl0_kbps;
    271  if (bitrates_bps.size() > 1) {
    272    tl1_kbps += bitrates_bps[1] / 1000;
    273  }
    274 
    275  if (!target_framerate_) {
    276    // First OnRatesUpdated() is called during construction, with the
    277    // configured targets as parameters.
    278    target_framerate_ = framerate_fps;
    279    capture_framerate_ = target_framerate_;
    280    bitrate_updated_ = true;
    281  } else {
    282    if ((capture_framerate_ &&
    283         framerate_fps != static_cast<int>(*capture_framerate_)) ||
    284        (tl0_kbps != layers_[0].target_rate_kbps_) ||
    285        (tl1_kbps != layers_[1].target_rate_kbps_)) {
    286      bitrate_updated_ = true;
    287    }
    288 
    289    if (framerate_fps < 0) {
    290      capture_framerate_.reset();
    291    } else {
    292      capture_framerate_ = framerate_fps;
    293    }
    294  }
    295 
    296  layers_[0].target_rate_kbps_ = tl0_kbps;
    297  layers_[1].target_rate_kbps_ = tl1_kbps;
    298 }
    299 
    300 void ScreenshareLayers::OnEncodeDone(size_t stream_index,
    301                                     uint32_t rtp_timestamp,
    302                                     size_t size_bytes,
    303                                     bool is_keyframe,
    304                                     int qp,
    305                                     CodecSpecificInfo* info) {
    306  RTC_DCHECK_LT(stream_index, StreamCount());
    307 
    308  if (size_bytes == 0) {
    309    RTC_LOG(LS_WARNING) << "Empty frame; treating as dropped.";
    310    OnFrameDropped(stream_index, rtp_timestamp);
    311    return;
    312  }
    313 
    314  std::optional<DependencyInfo> dependency_info;
    315  auto it = pending_frame_configs_.find(rtp_timestamp);
    316  if (it != pending_frame_configs_.end()) {
    317    dependency_info = it->second;
    318    pending_frame_configs_.erase(it);
    319 
    320    if (checker_) {
    321      RTC_DCHECK(checker_->CheckTemporalConfig(is_keyframe,
    322                                               dependency_info->frame_config));
    323    }
    324  }
    325 
    326  CodecSpecificInfoVP8& vp8_info = info->codecSpecific.VP8;
    327  GenericFrameInfo& generic_frame_info = info->generic_frame_info.emplace();
    328 
    329  if (number_of_temporal_layers_ == 1) {
    330    vp8_info.temporalIdx = kNoTemporalIdx;
    331    vp8_info.layerSync = false;
    332    generic_frame_info.temporal_id = 0;
    333    generic_frame_info.decode_target_indications = {kSwitch};
    334    generic_frame_info.encoder_buffers.emplace_back(
    335        0, /*referenced=*/!is_keyframe, /*updated=*/true);
    336  } else {
    337    int64_t unwrapped_timestamp = time_wrap_handler_.Unwrap(rtp_timestamp);
    338    if (dependency_info) {
    339      vp8_info.temporalIdx =
    340          dependency_info->frame_config.packetizer_temporal_idx;
    341      vp8_info.layerSync = dependency_info->frame_config.layer_sync;
    342      generic_frame_info.temporal_id = vp8_info.temporalIdx;
    343      generic_frame_info.decode_target_indications =
    344          dependency_info->decode_target_indications;
    345    } else {
    346      RTC_DCHECK(is_keyframe);
    347    }
    348 
    349    if (is_keyframe) {
    350      vp8_info.temporalIdx = 0;
    351      last_sync_timestamp_ = unwrapped_timestamp;
    352      vp8_info.layerSync = true;
    353      layers_[0].state = TemporalLayer::State::kKeyFrame;
    354      layers_[1].state = TemporalLayer::State::kKeyFrame;
    355      active_layer_ = 1;
    356      info->template_structure =
    357          GetTemplateStructure(number_of_temporal_layers_);
    358      generic_frame_info.temporal_id = vp8_info.temporalIdx;
    359      generic_frame_info.decode_target_indications = {kSwitch, kSwitch};
    360    } else if (active_layer_ >= 0 && layers_[active_layer_].state ==
    361                                         TemporalLayer::State::kKeyFrame) {
    362      layers_[active_layer_].state = TemporalLayer::State::kNormal;
    363    }
    364 
    365    vp8_info.useExplicitDependencies = true;
    366    RTC_DCHECK_EQ(vp8_info.referencedBuffersCount, 0u);
    367    RTC_DCHECK_EQ(vp8_info.updatedBuffersCount, 0u);
    368 
    369    // Note that `frame_config` is not derefernced if `is_keyframe`,
    370    // meaning it's never dereferenced if the optional may be unset.
    371    for (int i = 0; i < static_cast<int>(Vp8FrameConfig::Buffer::kCount); ++i) {
    372      bool references = false;
    373      bool updates = is_keyframe;
    374      if (!is_keyframe && dependency_info->frame_config.References(
    375                              static_cast<Vp8FrameConfig::Buffer>(i))) {
    376        RTC_DCHECK_LT(vp8_info.referencedBuffersCount,
    377                      std::size(vp8_info.referencedBuffers));
    378        references = true;
    379        vp8_info.referencedBuffers[vp8_info.referencedBuffersCount++] = i;
    380      }
    381 
    382      if (is_keyframe || dependency_info->frame_config.Updates(
    383                             static_cast<Vp8FrameConfig::Buffer>(i))) {
    384        RTC_DCHECK_LT(vp8_info.updatedBuffersCount,
    385                      std::size(vp8_info.updatedBuffers));
    386        updates = true;
    387        vp8_info.updatedBuffers[vp8_info.updatedBuffersCount++] = i;
    388      }
    389 
    390      if (references || updates)
    391        generic_frame_info.encoder_buffers.emplace_back(i, references, updates);
    392    }
    393  }
    394 
    395  encode_framerate_.Update(1, env_.clock().TimeInMilliseconds());
    396 
    397  if (number_of_temporal_layers_ == 1)
    398    return;
    399 
    400  RTC_DCHECK_NE(-1, active_layer_);
    401  if (layers_[active_layer_].state == TemporalLayer::State::kDropped) {
    402    layers_[active_layer_].state = TemporalLayer::State::kQualityBoost;
    403  }
    404 
    405  if (qp != -1)
    406    layers_[active_layer_].last_qp = qp;
    407 
    408  if (active_layer_ == 0) {
    409    layers_[0].debt_bytes_ += size_bytes;
    410    layers_[1].debt_bytes_ += size_bytes;
    411    ++stats_.num_tl0_frames_;
    412    stats_.tl0_target_bitrate_sum_ += layers_[0].target_rate_kbps_;
    413    stats_.tl0_qp_sum_ += qp;
    414  } else if (active_layer_ == 1) {
    415    layers_[1].debt_bytes_ += size_bytes;
    416    ++stats_.num_tl1_frames_;
    417    stats_.tl1_target_bitrate_sum_ += layers_[1].target_rate_kbps_;
    418    stats_.tl1_qp_sum_ += qp;
    419  }
    420 }
    421 
    422 void ScreenshareLayers::OnFrameDropped(size_t /* stream_index */,
    423                                       uint32_t /* rtp_timestamp */) {
    424  layers_[active_layer_].state = TemporalLayer::State::kDropped;
    425  ++stats_.num_overshoots_;
    426 }
    427 
    428 void ScreenshareLayers::OnPacketLossRateUpdate(float /* packet_loss_rate */) {}
    429 
    430 void ScreenshareLayers::OnRttUpdate(int64_t /* rtt_ms */) {}
    431 
    432 void ScreenshareLayers::OnLossNotification(
    433    const VideoEncoder::LossNotification& /* loss_notification */) {}
    434 
    435 FrameDependencyStructure ScreenshareLayers::GetTemplateStructure(
    436    int num_layers) const {
    437  RTC_CHECK_LT(num_layers, 3);
    438  RTC_CHECK_GT(num_layers, 0);
    439 
    440  FrameDependencyStructure template_structure;
    441  template_structure.num_decode_targets = num_layers;
    442 
    443  switch (num_layers) {
    444    case 1: {
    445      template_structure.templates.resize(2);
    446      template_structure.templates[0].T(0).Dtis("S");
    447      template_structure.templates[1].T(0).Dtis("S").FrameDiffs({1});
    448      return template_structure;
    449    }
    450    case 2: {
    451      template_structure.templates.resize(3);
    452      template_structure.templates[0].T(0).Dtis("SS");
    453      template_structure.templates[1].T(0).Dtis("SS").FrameDiffs({1});
    454      template_structure.templates[2].T(1).Dtis("-S").FrameDiffs({1});
    455      return template_structure;
    456    }
    457    default:
    458      RTC_DCHECK_NOTREACHED();
    459      // To make the compiler happy!
    460      return template_structure;
    461  }
    462 }
    463 
    464 bool ScreenshareLayers::TimeToSync(int64_t timestamp) const {
    465  RTC_DCHECK_EQ(1, active_layer_);
    466  RTC_DCHECK_NE(-1, layers_[0].last_qp);
    467  if (layers_[1].last_qp == -1) {
    468    // First frame in TL1 should only depend on TL0 since there are no
    469    // previous frames in TL1.
    470    return true;
    471  }
    472 
    473  RTC_DCHECK_NE(-1, last_sync_timestamp_);
    474  int64_t timestamp_diff = timestamp - last_sync_timestamp_;
    475  if (timestamp_diff > kMaxTimeBetweenSyncs) {
    476    // After a certain time, force a sync frame.
    477    return true;
    478  } else if (timestamp_diff < kMinTimeBetweenSyncs) {
    479    // If too soon from previous sync frame, don't issue a new one.
    480    return false;
    481  }
    482  // Issue a sync frame if difference in quality between TL0 and TL1 isn't too
    483  // large.
    484  if (layers_[0].last_qp - layers_[1].last_qp < kQpDeltaThresholdForSync)
    485    return true;
    486  return false;
    487 }
    488 
    489 uint32_t ScreenshareLayers::GetCodecTargetBitrateKbps() const {
    490  uint32_t target_bitrate_kbps = layers_[0].target_rate_kbps_;
    491 
    492  if (number_of_temporal_layers_ > 1) {
    493    // Calculate a codec target bitrate. This may be higher than TL0, gaining
    494    // quality at the expense of frame rate at TL0. Constraints:
    495    // - TL0 frame rate no less than framerate / kMaxTL0FpsReduction.
    496    // - Target rate * kAcceptableTargetOvershoot should not exceed TL1 rate.
    497    target_bitrate_kbps =
    498        std::min(layers_[0].target_rate_kbps_ * kMaxTL0FpsReduction,
    499                 layers_[1].target_rate_kbps_ / kAcceptableTargetOvershoot);
    500  }
    501 
    502  return std::max(layers_[0].target_rate_kbps_, target_bitrate_kbps);
    503 }
    504 
    505 Vp8EncoderConfig ScreenshareLayers::UpdateConfiguration(size_t stream_index) {
    506  RTC_DCHECK_LT(stream_index, StreamCount());
    507  RTC_DCHECK(min_qp_.has_value());
    508  RTC_DCHECK(max_qp_.has_value());
    509 
    510  const uint32_t target_bitrate_kbps = GetCodecTargetBitrateKbps();
    511 
    512  // TODO(sprang): We _really_ need to make an overhaul of this class. :(
    513  // If we're dropping frames in order to meet a target framerate, adjust the
    514  // bitrate assigned to the encoder so the total average bitrate is correct.
    515  float encoder_config_bitrate_kbps = target_bitrate_kbps;
    516  if (target_framerate_ && capture_framerate_ &&
    517      *target_framerate_ < *capture_framerate_) {
    518    encoder_config_bitrate_kbps *=
    519        static_cast<float>(*capture_framerate_) / *target_framerate_;
    520  }
    521 
    522  if (bitrate_updated_ || encoder_config_.rc_target_bitrate !=
    523                              std::make_optional(encoder_config_bitrate_kbps)) {
    524    encoder_config_.rc_target_bitrate = encoder_config_bitrate_kbps;
    525 
    526    // Don't reconfigure qp limits during quality boost frames.
    527    if (active_layer_ == -1 ||
    528        layers_[active_layer_].state != TemporalLayer::State::kQualityBoost) {
    529      const int min_qp = min_qp_.value();
    530      const int max_qp = max_qp_.value();
    531 
    532      // After a dropped frame, a frame with max qp will be encoded and the
    533      // quality will then ramp up from there. To boost the speed of recovery,
    534      // encode the next frame with lower max qp, if there is sufficient
    535      // bandwidth to do so without causing excessive delay.
    536      // TL0 is the most important to improve since the errors in this layer
    537      // will propagate to TL1.
    538      // Currently, reduce max qp by 20% for TL0 and 15% for TL1.
    539      if (layers_[1].target_rate_kbps_ >= kMinBitrateKbpsForQpBoost) {
    540        layers_[0].enhanced_max_qp = min_qp + (((max_qp - min_qp) * 80) / 100);
    541        layers_[1].enhanced_max_qp = min_qp + (((max_qp - min_qp) * 85) / 100);
    542      } else {
    543        layers_[0].enhanced_max_qp = -1;
    544        layers_[1].enhanced_max_qp = -1;
    545      }
    546    }
    547 
    548    if (capture_framerate_) {
    549      int avg_frame_size =
    550          (target_bitrate_kbps * 1000) / (8 * *capture_framerate_);
    551      // Allow max debt to be the size of a single optimal frame.
    552      // TODO(sprang): Determine if this needs to be adjusted by some factor.
    553      // (Lower values may cause more frame drops, higher may lead to queuing
    554      // delays.)
    555      max_debt_bytes_ = avg_frame_size;
    556    }
    557 
    558    bitrate_updated_ = false;
    559  }
    560 
    561  // Don't try to update boosts state if not active yet.
    562  if (active_layer_ == -1)
    563    return encoder_config_;
    564 
    565  if (number_of_temporal_layers_ <= 1)
    566    return encoder_config_;
    567 
    568  // If layer is in the quality boost state (following a dropped frame), update
    569  // the configuration with the adjusted (lower) qp and set the state back to
    570  // normal.
    571  unsigned int adjusted_max_qp = max_qp_.value();  // Set the normal max qp.
    572  if (layers_[active_layer_].state == TemporalLayer::State::kQualityBoost) {
    573    if (layers_[active_layer_].enhanced_max_qp != -1) {
    574      // Bitrate is high enough for quality boost, update max qp.
    575      adjusted_max_qp = layers_[active_layer_].enhanced_max_qp;
    576    }
    577    // Regardless of qp, reset the boost state for the next frame.
    578    layers_[active_layer_].state = TemporalLayer::State::kNormal;
    579  }
    580  encoder_config_.rc_max_quantizer = adjusted_max_qp;
    581 
    582  return encoder_config_;
    583 }
    584 
    585 void ScreenshareLayers::TemporalLayer::UpdateDebt(int64_t delta_ms) {
    586  uint32_t debt_reduction_bytes = target_rate_kbps_ * delta_ms / 8;
    587  if (debt_reduction_bytes >= debt_bytes_) {
    588    debt_bytes_ = 0;
    589  } else {
    590    debt_bytes_ -= debt_reduction_bytes;
    591  }
    592 }
    593 
    594 void ScreenshareLayers::UpdateHistograms() {
    595  if (stats_.first_frame_time_ms_ == -1)
    596    return;
    597  int64_t duration_sec =
    598      (env_.clock().TimeInMilliseconds() - stats_.first_frame_time_ms_ + 500) /
    599      1000;
    600  if (duration_sec >= metrics::kMinRunTime.seconds()) {
    601    RTC_HISTOGRAM_COUNTS_10000(
    602        "WebRTC.Video.Screenshare.Layer0.FrameRate",
    603        (stats_.num_tl0_frames_ + (duration_sec / 2)) / duration_sec);
    604    RTC_HISTOGRAM_COUNTS_10000(
    605        "WebRTC.Video.Screenshare.Layer1.FrameRate",
    606        (stats_.num_tl1_frames_ + (duration_sec / 2)) / duration_sec);
    607    int total_frames = stats_.num_tl0_frames_ + stats_.num_tl1_frames_;
    608    RTC_HISTOGRAM_COUNTS_10000(
    609        "WebRTC.Video.Screenshare.FramesPerDrop",
    610        (stats_.num_dropped_frames_ == 0
    611             ? 0
    612             : total_frames / stats_.num_dropped_frames_));
    613    RTC_HISTOGRAM_COUNTS_10000(
    614        "WebRTC.Video.Screenshare.FramesPerOvershoot",
    615        (stats_.num_overshoots_ == 0 ? 0
    616                                     : total_frames / stats_.num_overshoots_));
    617    if (stats_.num_tl0_frames_ > 0) {
    618      RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer0.Qp",
    619                                 stats_.tl0_qp_sum_ / stats_.num_tl0_frames_);
    620      RTC_HISTOGRAM_COUNTS_10000(
    621          "WebRTC.Video.Screenshare.Layer0.TargetBitrate",
    622          stats_.tl0_target_bitrate_sum_ / stats_.num_tl0_frames_);
    623    }
    624    if (stats_.num_tl1_frames_ > 0) {
    625      RTC_HISTOGRAM_COUNTS_10000("WebRTC.Video.Screenshare.Layer1.Qp",
    626                                 stats_.tl1_qp_sum_ / stats_.num_tl1_frames_);
    627      RTC_HISTOGRAM_COUNTS_10000(
    628          "WebRTC.Video.Screenshare.Layer1.TargetBitrate",
    629          stats_.tl1_target_bitrate_sum_ / stats_.num_tl1_frames_);
    630    }
    631  }
    632 }
    633 }  // namespace webrtc