/*
 *  Copyright 2020 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "call/adaptation/video_stream_adapter.h"

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <optional>
#include <utility>
#include <variant>

#include "api/adaptation/resource.h"
#include "api/field_trials_view.h"
#include "api/rtp_parameters.h"
#include "api/scoped_refptr.h"
#include "api/sequence_checker.h"
#include "api/video/video_adaptation_counters.h"
#include "api/video/video_codec_type.h"
#include "api/video_codecs/video_codec.h"
#include "call/adaptation/adaptation_constraint.h"
#include "call/adaptation/video_source_restrictions.h"
#include "call/adaptation/video_stream_input_state.h"
#include "call/adaptation/video_stream_input_state_provider.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "video/video_stream_encoder_observer.h"

namespace webrtc {

const int kMinFrameRateFps = 2;

namespace {

// For frame rate, the steps we take are 2/3 (down) and 3/2 (up).
int GetLowerFrameRateThan(int fps) {
  RTC_DCHECK(fps != std::numeric_limits<int>::max());
  return (fps * 2) / 3;
}
// TODO(hbos): Use std::optional<> instead?
int GetHigherFrameRateThan(int fps) {
  return fps != std::numeric_limits<int>::max()
             ? (fps * 3) / 2
             : std::numeric_limits<int>::max();
}

int GetIncreasedMaxPixelsWanted(int target_pixels) {
  if (target_pixels == std::numeric_limits<int>::max())
    return std::numeric_limits<int>::max();
  // When we decrease resolution, we go down to at most 3/5 of current pixels.
  // Thus to increase resolution, we need 3/5 to get back to where we started.
  // When going up, the desired max_pixels_per_frame() has to be significantly
  // higher than the target because the source's native resolutions might not
  // match the target. We pick 12/5 of the target.
  //
  // (This value was historically 4 times the old target, which is (3/5)*4 of
  // the new target - or 12/5 - assuming the target is adjusted according to
  // the above steps.)
  RTC_DCHECK(target_pixels != std::numeric_limits<int>::max());
  return (target_pixels * 12) / 5;
}

bool CanDecreaseResolutionTo(int target_pixels,
                             int target_pixels_min,
                             const VideoStreamInputState& input_state,
                             const VideoSourceRestrictions& restrictions) {
  int max_pixels_per_frame =
      dchecked_cast<int>(restrictions.max_pixels_per_frame().value_or(
          std::numeric_limits<int>::max()));
  return target_pixels < max_pixels_per_frame &&
         target_pixels_min >= input_state.min_pixels_per_frame();
}

bool CanIncreaseResolutionTo(int target_pixels,
                             const VideoSourceRestrictions& restrictions) {
  int max_pixels_wanted = GetIncreasedMaxPixelsWanted(target_pixels);
  int max_pixels_per_frame =
      dchecked_cast<int>(restrictions.max_pixels_per_frame().value_or(
          std::numeric_limits<int>::max()));
  return max_pixels_wanted > max_pixels_per_frame;
}

bool CanDecreaseFrameRateTo(int max_frame_rate,
                            const VideoSourceRestrictions& restrictions) {
  const int fps_wanted = std::max(kMinFrameRateFps, max_frame_rate);
  return fps_wanted < dchecked_cast<int>(restrictions.max_frame_rate().value_or(
                          std::numeric_limits<int>::max()));
}

bool CanIncreaseFrameRateTo(int max_frame_rate,
                            const VideoSourceRestrictions& restrictions) {
  return max_frame_rate >
         dchecked_cast<int>(restrictions.max_frame_rate().value_or(
             std::numeric_limits<int>::max()));
}

bool MinPixelLimitReached(const VideoStreamInputState& input_state) {
  if (input_state.single_active_stream_pixels().has_value()) {
    return GetLowerResolutionThan(
               input_state.single_active_stream_pixels().value()) <
           input_state.min_pixels_per_frame();
  }
  return input_state.frame_size_pixels().has_value() &&
         GetLowerResolutionThan(input_state.frame_size_pixels().value()) <
             input_state.min_pixels_per_frame();
}

}  // namespace

VideoSourceRestrictionsListener::~VideoSourceRestrictionsListener() = default;

VideoSourceRestrictions FilterRestrictionsByDegradationPreference(
    VideoSourceRestrictions source_restrictions,
    DegradationPreference degradation_preference) {
  switch (degradation_preference) {
    case DegradationPreference::BALANCED:
      break;
    case DegradationPreference::MAINTAIN_FRAMERATE:
      source_restrictions.set_max_frame_rate(std::nullopt);
      break;
    case DegradationPreference::MAINTAIN_RESOLUTION:
      source_restrictions.set_max_pixels_per_frame(std::nullopt);
      source_restrictions.set_target_pixels_per_frame(std::nullopt);
      break;
    case DegradationPreference::MAINTAIN_FRAMERATE_AND_RESOLUTION:
      source_restrictions.set_max_pixels_per_frame(std::nullopt);
      source_restrictions.set_target_pixels_per_frame(std::nullopt);
      source_restrictions.set_max_frame_rate(std::nullopt);
  }
  return source_restrictions;
}

// For resolution, the steps we take are 3/5 (down) and 5/3 (up).
// Notice the asymmetry of which restriction property is set depending on if
// we are adapting up or down:
// - VideoSourceRestrictor::DecreaseResolution() sets the max_pixels_per_frame()
//   to the desired target and target_pixels_per_frame() to null.
// - VideoSourceRestrictor::IncreaseResolutionTo() sets the
//   target_pixels_per_frame() to the desired target, and max_pixels_per_frame()
//   is set according to VideoSourceRestrictor::GetIncreasedMaxPixelsWanted().
int GetLowerResolutionThan(int pixel_count) {
  RTC_DCHECK(pixel_count != std::numeric_limits<int>::max());
  return (pixel_count * 3) / 5;
}

// TODO(hbos): Use std::optional<> instead?
int GetHigherResolutionThan(int pixel_count) {
  return pixel_count != std::numeric_limits<int>::max()
             ? (pixel_count * 5) / 3
             : std::numeric_limits<int>::max();
}

// static
const char* Adaptation::StatusToString(Adaptation::Status status) {
  switch (status) {
    case Adaptation::Status::kValid:
      return "kValid";
    case Adaptation::Status::kLimitReached:
      return "kLimitReached";
    case Adaptation::Status::kAwaitingPreviousAdaptation:
      return "kAwaitingPreviousAdaptation";
    case Status::kInsufficientInput:
      return "kInsufficientInput";
    case Status::kAdaptationDisabled:
      return "kAdaptationDisabled";
    case Status::kRejectedByConstraint:
      return "kRejectedByConstraint";
  }
  RTC_CHECK_NOTREACHED();
}

Adaptation::Adaptation(int validation_id,
                       VideoSourceRestrictions restrictions,
                       VideoAdaptationCounters counters,
                       VideoStreamInputState input_state)
    : validation_id_(validation_id),
      status_(Status::kValid),
      input_state_(std::move(input_state)),
      restrictions_(std::move(restrictions)),
      counters_(std::move(counters)) {}

Adaptation::Adaptation(int validation_id, Status invalid_status)
    : validation_id_(validation_id), status_(invalid_status) {
  RTC_DCHECK_NE(status_, Status::kValid);
}

Adaptation::Status Adaptation::status() const {
  return status_;
}

const VideoStreamInputState& Adaptation::input_state() const {
  return input_state_;
}

const VideoSourceRestrictions& Adaptation::restrictions() const {
  return restrictions_;
}

const VideoAdaptationCounters& Adaptation::counters() const {
  return counters_;
}

VideoStreamAdapter::VideoStreamAdapter(
    VideoStreamInputStateProvider* input_state_provider,
    VideoStreamEncoderObserver* encoder_stats_observer,
    const FieldTrialsView& field_trials)
    : input_state_provider_(input_state_provider),
      encoder_stats_observer_(encoder_stats_observer),
      balanced_settings_(field_trials),
      adaptation_validation_id_(0),
      degradation_preference_(
          DegradationPreference::MAINTAIN_FRAMERATE_AND_RESOLUTION),
      awaiting_frame_size_change_(std::nullopt) {
  sequence_checker_.Detach();
  RTC_DCHECK(input_state_provider_);
  RTC_DCHECK(encoder_stats_observer_);
}

VideoStreamAdapter::~VideoStreamAdapter() {
  RTC_DCHECK(adaptation_constraints_.empty())
      << "There are constaint(s) attached to a VideoStreamAdapter being "
         "destroyed.";
}

VideoSourceRestrictions VideoStreamAdapter::source_restrictions() const {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  return current_restrictions_.restrictions;
}

const VideoAdaptationCounters& VideoStreamAdapter::adaptation_counters() const {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  return current_restrictions_.counters;
}

void VideoStreamAdapter::ClearRestrictions() {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  // Invalidate any previously returned Adaptation.
  RTC_LOG(LS_INFO) << "Resetting restrictions";
  ++adaptation_validation_id_;
  current_restrictions_ = {.restrictions = VideoSourceRestrictions(),
                           .counters = VideoAdaptationCounters()};
  awaiting_frame_size_change_ = std::nullopt;
  BroadcastVideoRestrictionsUpdate(input_state_provider_->InputState(),
                                   nullptr);
}

void VideoStreamAdapter::AddRestrictionsListener(
    VideoSourceRestrictionsListener* restrictions_listener) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  RTC_DCHECK(std::find(restrictions_listeners_.begin(),
                       restrictions_listeners_.end(),
                       restrictions_listener) == restrictions_listeners_.end());
  restrictions_listeners_.push_back(restrictions_listener);
}

void VideoStreamAdapter::RemoveRestrictionsListener(
    VideoSourceRestrictionsListener* restrictions_listener) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  auto it = std::find(restrictions_listeners_.begin(),
                      restrictions_listeners_.end(), restrictions_listener);
  RTC_DCHECK(it != restrictions_listeners_.end());
  restrictions_listeners_.erase(it);
}

void VideoStreamAdapter::AddAdaptationConstraint(
    AdaptationConstraint* adaptation_constraint) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  RTC_DCHECK(std::find(adaptation_constraints_.begin(),
                       adaptation_constraints_.end(),
                       adaptation_constraint) == adaptation_constraints_.end());
  adaptation_constraints_.push_back(adaptation_constraint);
}

void VideoStreamAdapter::RemoveAdaptationConstraint(
    AdaptationConstraint* adaptation_constraint) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  auto it = std::find(adaptation_constraints_.begin(),
                      adaptation_constraints_.end(), adaptation_constraint);
  RTC_DCHECK(it != adaptation_constraints_.end());
  adaptation_constraints_.erase(it);
}

void VideoStreamAdapter::SetDegradationPreference(
    DegradationPreference degradation_preference) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  if (degradation_preference_ == degradation_preference)
    return;
  // Invalidate any previously returned Adaptation.
  ++adaptation_validation_id_;
  bool balanced_switch =
      degradation_preference == DegradationPreference::BALANCED ||
      degradation_preference_ == DegradationPreference::BALANCED;
  degradation_preference_ = degradation_preference;
  if (balanced_switch) {
    // ClearRestrictions() calls BroadcastVideoRestrictionsUpdate(nullptr).
    ClearRestrictions();
  } else {
    BroadcastVideoRestrictionsUpdate(input_state_provider_->InputState(),
                                     nullptr);
  }
}

struct VideoStreamAdapter::RestrictionsOrStateVisitor {
  Adaptation operator()(const RestrictionsWithCounters& r) const {
    return Adaptation(adaptation_validation_id, r.restrictions, r.counters,
                      input_state);
  }
  Adaptation operator()(const Adaptation::Status& status) const {
    RTC_DCHECK_NE(status, Adaptation::Status::kValid);
    return Adaptation(adaptation_validation_id, status);
  }

  const int adaptation_validation_id;
  const VideoStreamInputState& input_state;
};

Adaptation VideoStreamAdapter::RestrictionsOrStateToAdaptation(
    VideoStreamAdapter::RestrictionsOrState step_or_state,
    const VideoStreamInputState& input_state) const {
  RTC_DCHECK(!step_or_state.valueless_by_exception());
  return std::visit(RestrictionsOrStateVisitor{.adaptation_validation_id =
                                                   adaptation_validation_id_,
                                               .input_state = input_state},
                    step_or_state);
}

Adaptation VideoStreamAdapter::GetAdaptationUp(
    const VideoStreamInputState& input_state) const {
  RestrictionsOrState step = GetAdaptationUpStep(input_state);
  // If an adaptation proposed, check with the constraints that it is ok.
  if (std::holds_alternative<RestrictionsWithCounters>(step)) {
    RestrictionsWithCounters restrictions =
        std::get<RestrictionsWithCounters>(step);
    for (const auto* constraint : adaptation_constraints_) {
      if (!constraint->IsAdaptationUpAllowed(input_state,
                                             current_restrictions_.restrictions,
                                             restrictions.restrictions)) {
        RTC_LOG(LS_INFO) << "Not adapting up because constraint \""
                         << constraint->Name() << "\" disallowed it";
        step = Adaptation::Status::kRejectedByConstraint;
      }
    }
  }
  return RestrictionsOrStateToAdaptation(step, input_state);
}

Adaptation VideoStreamAdapter::GetAdaptationUp() {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  VideoStreamInputState input_state = input_state_provider_->InputState();
  ++adaptation_validation_id_;
  Adaptation adaptation = GetAdaptationUp(input_state);
  return adaptation;
}

VideoStreamAdapter::RestrictionsOrState VideoStreamAdapter::GetAdaptationUpStep(
    const VideoStreamInputState& input_state) const {
  if (!HasSufficientInputForAdaptation(input_state)) {
    return Adaptation::Status::kInsufficientInput;
  }
  // Don't adapt if we're awaiting a previous adaptation to have an effect.
  if (awaiting_frame_size_change_ &&
      awaiting_frame_size_change_->pixels_increased &&
      degradation_preference_ == DegradationPreference::MAINTAIN_FRAMERATE &&
      input_state.frame_size_pixels().value() <=
          awaiting_frame_size_change_->frame_size_pixels) {
    return Adaptation::Status::kAwaitingPreviousAdaptation;
  }

  // Maybe propose targets based on degradation preference.
  switch (degradation_preference_) {
    case DegradationPreference::BALANCED: {
      // Attempt to increase target frame rate.
      RestrictionsOrState increase_frame_rate =
          IncreaseFramerate(input_state, current_restrictions_);
      if (std::holds_alternative<RestrictionsWithCounters>(
              increase_frame_rate)) {
        return increase_frame_rate;
      }
      // else, increase resolution.
      [[fallthrough]];
    }
    case DegradationPreference::MAINTAIN_FRAMERATE: {
      // Attempt to increase pixel count.
      return IncreaseResolution(input_state, current_restrictions_);
    }
    case DegradationPreference::MAINTAIN_RESOLUTION: {
      // Scale up framerate.
      return IncreaseFramerate(input_state, current_restrictions_);
    }
    case DegradationPreference::MAINTAIN_FRAMERATE_AND_RESOLUTION:
      return Adaptation::Status::kAdaptationDisabled;
  }
  RTC_CHECK_NOTREACHED();
}

Adaptation VideoStreamAdapter::GetAdaptationDown() {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  VideoStreamInputState input_state = input_state_provider_->InputState();
  ++adaptation_validation_id_;
  RestrictionsOrState restrictions_or_state =
      GetAdaptationDownStep(input_state, current_restrictions_);
  if (MinPixelLimitReached(input_state)) {
    encoder_stats_observer_->OnMinPixelLimitReached();
  }
  // Check for min_fps
  if (degradation_preference_ == DegradationPreference::BALANCED &&
      std::holds_alternative<RestrictionsWithCounters>(restrictions_or_state)) {
    restrictions_or_state = AdaptIfFpsDiffInsufficient(
        input_state, std::get<RestrictionsWithCounters>(restrictions_or_state));
  }
  return RestrictionsOrStateToAdaptation(restrictions_or_state, input_state);
}

VideoStreamAdapter::RestrictionsOrState
VideoStreamAdapter::AdaptIfFpsDiffInsufficient(
    const VideoStreamInputState& input_state,
    const RestrictionsWithCounters& restrictions) const {
  RTC_DCHECK_EQ(degradation_preference_, DegradationPreference::BALANCED);
  int frame_size_pixels = input_state.single_active_stream_pixels().value_or(
      input_state.frame_size_pixels().value());
  std::optional<int> min_fps_diff =
      balanced_settings_.MinFpsDiff(frame_size_pixels);
  if (current_restrictions_.counters.fps_adaptations <
          restrictions.counters.fps_adaptations &&
      min_fps_diff && input_state.frames_per_second() > 0) {
    int fps_diff = input_state.frames_per_second() -
                   restrictions.restrictions.max_frame_rate().value();
    if (fps_diff < min_fps_diff.value()) {
      return GetAdaptationDownStep(input_state, restrictions);
    }
  }
  return restrictions;
}

VideoStreamAdapter::RestrictionsOrState
VideoStreamAdapter::GetAdaptationDownStep(
    const VideoStreamInputState& input_state,
    const RestrictionsWithCounters& current_restrictions) const {
  if (!HasSufficientInputForAdaptation(input_state)) {
    return Adaptation::Status::kInsufficientInput;
  }
  // Don't adapt if we're awaiting a previous adaptation to have an effect or
  // if we switched degradation preference.
  if (awaiting_frame_size_change_ &&
      !awaiting_frame_size_change_->pixels_increased &&
      degradation_preference_ == DegradationPreference::MAINTAIN_FRAMERATE &&
      input_state.frame_size_pixels().value() >=
          awaiting_frame_size_change_->frame_size_pixels) {
    return Adaptation::Status::kAwaitingPreviousAdaptation;
  }
  // Maybe propose targets based on degradation preference.
  switch (degradation_preference_) {
    case DegradationPreference::BALANCED: {
      // Try scale down framerate, if lower.
      RestrictionsOrState decrease_frame_rate =
          DecreaseFramerate(input_state, current_restrictions);
      if (std::holds_alternative<RestrictionsWithCounters>(
              decrease_frame_rate)) {
        return decrease_frame_rate;
      }
      // else, decrease resolution.
      [[fallthrough]];
    }
    case DegradationPreference::MAINTAIN_FRAMERATE: {
      return DecreaseResolution(input_state, current_restrictions);
    }
    case DegradationPreference::MAINTAIN_RESOLUTION: {
      return DecreaseFramerate(input_state, current_restrictions);
    }
    case DegradationPreference::MAINTAIN_FRAMERATE_AND_RESOLUTION:
      return Adaptation::Status::kAdaptationDisabled;
  }
  RTC_CHECK_NOTREACHED();
}

VideoStreamAdapter::RestrictionsOrState VideoStreamAdapter::DecreaseResolution(
    const VideoStreamInputState& input_state,
    const RestrictionsWithCounters& current_restrictions) {
  int target_pixels =
      GetLowerResolutionThan(input_state.frame_size_pixels().value());
  // Use single active stream if set, this stream could be lower than the input.
  int target_pixels_min =
      GetLowerResolutionThan(input_state.single_active_stream_pixels().value_or(
          input_state.frame_size_pixels().value()));
  if (!CanDecreaseResolutionTo(target_pixels, target_pixels_min, input_state,
                               current_restrictions.restrictions)) {
    return Adaptation::Status::kLimitReached;
  }
  RestrictionsWithCounters new_restrictions = current_restrictions;
  RTC_LOG(LS_INFO) << "Scaling down resolution, max pixels: " << target_pixels;
  new_restrictions.restrictions.set_max_pixels_per_frame(
      target_pixels != std::numeric_limits<int>::max()
          ? std::optional<size_t>(target_pixels)
          : std::nullopt);
  new_restrictions.restrictions.set_target_pixels_per_frame(std::nullopt);
  ++new_restrictions.counters.resolution_adaptations;
  return new_restrictions;
}

VideoStreamAdapter::RestrictionsOrState VideoStreamAdapter::DecreaseFramerate(
    const VideoStreamInputState& input_state,
    const RestrictionsWithCounters& current_restrictions) const {
  int max_frame_rate;
  if (degradation_preference_ == DegradationPreference::MAINTAIN_RESOLUTION) {
    max_frame_rate = GetLowerFrameRateThan(input_state.frames_per_second());
  } else if (degradation_preference_ == DegradationPreference::BALANCED) {
    int frame_size_pixels = input_state.single_active_stream_pixels().value_or(
        input_state.frame_size_pixels().value());
    max_frame_rate = balanced_settings_.MinFps(input_state.video_codec_type(),
                                               frame_size_pixels);
  } else {
    RTC_DCHECK_NOTREACHED();
    max_frame_rate = GetLowerFrameRateThan(input_state.frames_per_second());
  }
  if (!CanDecreaseFrameRateTo(max_frame_rate,
                              current_restrictions.restrictions)) {
    return Adaptation::Status::kLimitReached;
  }
  RestrictionsWithCounters new_restrictions = current_restrictions;
  max_frame_rate = std::max(kMinFrameRateFps, max_frame_rate);
  RTC_LOG(LS_INFO) << "Scaling down framerate: " << max_frame_rate;
  new_restrictions.restrictions.set_max_frame_rate(
      max_frame_rate != std::numeric_limits<int>::max()
          ? std::optional<double>(max_frame_rate)
          : std::nullopt);
  ++new_restrictions.counters.fps_adaptations;
  return new_restrictions;
}

VideoStreamAdapter::RestrictionsOrState VideoStreamAdapter::IncreaseResolution(
    const VideoStreamInputState& input_state,
    const RestrictionsWithCounters& current_restrictions) {
  int target_pixels = input_state.frame_size_pixels().value();
  if (current_restrictions.counters.resolution_adaptations == 1) {
    RTC_LOG(LS_INFO) << "Removing resolution down-scaling setting.";
    target_pixels = std::numeric_limits<int>::max();
  }
  target_pixels = GetHigherResolutionThan(target_pixels);
  if (!CanIncreaseResolutionTo(target_pixels,
                               current_restrictions.restrictions)) {
    return Adaptation::Status::kLimitReached;
  }
  int max_pixels_wanted = GetIncreasedMaxPixelsWanted(target_pixels);
  RestrictionsWithCounters new_restrictions = current_restrictions;
  RTC_LOG(LS_INFO) << "Scaling up resolution, max pixels: "
                   << max_pixels_wanted;
  new_restrictions.restrictions.set_max_pixels_per_frame(
      max_pixels_wanted != std::numeric_limits<int>::max()
          ? std::optional<size_t>(max_pixels_wanted)
          : std::nullopt);
  new_restrictions.restrictions.set_target_pixels_per_frame(
      max_pixels_wanted != std::numeric_limits<int>::max()
          ? std::optional<size_t>(target_pixels)
          : std::nullopt);
  --new_restrictions.counters.resolution_adaptations;
  RTC_DCHECK_GE(new_restrictions.counters.resolution_adaptations, 0);
  return new_restrictions;
}

VideoStreamAdapter::RestrictionsOrState VideoStreamAdapter::IncreaseFramerate(
    const VideoStreamInputState& input_state,
    const RestrictionsWithCounters& current_restrictions) const {
  int max_frame_rate;
  if (degradation_preference_ == DegradationPreference::MAINTAIN_RESOLUTION) {
    max_frame_rate = GetHigherFrameRateThan(input_state.frames_per_second());
  } else if (degradation_preference_ == DegradationPreference::BALANCED) {
    int frame_size_pixels = input_state.single_active_stream_pixels().value_or(
        input_state.frame_size_pixels().value());
    max_frame_rate = balanced_settings_.MaxFps(input_state.video_codec_type(),
                                               frame_size_pixels);
    // Temporary fix for cases when there are fewer framerate adaptation steps
    // up than down. Make number of down/up steps equal.
    if (max_frame_rate == std::numeric_limits<int>::max() &&
        current_restrictions.counters.fps_adaptations > 1) {
      // Do not unrestrict framerate to allow additional adaptation up steps.
      RTC_LOG(LS_INFO) << "Modifying framerate due to remaining fps count.";
      max_frame_rate -= current_restrictions.counters.fps_adaptations;
    }
    // In BALANCED, the max_frame_rate must be checked before proceeding. This
    // is because the MaxFps might be the current Fps and so the balanced
    // settings may want to scale up the resolution.
    if (!CanIncreaseFrameRateTo(max_frame_rate,
                                current_restrictions.restrictions)) {
      return Adaptation::Status::kLimitReached;
    }
  } else {
    RTC_DCHECK_NOTREACHED();
    max_frame_rate = GetHigherFrameRateThan(input_state.frames_per_second());
  }
  if (current_restrictions.counters.fps_adaptations == 1) {
    RTC_LOG(LS_INFO) << "Removing framerate down-scaling setting.";
    max_frame_rate = std::numeric_limits<int>::max();
  }
  if (!CanIncreaseFrameRateTo(max_frame_rate,
                              current_restrictions.restrictions)) {
    return Adaptation::Status::kLimitReached;
  }
  RTC_LOG(LS_INFO) << "Scaling up framerate: " << max_frame_rate;
  RestrictionsWithCounters new_restrictions = current_restrictions;
  new_restrictions.restrictions.set_max_frame_rate(
      max_frame_rate != std::numeric_limits<int>::max()
          ? std::optional<double>(max_frame_rate)
          : std::nullopt);
  --new_restrictions.counters.fps_adaptations;
  RTC_DCHECK_GE(new_restrictions.counters.fps_adaptations, 0);
  return new_restrictions;
}

Adaptation VideoStreamAdapter::GetAdaptDownResolution() {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  VideoStreamInputState input_state = input_state_provider_->InputState();
  switch (degradation_preference_) {
    case DegradationPreference::MAINTAIN_FRAMERATE_AND_RESOLUTION:
      return RestrictionsOrStateToAdaptation(
          Adaptation::Status::kAdaptationDisabled, input_state);
    case DegradationPreference::MAINTAIN_RESOLUTION:
      return RestrictionsOrStateToAdaptation(Adaptation::Status::kLimitReached,
                                             input_state);
    case DegradationPreference::MAINTAIN_FRAMERATE:
      return GetAdaptationDown();
    case DegradationPreference::BALANCED: {
      return RestrictionsOrStateToAdaptation(
          GetAdaptDownResolutionStepForBalanced(input_state), input_state);
    }
  }
  RTC_CHECK_NOTREACHED();
}

VideoStreamAdapter::RestrictionsOrState
VideoStreamAdapter::GetAdaptDownResolutionStepForBalanced(
    const VideoStreamInputState& input_state) const {
  // Adapt twice if the first adaptation did not decrease resolution.
  auto first_step = GetAdaptationDownStep(input_state, current_restrictions_);
  if (!std::holds_alternative<RestrictionsWithCounters>(first_step)) {
    return first_step;
  }
  auto first_restrictions = std::get<RestrictionsWithCounters>(first_step);
  if (first_restrictions.counters.resolution_adaptations >
      current_restrictions_.counters.resolution_adaptations) {
    return first_step;
  }
  // We didn't decrease resolution so force it; amend a resolution resuction
  // to the existing framerate reduction in `first_restrictions`.
  auto second_step = DecreaseResolution(input_state, first_restrictions);
  if (std::holds_alternative<RestrictionsWithCounters>(second_step)) {
    return second_step;
  }
  // If the second step was not successful then settle for the first one.
  return first_step;
}

void VideoStreamAdapter::ApplyAdaptation(const Adaptation& adaptation,
                                         scoped_refptr<Resource> resource) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  RTC_DCHECK_EQ(adaptation.validation_id_, adaptation_validation_id_);
  if (adaptation.status() != Adaptation::Status::kValid)
    return;
  // Remember the input pixels and fps of this adaptation. Used to avoid
  // adapting again before this adaptation has had an effect.
  if (DidIncreaseResolution(current_restrictions_.restrictions,
                            adaptation.restrictions())) {
    awaiting_frame_size_change_.emplace(
        true, adaptation.input_state().frame_size_pixels().value());
  } else if (DidDecreaseResolution(current_restrictions_.restrictions,
                                   adaptation.restrictions())) {
    awaiting_frame_size_change_.emplace(
        false, adaptation.input_state().frame_size_pixels().value());
  } else {
    awaiting_frame_size_change_ = std::nullopt;
  }
  current_restrictions_ = {.restrictions = adaptation.restrictions(),
                           .counters = adaptation.counters()};
  BroadcastVideoRestrictionsUpdate(adaptation.input_state(), resource);
}

Adaptation VideoStreamAdapter::GetAdaptationTo(
    const VideoAdaptationCounters& counters,
    const VideoSourceRestrictions& restrictions) {
  // Adapts up/down from the current levels so counters are equal.
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  VideoStreamInputState input_state = input_state_provider_->InputState();
  return Adaptation(adaptation_validation_id_, restrictions, counters,
                    input_state);
}

void VideoStreamAdapter::BroadcastVideoRestrictionsUpdate(
    const VideoStreamInputState& /* input_state */,
    const scoped_refptr<Resource>& resource) {
  RTC_DCHECK_RUN_ON(&sequence_checker_);
  VideoSourceRestrictions filtered = FilterRestrictionsByDegradationPreference(
      source_restrictions(), degradation_preference_);
  if (last_filtered_restrictions_ == filtered) {
    return;
  }
  for (auto* restrictions_listener : restrictions_listeners_) {
    restrictions_listener->OnVideoSourceRestrictionsUpdated(
        filtered, current_restrictions_.counters, resource,
        source_restrictions());
  }
  last_video_source_restrictions_ = current_restrictions_.restrictions;
  last_filtered_restrictions_ = filtered;
}

