/*
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. 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 www.aomedia.org/license/patent.
 */

#include "config/aom_dsp_rtcd.h"
#include "config/av1_rtcd.h"

#include "av1/common/filter.h"
#include "av1/common/scale.h"
#include "aom_dsp/aom_filter.h"

// Note: Expect val to be in q4 precision
static INLINE int scaled_x(int val, const struct scale_factors *sf) {
  const int off =
      (sf->x_scale_fp - (1 << REF_SCALE_SHIFT)) * (1 << (SUBPEL_BITS - 1));
  const int64_t tval = (int64_t)val * sf->x_scale_fp + off;
  return (int)ROUND_POWER_OF_TWO_SIGNED_64(tval,
                                           REF_SCALE_SHIFT - SCALE_EXTRA_BITS);
}

// Note: Expect val to be in q4 precision
static INLINE int scaled_y(int val, const struct scale_factors *sf) {
  const int off =
      (sf->y_scale_fp - (1 << REF_SCALE_SHIFT)) * (1 << (SUBPEL_BITS - 1));
  const int64_t tval = (int64_t)val * sf->y_scale_fp + off;
  return (int)ROUND_POWER_OF_TWO_SIGNED_64(tval,
                                           REF_SCALE_SHIFT - SCALE_EXTRA_BITS);
}

// Note: Expect val to be in q4 precision
static int unscaled_value(int val, const struct scale_factors *sf) {
  (void)sf;
  return val << SCALE_EXTRA_BITS;
}

static int get_fixed_point_scale_factor(int other_size, int this_size) {
  // Calculate scaling factor once for each reference frame
  // and use fixed point scaling factors in decoding and encoding routines.
  // Hardware implementations can calculate scale factor in device driver
  // and use multiplication and shifting on hardware instead of division.
  return ((other_size << REF_SCALE_SHIFT) + this_size / 2) / this_size;
}

// Given the fixed point scale, calculate coarse point scale.
static int fixed_point_scale_to_coarse_point_scale(int scale_fp) {
  return ROUND_POWER_OF_TWO(scale_fp, REF_SCALE_SHIFT - SCALE_SUBPEL_BITS);
}

// Note: x and y are integer precision, mvq4 is q4 precision.
MV32 av1_scale_mv(const MV32 *mvq4, int x, int y,
                  const struct scale_factors *sf) {
  const int x_off_q4 = scaled_x(x << SUBPEL_BITS, sf);
  const int y_off_q4 = scaled_y(y << SUBPEL_BITS, sf);
  const MV32 res = { scaled_y((y << SUBPEL_BITS) + mvq4->row, sf) - y_off_q4,
                     scaled_x((x << SUBPEL_BITS) + mvq4->col, sf) - x_off_q4 };
  return res;
}

void av1_setup_scale_factors_for_frame(struct scale_factors *sf, int other_w,
                                       int other_h, int this_w, int this_h) {
  if (!valid_ref_frame_size(other_w, other_h, this_w, this_h)) {
    sf->x_scale_fp = REF_INVALID_SCALE;
    sf->y_scale_fp = REF_INVALID_SCALE;
    return;
  }

  sf->x_scale_fp = get_fixed_point_scale_factor(other_w, this_w);
  sf->y_scale_fp = get_fixed_point_scale_factor(other_h, this_h);

  sf->x_step_q4 = fixed_point_scale_to_coarse_point_scale(sf->x_scale_fp);
  sf->y_step_q4 = fixed_point_scale_to_coarse_point_scale(sf->y_scale_fp);

  if (av1_is_scaled(sf)) {
    sf->scale_value_x = scaled_x;
    sf->scale_value_y = scaled_y;
  } else {
    sf->scale_value_x = unscaled_value;
    sf->scale_value_y = unscaled_value;
  }

  // AV1 convolve functions
  // Special case convolve functions should produce the same result as
  // av1_convolve_2d.
  // subpel_x_q4 == 0 && subpel_y_q4 == 0
  sf->convolve[0][0][0] = av1_convolve_2d_copy_sr;
  // subpel_x_q4 == 0
  sf->convolve[0][1][0] = av1_convolve_y_sr;
  // subpel_y_q4 == 0
  sf->convolve[1][0][0] = av1_convolve_x_sr;
  // subpel_x_q4 != 0 && subpel_y_q4 != 0
  sf->convolve[1][1][0] = av1_convolve_2d_sr;
  // subpel_x_q4 == 0 && subpel_y_q4 == 0
  sf->convolve[0][0][1] = av1_jnt_convolve_2d_copy;
  // subpel_x_q4 == 0
  sf->convolve[0][1][1] = av1_jnt_convolve_y;
  // subpel_y_q4 == 0
  sf->convolve[1][0][1] = av1_jnt_convolve_x;
  // subpel_x_q4 != 0 && subpel_y_q4 != 0
  sf->convolve[1][1][1] = av1_jnt_convolve_2d;
  // AV1 High BD convolve functions
  // Special case convolve functions should produce the same result as
  // av1_highbd_convolve_2d.
  // subpel_x_q4 == 0 && subpel_y_q4 == 0
  sf->highbd_convolve[0][0][0] = av1_highbd_convolve_2d_copy_sr;
  // subpel_x_q4 == 0
  sf->highbd_convolve[0][1][0] = av1_highbd_convolve_y_sr;
  // subpel_y_q4 == 0
  sf->highbd_convolve[1][0][0] = av1_highbd_convolve_x_sr;
  // subpel_x_q4 != 0 && subpel_y_q4 != 0
  sf->highbd_convolve[1][1][0] = av1_highbd_convolve_2d_sr;
  // subpel_x_q4 == 0 && subpel_y_q4 == 0
  sf->highbd_convolve[0][0][1] = av1_highbd_jnt_convolve_2d_copy;
  // subpel_x_q4 == 0
  sf->highbd_convolve[0][1][1] = av1_highbd_jnt_convolve_y;
  // subpel_y_q4 == 0
  sf->highbd_convolve[1][0][1] = av1_highbd_jnt_convolve_x;
  // subpel_x_q4 != 0 && subpel_y_q4 != 0
  sf->highbd_convolve[1][1][1] = av1_highbd_jnt_convolve_2d;
}
