/*
 * 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 "./aom_dsp_rtcd.h"
#include "./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 MV *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;
}
