/*
 *  Copyright (c) 2016 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/audio_coding/audio_network_adaptor/frame_length_controller.h"

#include <algorithm>
#include <utility>

#include "rtc_base/checks.h"
#include "rtc_base/logging.h"

namespace webrtc {

namespace {
constexpr int kPreventOveruseMarginBps = 5000;

int OverheadRateBps(size_t overhead_bytes_per_packet, int frame_length_ms) {
  return static_cast<int>(overhead_bytes_per_packet * 8 * 1000 /
                          frame_length_ms);
}
}

FrameLengthController::Config::Config(
    const std::vector<int>& encoder_frame_lengths_ms,
    int initial_frame_length_ms,
    int min_encoder_bitrate_bps,
    float fl_increasing_packet_loss_fraction,
    float fl_decreasing_packet_loss_fraction,
    int fl_increase_overhead_offset,
    int fl_decrease_overhead_offset,
    std::map<FrameLengthChange, int> fl_changing_bandwidths_bps)
    : encoder_frame_lengths_ms(encoder_frame_lengths_ms),
      initial_frame_length_ms(initial_frame_length_ms),
      min_encoder_bitrate_bps(min_encoder_bitrate_bps),
      fl_increasing_packet_loss_fraction(fl_increasing_packet_loss_fraction),
      fl_decreasing_packet_loss_fraction(fl_decreasing_packet_loss_fraction),
      fl_increase_overhead_offset(fl_increase_overhead_offset),
      fl_decrease_overhead_offset(fl_decrease_overhead_offset),
      fl_changing_bandwidths_bps(std::move(fl_changing_bandwidths_bps)) {}

FrameLengthController::Config::Config(const Config& other) = default;

FrameLengthController::Config::~Config() = default;

FrameLengthController::FrameLengthController(const Config& config)
    : config_(config) {
  frame_length_ms_ = std::find(config_.encoder_frame_lengths_ms.begin(),
                               config_.encoder_frame_lengths_ms.end(),
                               config_.initial_frame_length_ms);
  // |encoder_frame_lengths_ms| must contain |initial_frame_length_ms|.
  RTC_DCHECK(frame_length_ms_ != config_.encoder_frame_lengths_ms.end());
}

FrameLengthController::~FrameLengthController() = default;

void FrameLengthController::UpdateNetworkMetrics(
    const NetworkMetrics& network_metrics) {
  if (network_metrics.uplink_bandwidth_bps)
    uplink_bandwidth_bps_ = network_metrics.uplink_bandwidth_bps;
  if (network_metrics.uplink_packet_loss_fraction)
    uplink_packet_loss_fraction_ = network_metrics.uplink_packet_loss_fraction;
  if (network_metrics.overhead_bytes_per_packet)
    overhead_bytes_per_packet_ = network_metrics.overhead_bytes_per_packet;
}

void FrameLengthController::MakeDecision(AudioEncoderRuntimeConfig* config) {
  // Decision on |frame_length_ms| should not have been made.
  RTC_DCHECK(!config->frame_length_ms);

  if (FrameLengthIncreasingDecision(*config)) {
    ++frame_length_ms_;
    prev_decision_increase_ = true;
  } else if (FrameLengthDecreasingDecision(*config)) {
    --frame_length_ms_;
    prev_decision_increase_ = false;
  }
  config->last_fl_change_increase = prev_decision_increase_;
  config->frame_length_ms = *frame_length_ms_;
}

FrameLengthController::Config::FrameLengthChange::FrameLengthChange(
    int from_frame_length_ms,
    int to_frame_length_ms)
    : from_frame_length_ms(from_frame_length_ms),
      to_frame_length_ms(to_frame_length_ms) {}

bool FrameLengthController::Config::FrameLengthChange::operator<(
    const FrameLengthChange& rhs) const {
  return from_frame_length_ms < rhs.from_frame_length_ms ||
         (from_frame_length_ms == rhs.from_frame_length_ms &&
          to_frame_length_ms < rhs.to_frame_length_ms);
}

bool FrameLengthController::FrameLengthIncreasingDecision(
    const AudioEncoderRuntimeConfig& config) const {
  // Increase frame length if
  // 1. |uplink_bandwidth_bps| is known to be smaller or equal than
  //    |min_encoder_bitrate_bps| plus |prevent_overuse_margin_bps| plus the
  //    current overhead rate OR all the following:
  // 2. longer frame length is available AND
  // 3. |uplink_bandwidth_bps| is known to be smaller than a threshold AND
  // 4. |uplink_packet_loss_fraction| is known to be smaller than a threshold.

  auto longer_frame_length_ms = std::next(frame_length_ms_);
  if (longer_frame_length_ms == config_.encoder_frame_lengths_ms.end())
    return false;

  auto increase_threshold = config_.fl_changing_bandwidths_bps.find(
      Config::FrameLengthChange(*frame_length_ms_, *longer_frame_length_ms));

  if (increase_threshold == config_.fl_changing_bandwidths_bps.end())
    return false;

  // Check that
  // -(*overhead_bytes_per_packet_) <= offset <= (*overhead_bytes_per_packet_)
  RTC_DCHECK(
      !overhead_bytes_per_packet_ ||
      (overhead_bytes_per_packet_ &&
       static_cast<size_t>(std::max(0, -config_.fl_increase_overhead_offset)) <=
           *overhead_bytes_per_packet_ &&
       static_cast<size_t>(std::max(0, config_.fl_increase_overhead_offset)) <=
           *overhead_bytes_per_packet_));

  if (uplink_bandwidth_bps_ && overhead_bytes_per_packet_ &&
      *uplink_bandwidth_bps_ <=
          config_.min_encoder_bitrate_bps + kPreventOveruseMarginBps +
              OverheadRateBps(*overhead_bytes_per_packet_ +
                                  config_.fl_increase_overhead_offset,
                              *frame_length_ms_)) {
    return true;
  }

  return (uplink_bandwidth_bps_ &&
          *uplink_bandwidth_bps_ <= increase_threshold->second) &&
         (uplink_packet_loss_fraction_ &&
          *uplink_packet_loss_fraction_ <=
              config_.fl_increasing_packet_loss_fraction);
}

bool FrameLengthController::FrameLengthDecreasingDecision(
    const AudioEncoderRuntimeConfig& config) const {
  // Decrease frame length if
  // 1. shorter frame length is available AND
  // 2. |uplink_bandwidth_bps| is known to be bigger than
  // |min_encoder_bitrate_bps| plus |prevent_overuse_margin_bps| plus the
  // overhead which would be produced with the shorter frame length AND
  // one or more of the followings:
  // 3. |uplink_bandwidth_bps| is known to be larger than a threshold,
  // 4. |uplink_packet_loss_fraction| is known to be larger than a threshold,
  if (frame_length_ms_ == config_.encoder_frame_lengths_ms.begin())
    return false;

  auto shorter_frame_length_ms = std::prev(frame_length_ms_);
  auto decrease_threshold = config_.fl_changing_bandwidths_bps.find(
      Config::FrameLengthChange(*frame_length_ms_, *shorter_frame_length_ms));

  if (decrease_threshold == config_.fl_changing_bandwidths_bps.end())
    return false;

  if (uplink_bandwidth_bps_ && overhead_bytes_per_packet_ &&
      *uplink_bandwidth_bps_ <=
          config_.min_encoder_bitrate_bps + kPreventOveruseMarginBps +
              OverheadRateBps(*overhead_bytes_per_packet_ +
                                  config_.fl_decrease_overhead_offset,
                              *shorter_frame_length_ms)) {
    return false;
  }

  return (uplink_bandwidth_bps_ &&
          *uplink_bandwidth_bps_ >= decrease_threshold->second) ||
         (uplink_packet_loss_fraction_ &&
          *uplink_packet_loss_fraction_ >=
              config_.fl_decreasing_packet_loss_fraction);
}

}  // namespace webrtc
