/*
 *  Copyright (c) 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 "video/alignment_adjuster.h"

#include <algorithm>
#include <cstddef>
#include <cstdlib>
#include <limits>
#include <optional>

#include "absl/algorithm/container.h"
#include "api/video_codecs/video_encoder.h"
#include "rtc_base/logging.h"
#include "video/config/video_encoder_config.h"

namespace webrtc {
namespace {
// Round each scale factor to the closest rational in form alignment/i where i
// is a multiple of `requested_alignment`. Each resolution divisible by
// `alignment` will be divisible by `requested_alignment` after the scale factor
// is applied.
double RoundToMultiple(int alignment,
                       int requested_alignment,
                       VideoEncoderConfig* config,
                       bool update_config) {
  double diff = 0.0;
  for (auto& layer : config->simulcast_layers) {
    double min_dist = std::numeric_limits<double>::max();
    double new_scale = 1.0;
    for (int i = requested_alignment; i <= alignment;
         i += requested_alignment) {
      double dist = std::abs(layer.scale_resolution_down_by -
                             alignment / static_cast<double>(i));
      if (dist <= min_dist) {
        min_dist = dist;
        new_scale = alignment / static_cast<double>(i);
      }
    }
    diff += std::abs(layer.scale_resolution_down_by - new_scale);
    if (update_config) {
      RTC_LOG(LS_INFO) << "scale_resolution_down_by "
                       << layer.scale_resolution_down_by << " -> " << new_scale;
      layer.scale_resolution_down_by = new_scale;
    }
  }
  return diff;
}
}  // namespace

// Input: encoder_info.requested_resolution_alignment (K)
// Input: encoder_info.apply_alignment_to_all_simulcast_layers (B)
// Input: vector config->simulcast_layers.scale_resolution_down_by (S[i])
// Output:
// If B is false, returns K and does not adjust scaling factors.
// Otherwise, returns adjusted alignment (A), adjusted scaling factors (S'[i])
// are written in `config` such that:
//
// A / S'[i] are integers divisible by K
// sum abs(S'[i] - S[i]) -> min
// A integer <= 16
//
// Solution chooses closest S'[i] in a form A / j where j is a multiple of K.

int AlignmentAdjuster::GetAlignmentAndMaybeAdjustScaleFactors(
    const VideoEncoder::EncoderInfo& encoder_info,
    VideoEncoderConfig* config,
    std::optional<size_t> max_layers) {
  const int requested_alignment = encoder_info.requested_resolution_alignment;
  if (!encoder_info.apply_alignment_to_all_simulcast_layers) {
    return requested_alignment;
  }

  if (requested_alignment < 1 || config->number_of_streams <= 1 ||
      config->simulcast_layers.size() <= 1) {
    return requested_alignment;
  }

  // Update alignment to also apply to simulcast layers.
  const bool has_scale_resolution_down_by =
      absl::c_any_of(config->simulcast_layers, [](const VideoStream& layer) {
        return layer.scale_resolution_down_by >= 1.0;
      });

  if (!has_scale_resolution_down_by) {
    // Default resolution downscaling used (scale factors: 1, 2, 4, ...).
    size_t size = config->simulcast_layers.size();
    if (max_layers && *max_layers > 0 && *max_layers < size) {
      size = *max_layers;
    }
    return requested_alignment * (1 << (size - 1));
  }

  // Get alignment for downscaled layers.
  // Adjust `scale_resolution_down_by` to a common multiple to limit the
  // alignment value (to avoid largely cropped frames and possibly with an
  // aspect ratio far from the original).
  const int kMaxAlignment = 16;

  for (auto& layer : config->simulcast_layers) {
    layer.scale_resolution_down_by =
        std::max(layer.scale_resolution_down_by, 1.0);
    layer.scale_resolution_down_by =
        std::min(layer.scale_resolution_down_by, 10000.0);
  }

  // Decide on common multiple to use.
  double min_diff = std::numeric_limits<double>::max();
  int best_alignment = 1;
  for (int alignment = requested_alignment; alignment <= kMaxAlignment;
       ++alignment) {
    double diff = RoundToMultiple(alignment, requested_alignment, config,
                                  /*update_config=*/false);
    if (diff < min_diff) {
      min_diff = diff;
      best_alignment = alignment;
    }
  }
  RoundToMultiple(best_alignment, requested_alignment, config,
                  /*update_config=*/true);

  return std::max(best_alignment, requested_alignment);
}
}  // namespace webrtc
