1ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang/*
2ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *
4ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  Use of this source code is governed by a BSD-style license
5ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  that can be found in the LICENSE file in the root of the source
6ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  tree. An additional intellectual property rights grant can be found
7ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  in the file PATENTS.  All contributing project authors may
8ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang *  be found in the AUTHORS file in the root of the source tree.
9ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang */
10ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
11ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include <assert.h>
12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
131184aebb761cbeac9124c37189a80a1a58f04b6bhkuang#include "./vpx_scale_rtcd.h"
14ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "./vpx_config.h"
151184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
16ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vpx/vpx_integer.h"
171184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
18ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vp9/common/vp9_blockd.h"
19ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vp9/common/vp9_reconinter.h"
20ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "vp9/common/vp9_reconintra.h"
21ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
22da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if CONFIG_VP9_HIGHBITDEPTH
23da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianvoid high_inter_predictor(const uint8_t *src, int src_stride,
24da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                 uint8_t *dst, int dst_stride,
25da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                 const int subpel_x,
26da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                 const int subpel_y,
27da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                 const struct scale_factors *sf,
28da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                 int w, int h, int ref,
29da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                 const InterpKernel *kernel,
30da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                 int xs, int ys, int bd) {
31da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  sf->highbd_predict[subpel_x != 0][subpel_y != 0][ref](
32da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      src, src_stride, dst, dst_stride,
33da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      kernel[subpel_x], xs, kernel[subpel_y], ys, w, h, bd);
34da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian}
355ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
36da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianvoid vp9_highbd_build_inter_predictor(const uint8_t *src, int src_stride,
37da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                      uint8_t *dst, int dst_stride,
38da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                      const MV *src_mv,
39da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                      const struct scale_factors *sf,
40da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                      int w, int h, int ref,
41da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                      const InterpKernel *kernel,
42da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                      enum mv_precision precision,
43da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                      int x, int y, int bd) {
44da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  const int is_q4 = precision == MV_PRECISION_Q4;
45da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2,
46da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                     is_q4 ? src_mv->col : src_mv->col * 2 };
47da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  MV32 mv = vp9_scale_mv(&mv_q4, x, y, sf);
48da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  const int subpel_x = mv.col & SUBPEL_MASK;
49da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  const int subpel_y = mv.row & SUBPEL_MASK;
502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
51da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  src += (mv.row >> SUBPEL_BITS) * src_stride + (mv.col >> SUBPEL_BITS);
52ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
53da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  high_inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y,
54da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                       sf, w, h, ref, kernel, sf->x_step_q4, sf->y_step_q4, bd);
555ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang}
56da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif  // CONFIG_VP9_HIGHBITDEPTH
575ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
58ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangvoid vp9_build_inter_predictor(const uint8_t *src, int src_stride,
59ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang                               uint8_t *dst, int dst_stride,
60f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang                               const MV *src_mv,
612ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                               const struct scale_factors *sf,
621184aebb761cbeac9124c37189a80a1a58f04b6bhkuang                               int w, int h, int ref,
632ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                               const InterpKernel *kernel,
642ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                               enum mv_precision precision,
652ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                               int x, int y) {
661184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  const int is_q4 = precision == MV_PRECISION_Q4;
675ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang  const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2,
685ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                     is_q4 ? src_mv->col : src_mv->col * 2 };
692ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  MV32 mv = vp9_scale_mv(&mv_q4, x, y, sf);
702ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int subpel_x = mv.col & SUBPEL_MASK;
712ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int subpel_y = mv.row & SUBPEL_MASK;
722ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
732ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  src += (mv.row >> SUBPEL_BITS) * src_stride + (mv.col >> SUBPEL_BITS);
745ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
752ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y,
762ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                  sf, w, h, ref, kernel, sf->x_step_q4, sf->y_step_q4);
77ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
78ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
79ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic INLINE int round_mv_comp_q4(int value) {
80ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return (value < 0 ? value - 2 : value + 2) / 4;
81ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
82ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
83f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuangstatic MV mi_mv_pred_q4(const MODE_INFO *mi, int idx) {
84f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  MV res = { round_mv_comp_q4(mi->bmi[0].as_mv[idx].as_mv.row +
85f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang                              mi->bmi[1].as_mv[idx].as_mv.row +
86f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang                              mi->bmi[2].as_mv[idx].as_mv.row +
87f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang                              mi->bmi[3].as_mv[idx].as_mv.row),
88f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang             round_mv_comp_q4(mi->bmi[0].as_mv[idx].as_mv.col +
89f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang                              mi->bmi[1].as_mv[idx].as_mv.col +
90f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang                              mi->bmi[2].as_mv[idx].as_mv.col +
91f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang                              mi->bmi[3].as_mv[idx].as_mv.col) };
92f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  return res;
93ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
94ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
95ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic INLINE int round_mv_comp_q2(int value) {
96ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return (value < 0 ? value - 1 : value + 1) / 2;
97ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
98ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
99ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianstatic MV mi_mv_pred_q2(const MODE_INFO *mi, int idx, int block0, int block1) {
100ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  MV res = { round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.row +
101ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              mi->bmi[block1].as_mv[idx].as_mv.row),
102ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian             round_mv_comp_q2(mi->bmi[block0].as_mv[idx].as_mv.col +
103ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian                              mi->bmi[block1].as_mv[idx].as_mv.col) };
104ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return res;
105ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
106ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
107ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang// TODO(jkoleszar): yet another mv clamping function :-(
1081184aebb761cbeac9124c37189a80a1a58f04b6bhkuangMV clamp_mv_to_umv_border_sb(const MACROBLOCKD *xd, const MV *src_mv,
1091184aebb761cbeac9124c37189a80a1a58f04b6bhkuang                             int bw, int bh, int ss_x, int ss_y) {
110f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  // If the MV points so far into the UMV border that no visible pixels
111f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  // are used for reconstruction, the subpel part of the MV can be
112f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  // discarded and the MV limited to 16 pixels with equivalent results.
1131184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  const int spel_left = (VP9_INTERP_EXTEND + bw) << SUBPEL_BITS;
1141184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  const int spel_right = spel_left - SUBPEL_SHIFTS;
1151184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  const int spel_top = (VP9_INTERP_EXTEND + bh) << SUBPEL_BITS;
1161184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  const int spel_bottom = spel_top - SUBPEL_SHIFTS;
117f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  MV clamped_mv = {
1185ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    src_mv->row * (1 << (1 - ss_y)),
1195ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    src_mv->col * (1 << (1 - ss_x))
120f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang  };
121ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  assert(ss_x <= 1);
122ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  assert(ss_y <= 1);
123f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
1245ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang  clamp_mv(&clamped_mv,
1255ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang           xd->mb_to_left_edge * (1 << (1 - ss_x)) - spel_left,
1265ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang           xd->mb_to_right_edge * (1 << (1 - ss_x)) + spel_right,
1275ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang           xd->mb_to_top_edge * (1 << (1 - ss_y)) - spel_top,
1285ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang           xd->mb_to_bottom_edge * (1 << (1 - ss_y)) + spel_bottom);
129f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
130ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  return clamped_mv;
131ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
132ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
133da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh VenkatasubramanianMV average_split_mvs(const struct macroblockd_plane *pd,
134da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                     const MODE_INFO *mi, int ref, int block) {
135ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  const int ss_idx = ((pd->subsampling_x > 0) << 1) | (pd->subsampling_y > 0);
136ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  MV res = {0, 0};
137ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  switch (ss_idx) {
138ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case 0:
139ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      res = mi->bmi[block].as_mv[ref].as_mv;
140ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
141ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case 1:
142ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      res = mi_mv_pred_q2(mi, ref, block, block + 2);
143ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
144ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case 2:
145ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      res = mi_mv_pred_q2(mi, ref, block, block + 1);
146ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
147ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    case 3:
148ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      res = mi_mv_pred_q4(mi, ref);
149ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian      break;
150ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    default:
151da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      assert(ss_idx <= 3 && ss_idx >= 0);
152ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  }
153ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian  return res;
154ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian}
155ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian
1569b35249446b07f40ac5fcc3205f2c048616efacchkuangstatic void build_inter_predictors(MACROBLOCKD *xd, int plane, int block,
1572ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                   int bw, int bh,
1582ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                   int x, int y, int w, int h,
1599b35249446b07f40ac5fcc3205f2c048616efacchkuang                                   int mi_x, int mi_y) {
1601184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  struct macroblockd_plane *const pd = &xd->plane[plane];
1614fb68e5dd4e93c7599dc905d861de11ac39c5585hkuang  const MODE_INFO *mi = xd->mi[0];
1625ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang  const int is_compound = has_second_ref(&mi->mbmi);
163da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  const InterpKernel *kernel = vp9_filter_kernels[mi->mbmi.interp_filter];
1641184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  int ref;
1651184aebb761cbeac9124c37189a80a1a58f04b6bhkuang
1665ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang  for (ref = 0; ref < 1 + is_compound; ++ref) {
1672ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
1681184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    struct buf_2d *const pre_buf = &pd->pre[ref];
1691184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    struct buf_2d *const dst_buf = &pd->dst;
1701184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
1711184aebb761cbeac9124c37189a80a1a58f04b6bhkuang    const MV mv = mi->mbmi.sb_type < BLOCK_8X8
172ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian               ? average_split_mvs(pd, mi, ref, block)
1731184aebb761cbeac9124c37189a80a1a58f04b6bhkuang               : mi->mbmi.mv[ref].as_mv;
174f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang
175f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang    // TODO(jkoleszar): This clamping is done in the incorrect place for the
176f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang    // scaling case. It needs to be done on the scaled MV, not the pre-scaling
177f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang    // MV. Note however that it performs the subsampling aware scaling so
178f3bed9137f66ef693bd406e43b17e9a1114f1e14hkuang    // that the result is always q4.
1795ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    // mv_precision precision is MV_PRECISION_Q4.
1805ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    const MV mv_q4 = clamp_mv_to_umv_border_sb(xd, &mv, bw, bh,
1815ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                                               pd->subsampling_x,
1825ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang                                               pd->subsampling_y);
1835ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
1845ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    uint8_t *pre;
1855ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    MV32 scaled_mv;
1862ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    int xs, ys, subpel_x, subpel_y;
187da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    const int is_scaled = vp9_is_scaled(sf);
1882ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
189da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (is_scaled) {
1902263fc984bdc858ee931d3e35c87c404de923950Johann      // Co-ordinate of containing block to pixel precision.
1912263fc984bdc858ee931d3e35c87c404de923950Johann      const int x_start = (-xd->mb_to_left_edge >> (3 + pd->subsampling_x));
1922263fc984bdc858ee931d3e35c87c404de923950Johann      const int y_start = (-xd->mb_to_top_edge >> (3 + pd->subsampling_y));
1932263fc984bdc858ee931d3e35c87c404de923950Johann      if (plane == 0)
1942263fc984bdc858ee931d3e35c87c404de923950Johann        pre_buf->buf = xd->block_refs[ref]->buf->y_buffer;
1952263fc984bdc858ee931d3e35c87c404de923950Johann      else if (plane == 1)
1962263fc984bdc858ee931d3e35c87c404de923950Johann        pre_buf->buf = xd->block_refs[ref]->buf->u_buffer;
1972263fc984bdc858ee931d3e35c87c404de923950Johann      else
1982263fc984bdc858ee931d3e35c87c404de923950Johann        pre_buf->buf = xd->block_refs[ref]->buf->v_buffer;
1992263fc984bdc858ee931d3e35c87c404de923950Johann
2002263fc984bdc858ee931d3e35c87c404de923950Johann      pre_buf->buf += scaled_buffer_offset(x_start + x, y_start + y,
2012263fc984bdc858ee931d3e35c87c404de923950Johann                                           pre_buf->stride, sf);
2022263fc984bdc858ee931d3e35c87c404de923950Johann      pre = pre_buf->buf;
2032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      scaled_mv = vp9_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf);
2042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      xs = sf->x_step_q4;
2052ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      ys = sf->y_step_q4;
2065ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    } else {
2075ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      pre = pre_buf->buf + (y * pre_buf->stride + x);
2085ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      scaled_mv.row = mv_q4.row;
2095ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      scaled_mv.col = mv_q4.col;
2105ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang      xs = ys = 16;
2115ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    }
2122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    subpel_x = scaled_mv.col & SUBPEL_MASK;
2132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    subpel_y = scaled_mv.row & SUBPEL_MASK;
2142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    pre += (scaled_mv.row >> SUBPEL_BITS) * pre_buf->stride
2152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian           + (scaled_mv.col >> SUBPEL_BITS);
2165ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang
217da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#if CONFIG_VP9_HIGHBITDEPTH
218da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
219da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      high_inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
220da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                           subpel_x, subpel_y, sf, w, h, ref, kernel, xs, ys,
221da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                           xd->bd);
222da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    } else {
223da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
224da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                      subpel_x, subpel_y, sf, w, h, ref, kernel, xs, ys);
225da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    }
226da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#else
2275ae7ac49f08a179e4f054d99fcfc9dce78d26e58hkuang    inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
2284fb68e5dd4e93c7599dc905d861de11ac39c5585hkuang                    subpel_x, subpel_y, sf, w, h, ref, kernel, xs, ys);
229da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian#endif  // CONFIG_VP9_HIGHBITDEPTH
230ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  }
231ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
232ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2331184aebb761cbeac9124c37189a80a1a58f04b6bhkuangstatic void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize,
2341184aebb761cbeac9124c37189a80a1a58f04b6bhkuang                                              int mi_row, int mi_col,
2351184aebb761cbeac9124c37189a80a1a58f04b6bhkuang                                              int plane_from, int plane_to) {
2361184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  int plane;
2372ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int mi_x = mi_col * MI_SIZE;
2382ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  const int mi_y = mi_row * MI_SIZE;
2391184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  for (plane = plane_from; plane <= plane_to; ++plane) {
2402ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const BLOCK_SIZE plane_bsize = get_plane_block_size(bsize,
2412ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                                        &xd->plane[plane]);
2422ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int num_4x4_w = num_4x4_blocks_wide_lookup[plane_bsize];
2432ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int num_4x4_h = num_4x4_blocks_high_lookup[plane_bsize];
2442ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int bw = 4 * num_4x4_w;
2452ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    const int bh = 4 * num_4x4_h;
2469b35249446b07f40ac5fcc3205f2c048616efacchkuang
2474fb68e5dd4e93c7599dc905d861de11ac39c5585hkuang    if (xd->mi[0]->mbmi.sb_type < BLOCK_8X8) {
2489b35249446b07f40ac5fcc3205f2c048616efacchkuang      int i = 0, x, y;
2499b35249446b07f40ac5fcc3205f2c048616efacchkuang      assert(bsize == BLOCK_8X8);
2502ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      for (y = 0; y < num_4x4_h; ++y)
2512ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian        for (x = 0; x < num_4x4_w; ++x)
2522ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian           build_inter_predictors(xd, plane, i++, bw, bh,
2532ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                                  4 * x, 4 * y, 4, 4, mi_x, mi_y);
2549b35249446b07f40ac5fcc3205f2c048616efacchkuang    } else {
2552ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      build_inter_predictors(xd, plane, 0, bw, bh,
2562ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                             0, 0, bw, bh, mi_x, mi_y);
2579b35249446b07f40ac5fcc3205f2c048616efacchkuang    }
2581184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  }
259ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
260ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
2611184aebb761cbeac9124c37189a80a1a58f04b6bhkuangvoid vp9_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col,
2621184aebb761cbeac9124c37189a80a1a58f04b6bhkuang                                    BLOCK_SIZE bsize) {
2631184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0);
2641184aebb761cbeac9124c37189a80a1a58f04b6bhkuang}
265da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
266da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanianvoid vp9_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col,
267da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian                                    BLOCK_SIZE bsize, int plane) {
268da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, plane, plane);
269da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian}
270da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
2711184aebb761cbeac9124c37189a80a1a58f04b6bhkuangvoid vp9_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col,
2721184aebb761cbeac9124c37189a80a1a58f04b6bhkuang                                     BLOCK_SIZE bsize) {
2731184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1,
2741184aebb761cbeac9124c37189a80a1a58f04b6bhkuang                                    MAX_MB_PLANE - 1);
2751184aebb761cbeac9124c37189a80a1a58f04b6bhkuang}
276da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian
2771184aebb761cbeac9124c37189a80a1a58f04b6bhkuangvoid vp9_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
2781184aebb761cbeac9124c37189a80a1a58f04b6bhkuang                                   BLOCK_SIZE bsize) {
2791184aebb761cbeac9124c37189a80a1a58f04b6bhkuang  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0,
2801184aebb761cbeac9124c37189a80a1a58f04b6bhkuang                                    MAX_MB_PLANE - 1);
281ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang}
282ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
283ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanianvoid vp9_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE],
2842ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                          const YV12_BUFFER_CONFIG *src,
2852ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                          int mi_row, int mi_col) {
286da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  uint8_t *const buffers[MAX_MB_PLANE] = { src->y_buffer, src->u_buffer,
287da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      src->v_buffer};
288da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian  const int strides[MAX_MB_PLANE] = { src->y_stride, src->uv_stride,
289da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian      src->uv_stride};
2902ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  int i;
2912ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2922ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  for (i = 0; i < MAX_MB_PLANE; ++i) {
293ba6c59e9d7d7013b3906b6f4230b663422681848Vignesh Venkatasubramanian    struct macroblockd_plane *const pd = &planes[i];
2942ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    setup_pred_plane(&pd->dst, buffers[i], strides[i], mi_row, mi_col, NULL,
2952ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                     pd->subsampling_x, pd->subsampling_y);
2962ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
2972ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
2982ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian
2992ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanianvoid vp9_setup_pre_planes(MACROBLOCKD *xd, int idx,
3002ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                          const YV12_BUFFER_CONFIG *src,
3012ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                          int mi_row, int mi_col,
3022ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                          const struct scale_factors *sf) {
3032ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  if (src != NULL) {
3042ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    int i;
305da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    uint8_t *const buffers[MAX_MB_PLANE] = { src->y_buffer, src->u_buffer,
306da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        src->v_buffer};
307da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian    const int strides[MAX_MB_PLANE] = { src->y_stride, src->uv_stride,
308da49e34c1fb5e99681f4ad99c21d9cfd83eddb96Vignesh Venkatasubramanian        src->uv_stride};
3092ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    for (i = 0; i < MAX_MB_PLANE; ++i) {
3102ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      struct macroblockd_plane *const pd = &xd->plane[i];
3112ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian      setup_pred_plane(&pd->pre[idx], buffers[i], strides[i], mi_row, mi_col,
3122ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian                       sf, pd->subsampling_x, pd->subsampling_y);
3132ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian    }
3142ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian  }
3152ec72e65689c948e92b826ae1e867bf369e72f13Vignesh Venkatasubramanian}
316