/*
 * Copyright (c) 2020, 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.
 */

#ifndef AOM_AV1_ENCODER_MOTION_SEARCH_H_
#define AOM_AV1_ENCODER_MOTION_SEARCH_H_

#include "av1/encoder/encoder.h"

#ifdef __cplusplus
extern "C" {
#endif

#define NUM_JOINT_ME_REFINE_ITER 2
#define REDUCED_JOINT_ME_REFINE_ITER 1
// TODO(any): rename this struct to something else. There is already another
// struct called inter_modes_info, which makes this terribly confusing.
typedef struct {
  int drl_cost;
  int_mv full_search_mv;
  int full_mv_rate;
  int full_mv_bestsme;
  int skip;
} inter_mode_info;

struct HandleInterModeArgs;
void av1_single_motion_search(const AV1_COMP *const cpi, MACROBLOCK *x,
                              BLOCK_SIZE bsize, int ref_idx, int *rate_mv,
                              int search_range, inter_mode_info *mode_info,
                              int_mv *best_mv,
                              struct HandleInterModeArgs *const args);

int av1_joint_motion_search(const AV1_COMP *cpi, MACROBLOCK *x,
                            BLOCK_SIZE bsize, int_mv *cur_mv,
                            const uint8_t *mask, int mask_stride, int *rate_mv,
                            int allow_second_mv, int joint_me_num_refine_iter);

int av1_interinter_compound_motion_search(const AV1_COMP *const cpi,
                                          MACROBLOCK *x,
                                          const int_mv *const cur_mv,
                                          const BLOCK_SIZE bsize,
                                          const PREDICTION_MODE this_mode);

int av1_compound_single_motion_search_interinter(
    const AV1_COMP *cpi, MACROBLOCK *x, BLOCK_SIZE bsize, int_mv *cur_mv,
    const uint8_t *mask, int mask_stride, int *rate_mv, int ref_idx);

int av1_compound_single_motion_search(const AV1_COMP *cpi, MACROBLOCK *x,
                                      BLOCK_SIZE bsize, MV *this_mv,
                                      const uint8_t *second_pred,
                                      const uint8_t *mask, int mask_stride,
                                      int *rate_mv, int ref_idx);

// Performs a motion search in SIMPLE_TRANSLATION mode using reference frame
// ref and calculates the sse and var of the residue. Note that this sets the
// offset of mbmi, so we will need to reset it after calling this function.
int_mv av1_simple_motion_search_sse_var(struct AV1_COMP *cpi, MACROBLOCK *x,
                                        int mi_row, int mi_col,
                                        BLOCK_SIZE bsize, int ref,
                                        const FULLPEL_MV start_mv,
                                        int num_planes, int use_subpixel,
                                        unsigned int *sse, unsigned int *var);

static AOM_INLINE const search_site_config *av1_get_search_site_config(
    const AV1_COMP *cpi, MACROBLOCK *x, SEARCH_METHODS search_method) {
  const int ref_stride = x->e_mbd.plane[0].pre[0].stride;

  // AV1_COMP::mv_search_params.search_site_config is a compressor level cache
  // that's shared by multiple threads. In most cases where all frames have the
  // same resolution, the cache contains the search site config that we need.
  const MotionVectorSearchParams *mv_search_params = &cpi->mv_search_params;
  if (ref_stride == mv_search_params->search_site_cfg[SS_CFG_SRC]->stride) {
    return mv_search_params->search_site_cfg[SS_CFG_SRC];
  } else if (ref_stride ==
             mv_search_params->search_site_cfg[SS_CFG_LOOKAHEAD]->stride) {
    return mv_search_params->search_site_cfg[SS_CFG_LOOKAHEAD];
  }

  // If the cache does not contain the correct stride, then we will need to rely
  // on the thread level config MACROBLOCK::search_site_cfg_buf. If even the
  // thread level config doesn't match, then we need to update it.
  search_method = search_method_lookup[search_method];
  assert(search_method_lookup[search_method] == search_method &&
         "The search_method_lookup table should be idempotent.");
  if (ref_stride != x->search_site_cfg_buf[search_method].stride) {
    av1_refresh_search_site_config(x->search_site_cfg_buf, search_method,
                                   ref_stride);
  }

  return x->search_site_cfg_buf;
}

static AOM_INLINE SEARCH_METHODS
av1_get_faster_search_method(SEARCH_METHODS search_method) {
  // Note on search method's accuracy:
  //  1. NSTEP
  //  2. DIAMOND
  //  3. BIGDIA \approx SQUARE
  //  4. HEX.
  //  5. FAST_HEX \approx FAST_DIAMOND
  switch (search_method) {
    case NSTEP: return DIAMOND;
    case NSTEP_8PT: return DIAMOND;
    case DIAMOND: return BIGDIA;
    case CLAMPED_DIAMOND: return BIGDIA;
    case BIGDIA: return HEX;
    case SQUARE: return HEX;
    case HEX: return FAST_HEX;
    case FAST_HEX: return FAST_HEX;
    case FAST_DIAMOND: return VFAST_DIAMOND;
    case FAST_BIGDIA: return FAST_BIGDIA;
    case VFAST_DIAMOND: return VFAST_DIAMOND;
    default: assert(0 && "Invalid search method!"); return DIAMOND;
  }
}

static AOM_INLINE SEARCH_METHODS av1_get_default_mv_search_method(
    const MACROBLOCK *x, const MV_SPEED_FEATURES *mv_sf, BLOCK_SIZE bsize) {
  SEARCH_METHODS search_method = mv_sf->search_method;
  const int sf_blk_search_method = mv_sf->use_bsize_dependent_search_method;
  const int min_dim = AOMMIN(block_size_wide[bsize], block_size_high[bsize]);
  const int qband = x->qindex >> (QINDEX_BITS - 2);
  const bool use_faster_search_method =
      (sf_blk_search_method == 1 && min_dim >= 32) ||
      (sf_blk_search_method >= 2 && min_dim >= 16 &&
       x->content_state_sb.source_sad_nonrd <= kMedSad && qband < 3);

  if (use_faster_search_method) {
    search_method = av1_get_faster_search_method(search_method);
  }
  return search_method;
}

#ifdef __cplusplus
}  // extern "C"
#endif

#endif  // AOM_AV1_ENCODER_MOTION_SEARCH_H_