bool VideoStreamAdapter::HasSufficientInputForAdaptation(
    const VideoStreamInputState& input_state) const {
  return input_state.HasInputFrameSizeAndFramesPerSecond() &&
         (degradation_preference_ !=
              DegradationPreference::MAINTAIN_RESOLUTION ||
          input_state.frames_per_second() >= kMinFrameRateFps);
}

VideoStreamAdapter::AwaitingFrameSizeChange::AwaitingFrameSizeChange(
    bool pixels_increased,
    int frame_size_pixels)
    : pixels_increased(pixels_increased),
      frame_size_pixels(frame_size_pixels) {}

std::optional<uint32_t> VideoStreamAdapter::GetSingleActiveLayerPixels(
    const VideoCodec& codec) {
  int num_active = 0;
  std::optional<uint32_t> pixels;
  if (codec.numberOfSimulcastStreams > 1 ||
      !(codec.codecType == VideoCodecType::kVideoCodecAV1 ||
        codec.codecType == VideoCodecType::kVideoCodecVP9)) {
    // Simulcast or non-SVC codec.
    for (const auto& stream : codec.simulcastStream) {
      if (stream.active) {
        ++num_active;
        pixels = stream.width * stream.height;
      }
    }
  } else {
    for (const auto& stream : codec.spatialLayers) {
      if (stream.active) {
        ++num_active;
        pixels = stream.width * stream.height;
      }
    }
  }
  return (num_active > 1) ? std::nullopt : pixels;
}

}  // namespace webrtc
