/*
 *  Copyright 2021 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 "modules/video_coding/utility/bandwidth_quality_scaler.h"

#include <algorithm>
#include <memory>
#include <utility>
#include <vector>

#include "api/video/video_adaptation_reason.h"
#include "api/video_codecs/video_encoder.h"
#include "rtc_base/checks.h"
#include "rtc_base/experiments/bandwidth_quality_scaler_settings.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/exp_filter.h"
#include "rtc_base/task_queue.h"
#include "rtc_base/task_utils/to_queued_task.h"
#include "rtc_base/time_utils.h"
#include "rtc_base/weak_ptr.h"

namespace webrtc {

namespace {

constexpr int kDefaultMaxWindowSizeMs = 5000;
constexpr float kHigherMaxBitrateTolerationFactor = 0.95;
constexpr float kLowerMinBitrateTolerationFactor = 0.8;
constexpr int kDefaultBitrateStateUpdateIntervalSeconds = 5;
}  // namespace

BandwidthQualityScaler::BandwidthQualityScaler(
    BandwidthQualityScalerUsageHandlerInterface* handler)
    : kBitrateStateUpdateInterval(TimeDelta::Seconds(
          BandwidthQualityScalerSettings::ParseFromFieldTrials()
              .BitrateStateUpdateInterval()
              .value_or(kDefaultBitrateStateUpdateIntervalSeconds))),
      handler_(handler),
      encoded_bitrate_(kDefaultMaxWindowSizeMs, RateStatistics::kBpsScale),
      weak_ptr_factory_(this) {
  RTC_DCHECK_RUN_ON(&task_checker_);
  RTC_DCHECK(handler_ != nullptr);

  StartCheckForBitrate();
}

BandwidthQualityScaler::~BandwidthQualityScaler() {
  RTC_DCHECK_RUN_ON(&task_checker_);
}

void BandwidthQualityScaler::StartCheckForBitrate() {
  RTC_DCHECK_RUN_ON(&task_checker_);
  TaskQueueBase::Current()->PostDelayedTask(
      ToQueuedTask([this_weak_ptr = weak_ptr_factory_.GetWeakPtr(), this] {
        if (!this_weak_ptr) {
          // The caller BandwidthQualityScaler has been deleted.
          return;
        }
        RTC_DCHECK_RUN_ON(&task_checker_);
        switch (CheckBitrate()) {
          case BandwidthQualityScaler::CheckBitrateResult::kHighBitRate: {
            handler_->OnReportUsageBandwidthHigh();
            last_frame_size_pixels_.reset();
            break;
          }
          case BandwidthQualityScaler::CheckBitrateResult::kLowBitRate: {
            handler_->OnReportUsageBandwidthLow();
            last_frame_size_pixels_.reset();
            break;
          }
          case BandwidthQualityScaler::CheckBitrateResult::kNormalBitrate: {
            break;
          }
          case BandwidthQualityScaler::CheckBitrateResult::
              kInsufficientSamples: {
            break;
          }
        }
        StartCheckForBitrate();
      }),
      kBitrateStateUpdateInterval.ms());
}

void BandwidthQualityScaler::ReportEncodeInfo(int frame_size_bytes,
                                              int64_t time_sent_in_ms,
                                              uint32_t encoded_width,
                                              uint32_t encoded_height) {
  RTC_DCHECK_RUN_ON(&task_checker_);
  last_time_sent_in_ms_ = time_sent_in_ms;
  last_frame_size_pixels_ = encoded_width * encoded_height;
  encoded_bitrate_.Update(frame_size_bytes, time_sent_in_ms);
}

void BandwidthQualityScaler::SetResolutionBitrateLimits(
    const std::vector<VideoEncoder::ResolutionBitrateLimits>&
        resolution_bitrate_limits) {
  if (resolution_bitrate_limits.empty()) {
    resolution_bitrate_limits_ = EncoderInfoSettings::
        GetDefaultSinglecastBitrateLimitsWhenQpIsUntrusted();
  } else {
    resolution_bitrate_limits_ = resolution_bitrate_limits;
  }
}

BandwidthQualityScaler::CheckBitrateResult
BandwidthQualityScaler::CheckBitrate() {
  RTC_DCHECK_RUN_ON(&task_checker_);
  if (!last_frame_size_pixels_.has_value() ||
      !last_time_sent_in_ms_.has_value()) {
    return BandwidthQualityScaler::CheckBitrateResult::kInsufficientSamples;
  }

  absl::optional<int64_t> current_bitrate_bps =
      encoded_bitrate_.Rate(last_time_sent_in_ms_.value());
  if (!current_bitrate_bps.has_value()) {
    // We can't get a valid bitrate due to not enough data points.
    return BandwidthQualityScaler::CheckBitrateResult::kInsufficientSamples;
  }
  absl::optional<VideoEncoder::ResolutionBitrateLimits> suitable_bitrate_limit =
      EncoderInfoSettings::
          GetSinglecastBitrateLimitForResolutionWhenQpIsUntrusted(
              last_frame_size_pixels_, resolution_bitrate_limits_);

  if (!suitable_bitrate_limit.has_value()) {
    return BandwidthQualityScaler::CheckBitrateResult::kInsufficientSamples;
  }

  // Multiply by toleration factor to solve the frequent adaptation due to
  // critical value.
  if (current_bitrate_bps > suitable_bitrate_limit->max_bitrate_bps *
                                kHigherMaxBitrateTolerationFactor) {
    return BandwidthQualityScaler::CheckBitrateResult::kLowBitRate;
  } else if (current_bitrate_bps <
             suitable_bitrate_limit->min_start_bitrate_bps *
                 kLowerMinBitrateTolerationFactor) {
    return BandwidthQualityScaler::CheckBitrateResult::kHighBitRate;
  }
  return BandwidthQualityScaler::CheckBitrateResult::kNormalBitrate;
}

BandwidthQualityScalerUsageHandlerInterface::
    ~BandwidthQualityScalerUsageHandlerInterface() {}
}  // namespace webrtc
