/*
 * Copyright (c) 2021, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 3-Clause Clear License
 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
 * License was not distributed with this source code in the LICENSE file, you
 * can obtain it at aomedia.org/license/software-license/bsd-3-c-c/.  If the
 * Alliance for Open Media Patent License 1.0 was not distributed with this
 * source code in the PATENTS file, you can obtain it at
 * aomedia.org/license/patent-license/.
 */

#include "av1/encoder/encoder_alloc.h"
#include "av1/encoder/superres_scale.h"
#include "av1/encoder/random.h"

// This function is used to compute the resolution for low delay mode
static uint8_t get_resolution_ratio_pattern1(const int display_order_hint) {
  uint8_t new_denom = 8;
  const uint8_t denom_indices8[8] = { 8, 10, 12, 14, 16, 15, 13, 9 };
  const uint8_t denom_indices16[16] = { 8,  9,  10, 11, 12, 13, 14, 15,
                                        16, 15, 14, 13, 12, 11, 10, 9 };
  int chunk_size = display_order_hint % 48;
  if (chunk_size < 8) {
    new_denom = denom_indices8[chunk_size];
  } else if (chunk_size < 16) {
    new_denom = 8;
  } else if (chunk_size < 32) {
    new_denom = denom_indices16[chunk_size - 16];
  } else {
    new_denom = 8;
  }
  return new_denom;
}

// This function is used to compute the resolution for RA mode
static uint8_t get_resolution_ratio_pattern2(const int display_order_hint) {
  uint8_t new_denom = 8;
  int chunk_size = display_order_hint % 65;
  if (chunk_size < 17) {
    new_denom = 8;
  } else if (chunk_size < 33) {
    new_denom = 16;
  } else if (chunk_size < 49) {
    new_denom = 8;
  } else {
    new_denom = 12;
  }
  return new_denom;
}

static uint8_t calculate_next_resize_scale(const AV1_COMP *cpi) {
  // Choose an arbitrary random number
  static unsigned int seed = 56789;
  const ResizeCfg *resize_cfg = &cpi->oxcf.resize_cfg;
  if (is_stat_generation_stage(cpi)) return SCALE_NUMERATOR;
  uint8_t new_denom = SCALE_NUMERATOR;
  const int display_order_hint = cpi->common.current_frame.display_order_hint;
  const uint8_t is_low_delay_enc = (cpi->oxcf.gf_cfg.lag_in_frames == 0);

  if (cpi->common.seq_params.reduced_still_picture_hdr) return SCALE_NUMERATOR;
  switch (resize_cfg->resize_mode) {
    case RESIZE_NONE: new_denom = SCALE_NUMERATOR; break;
    case RESIZE_FIXED:
      if (cpi->common.current_frame.frame_type == KEY_FRAME)
        new_denom = resize_cfg->resize_kf_scale_denominator;
      else
        new_denom = resize_cfg->resize_scale_denominator;
      break;
    case RESIZE_RANDOM: new_denom = lcg_rand16(&seed) % 9 + 8; break;
    case RESIZE_PATTERN:
      new_denom = is_low_delay_enc
                      ? get_resolution_ratio_pattern1(display_order_hint)
                      : get_resolution_ratio_pattern2(display_order_hint);
      break;
    default: assert(0);
  }
  return new_denom;
}

static int dimension_is_ok(int orig_dim, int resized_dim, int denom) {
  return (resized_dim * SCALE_NUMERATOR >= orig_dim * denom / 2);
}

static int dimensions_are_ok(int owidth, int oheight, size_params_type *rsz) {
  // Only need to check the width, as scaling is horizontal only.
  (void)oheight;
  return dimension_is_ok(owidth, rsz->resize_width, rsz->superres_denom);
}

static int validate_size_scales(RESIZE_MODE resize_mode, int owidth,
                                int oheight, size_params_type *rsz) {
  if (dimensions_are_ok(owidth, oheight, rsz)) {  // Nothing to do.
    return 1;
  }
  if ((resize_mode == RESIZE_RANDOM || resize_mode == RESIZE_PATTERN)) {
    // Alter resize scale as needed to enforce conformity.
    int resize_denom =
        (2 * SCALE_NUMERATOR * SCALE_NUMERATOR) / rsz->superres_denom;
    rsz->resize_width = owidth;
    rsz->resize_height = oheight;
    av1_calculate_scaled_size(&rsz->resize_width, &rsz->resize_height,
                              resize_denom);
    if (!dimensions_are_ok(owidth, oheight, rsz)) {
      if (resize_denom > SCALE_NUMERATOR) {
        --resize_denom;
        rsz->resize_width = owidth;
        rsz->resize_height = oheight;
        av1_calculate_scaled_size(&rsz->resize_width, &rsz->resize_height,
                                  resize_denom);
      }
    }
  } else {  // We are allowed to alter neither resize scale nor superres
            // scale.
    return 0;
  }
  return dimensions_are_ok(owidth, oheight, rsz);
}

// Calculates resize and superres params for next frame
static size_params_type calculate_next_size_params(AV1_COMP *cpi) {
  const AV1EncoderConfig *oxcf = &cpi->oxcf;
  ResizePendingParams *resize_pending_params = &cpi->resize_pending_params;
  const FrameDimensionCfg *const frm_dim_cfg = &oxcf->frm_dim_cfg;
  size_params_type rsz = { frm_dim_cfg->width, frm_dim_cfg->height,
                           SCALE_NUMERATOR };
  int resize_denom = SCALE_NUMERATOR;
  if (is_stat_generation_stage(cpi)) return rsz;
  if (resize_pending_params->width && resize_pending_params->height) {
    rsz.resize_width = resize_pending_params->width;
    rsz.resize_height = resize_pending_params->height;
    resize_pending_params->width = resize_pending_params->height = 0;
    return rsz;
  } else {
    resize_denom = calculate_next_resize_scale(cpi);
    rsz.resize_width = frm_dim_cfg->width;
    rsz.resize_height = frm_dim_cfg->height;
    av1_calculate_scaled_size(&rsz.resize_width, &rsz.resize_height,
                              resize_denom);
  }
  if (!validate_size_scales(oxcf->resize_cfg.resize_mode, frm_dim_cfg->width,
                            frm_dim_cfg->height, &rsz))
    assert(0 && "Invalid scale parameters");
  return rsz;
}

static void setup_frame_size_from_params(AV1_COMP *cpi,
                                         const size_params_type *rsz) {
  int encode_width = rsz->resize_width;
  int encode_height = rsz->resize_height;
  av1_set_frame_size(cpi, encode_width, encode_height);
}

void av1_setup_frame_size(AV1_COMP *cpi) {
  const size_params_type rsz = calculate_next_size_params(cpi);
  setup_frame_size_from_params(cpi, &rsz);
}
