/*
 *  Copyright (c) 2010 The WebM 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 <limits.h>
#include "vpx_config.h"
#include "onyx_int.h"
#include "mr_dissim.h"
#include "vpx_dsp/vpx_dsp_common.h"
#include "vpx_mem/vpx_mem.h"
#include "rdopt.h"
#include "vp8/common/common.h"

void vp8_cal_low_res_mb_cols(VP8_COMP *cpi) {
  int low_res_w;

  /* Support arbitrary down-sampling factor */
  unsigned int iw = cpi->oxcf.Width * cpi->oxcf.mr_down_sampling_factor.den +
                    cpi->oxcf.mr_down_sampling_factor.num - 1;

  low_res_w = iw / cpi->oxcf.mr_down_sampling_factor.num;
  cpi->mr_low_res_mb_cols = ((low_res_w + 15) >> 4);
}

#define GET_MV(x)                         \
  if (x->mbmi.ref_frame != INTRA_FRAME) { \
    mvx[cnt] = x->mbmi.mv.as_mv.row;      \
    mvy[cnt] = x->mbmi.mv.as_mv.col;      \
    cnt++;                                \
  }

#define GET_MV_SIGN(x)                                  \
  if (x->mbmi.ref_frame != INTRA_FRAME) {               \
    mvx[cnt] = x->mbmi.mv.as_mv.row;                    \
    mvy[cnt] = x->mbmi.mv.as_mv.col;                    \
    if (cm->ref_frame_sign_bias[x->mbmi.ref_frame] !=   \
        cm->ref_frame_sign_bias[tmp->mbmi.ref_frame]) { \
      mvx[cnt] *= -1;                                   \
      mvy[cnt] *= -1;                                   \
    }                                                   \
    cnt++;                                              \
  }

