/*
 *  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 "webrtc/modules/audio_coding/audio_network_adaptor/frame_length_controller.h"

#include <utility>

#include "webrtc/rtc_base/checks.h"
#include "webrtc/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,
    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_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_;
  } else if (FrameLengthDecreasingDecision(*config)) {
    --frame_length_ms_;
  }
  config->frame_length_ms = rtc::Optional<int>(*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;

  if (uplink_bandwidth_bps_ && overhead_bytes_per_packet_ &&
      *uplink_bandwidth_bps_ <=
          config_.min_encoder_bitrate_bps + kPreventOveruseMarginBps +
              OverheadRateBps(*overhead_bytes_per_packet_, *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_,
                                                    *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