void vp8_cal_dissimilarity(VP8_COMP *cpi) {
  VP8_COMMON *cm = &cpi->common;
  int i;

  /* Note: The first row & first column in mip are outside the frame, which
   * were initialized to all 0.(ref_frame, mode, mv...)
   * Their ref_frame = 0 means they won't be counted in the following
   * calculation.
   */
  if (cpi->oxcf.mr_total_resolutions > 1 &&
      cpi->oxcf.mr_encoder_id < (cpi->oxcf.mr_total_resolutions - 1)) {
    /* Store info for show/no-show frames for supporting alt_ref.
     * If parent frame is alt_ref, child has one too.
     */
    LOWER_RES_FRAME_INFO *store_info =
        (LOWER_RES_FRAME_INFO *)cpi->oxcf.mr_low_res_mode_info;

    store_info->frame_type = cm->frame_type;

    if (cm->frame_type != KEY_FRAME) {
      store_info->is_frame_dropped = 0;
      for (i = 1; i < MAX_REF_FRAMES; ++i)
        store_info->low_res_ref_frames[i] = cpi->current_ref_frames[i];
    }

    if (cm->frame_type != KEY_FRAME) {
      int mb_row;
      int mb_col;
      /* Point to beginning of allocated MODE_INFO arrays. */
      MODE_INFO *tmp = cm->mip + cm->mode_info_stride;
      LOWER_RES_MB_INFO *store_mode_info = store_info->mb_info;

      for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {
        tmp++;
        for (mb_col = 0; mb_col < cm->mb_cols; ++mb_col) {
          int dissim = INT_MAX;

          if (tmp->mbmi.ref_frame != INTRA_FRAME) {
            int mvx[8];
            int mvy[8];
            int mmvx;
            int mmvy;
            int cnt = 0;
            const MODE_INFO *here = tmp;
            const MODE_INFO *above = here - cm->mode_info_stride;
            const MODE_INFO *left = here - 1;
            const MODE_INFO *aboveleft = above - 1;
            const MODE_INFO *aboveright = NULL;
            const MODE_INFO *right = NULL;
            const MODE_INFO *belowleft = NULL;
            const MODE_INFO *below = NULL;
            const MODE_INFO *belowright = NULL;

            /* If alternate reference frame is used, we have to
             * check sign of MV. */
            if (cpi->oxcf.play_alternate) {
              /* Gather mv of neighboring MBs */
              GET_MV_SIGN(above)
              GET_MV_SIGN(left)
              GET_MV_SIGN(aboveleft)

              if (mb_col < (cm->mb_cols - 1)) {
                right = here + 1;
                aboveright = above + 1;
                GET_MV_SIGN(right)
                GET_MV_SIGN(aboveright)
              }

              if (mb_row < (cm->mb_rows - 1)) {
                below = here + cm->mode_info_stride;
                belowleft = below - 1;
                GET_MV_SIGN(below)
                GET_MV_SIGN(belowleft)
              }

              if (mb_col < (cm->mb_cols - 1) && mb_row < (cm->mb_rows - 1)) {
                belowright = below + 1;
                GET_MV_SIGN(belowright)
              }
            } else {
              /* No alt_ref and gather mv of neighboring MBs */
              GET_MV(above)
              GET_MV(left)
              GET_MV(aboveleft)

              if (mb_col < (cm->mb_cols - 1)) {
                right = here + 1;
                aboveright = above + 1;
                GET_MV(right)
                GET_MV(aboveright)
              }

              if (mb_row < (cm->mb_rows - 1)) {
                below = here + cm->mode_info_stride;
                belowleft = below - 1;
                GET_MV(below)
                GET_MV(belowleft)
              }

              if (mb_col < (cm->mb_cols - 1) && mb_row < (cm->mb_rows - 1)) {
                belowright = below + 1;
                GET_MV(belowright)
              }
            }

            if (cnt > 0) {
              int max_mvx = mvx[0];
              int min_mvx = mvx[0];
              int max_mvy = mvy[0];
              int min_mvy = mvy[0];
              int i;

              if (cnt > 1) {
                for (i = 1; i < cnt; ++i) {
                  if (mvx[i] > max_mvx)
                    max_mvx = mvx[i];
                  else if (mvx[i] < min_mvx)
                    min_mvx = mvx[i];
                  if (mvy[i] > max_mvy)
                    max_mvy = mvy[i];
                  else if (mvy[i] < min_mvy)
                    min_mvy = mvy[i];
                }
              }

              mmvx = VPXMAX(abs(min_mvx - here->mbmi.mv.as_mv.row),
                            abs(max_mvx - here->mbmi.mv.as_mv.row));
              mmvy = VPXMAX(abs(min_mvy - here->mbmi.mv.as_mv.col),
                            abs(max_mvy - here->mbmi.mv.as_mv.col));
              dissim = VPXMAX(mmvx, mmvy);
            }
          }

          /* Store mode info for next resolution encoding */
          store_mode_info->mode = tmp->mbmi.mode;
          store_mode_info->ref_frame = tmp->mbmi.ref_frame;
          store_mode_info->mv.as_int = tmp->mbmi.mv.as_int;
          store_mode_info->dissim = dissim;
          tmp++;
          store_mode_info++;
        }
      }
    }
  }
}

/* This function is called only when this frame is dropped at current
   resolution level. */
void vp8_store_drop_frame_info(VP8_COMP *cpi) {
  /* If the frame is dropped in lower-resolution encoding, this information
     is passed to higher resolution level so that the encoder knows there
     is no mode & motion info available.
   */
  if (cpi->oxcf.mr_total_resolutions > 1 &&
      cpi->oxcf.mr_encoder_id < (cpi->oxcf.mr_total_resolutions - 1)) {
    /* Store info for show/no-show frames for supporting alt_ref.
     * If parent frame is alt_ref, child has one too.
     */
    LOWER_RES_FRAME_INFO *store_info =
        (LOWER_RES_FRAME_INFO *)cpi->oxcf.mr_low_res_mode_info;

    /* Set frame_type to be INTER_FRAME since we won't drop key frame. */
    store_info->frame_type = INTER_FRAME;
    store_info->is_frame_dropped = 1;
  }
}
