reconinter.c 27.5 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
4
5
6
7
8
9
 * 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.
Jingning Han's avatar
Jingning Han committed
10
11
12
13
 */

#include <assert.h>

Adrian Grange's avatar
Adrian Grange committed
14
15
#include "./aom_scale_rtcd.h"
#include "./aom_config.h"
16
#include "./aom_dsp_rtcd.h"
Jingning Han's avatar
Jingning Han committed
17

Adrian Grange's avatar
Adrian Grange committed
18
#include "aom/aom_integer.h"
Jingning Han's avatar
Jingning Han committed
19

Yaowu Xu's avatar
Yaowu Xu committed
20
21
22
#include "av1/common/blockd.h"
#include "av1/common/reconinter.h"
#include "av1/common/reconintra.h"
Jingning Han's avatar
Jingning Han committed
23

24
25
#if CONFIG_AOM_HIGHBITDEPTH
void av1_highbd_build_inter_predictor(
clang-format's avatar
clang-format committed
26
27
    const uint8_t *src, int src_stride, uint8_t *dst, int dst_stride,
    const MV *src_mv, const struct scale_factors *sf, int w, int h, int ref,
28
29
    const InterpFilter *interp_filter, enum mv_precision precision, int x,
    int y, int bd) {
Jingning Han's avatar
Jingning Han committed
30
31
32
  const int is_q4 = precision == MV_PRECISION_Q4;
  const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2,
                     is_q4 ? src_mv->col : src_mv->col * 2 };
33
  MV32 mv = av1_scale_mv(&mv_q4, x, y, sf);
Jingning Han's avatar
Jingning Han committed
34
35
36
37
38
  const int subpel_x = mv.col & SUBPEL_MASK;
  const int subpel_y = mv.row & SUBPEL_MASK;

  src += (mv.row >> SUBPEL_BITS) * src_stride + (mv.col >> SUBPEL_BITS);

clang-format's avatar
clang-format committed
39
  high_inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y, sf,
40
41
                       w, h, ref, interp_filter, sf->x_step_q4, sf->y_step_q4,
                       bd);
Jingning Han's avatar
Jingning Han committed
42
}
43
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
44

clang-format's avatar
clang-format committed
45
46
47
void av1_build_inter_predictor(const uint8_t *src, int src_stride, uint8_t *dst,
                               int dst_stride, const MV *src_mv,
                               const struct scale_factors *sf, int w, int h,
48
                               int ref, const InterpFilter *interp_filter,
clang-format's avatar
clang-format committed
49
                               enum mv_precision precision, int x, int y) {
Jingning Han's avatar
Jingning Han committed
50
51
52
  const int is_q4 = precision == MV_PRECISION_Q4;
  const MV mv_q4 = { is_q4 ? src_mv->row : src_mv->row * 2,
                     is_q4 ? src_mv->col : src_mv->col * 2 };
53
  MV32 mv = av1_scale_mv(&mv_q4, x, y, sf);
Jingning Han's avatar
Jingning Han committed
54
55
56
57
58
  const int subpel_x = mv.col & SUBPEL_MASK;
  const int subpel_y = mv.row & SUBPEL_MASK;

  src += (mv.row >> SUBPEL_BITS) * src_stride + (mv.col >> SUBPEL_BITS);

clang-format's avatar
clang-format committed
59
  inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y, sf, w,
60
                  h, ref, interp_filter, sf->x_step_q4, sf->y_step_q4);
Jingning Han's avatar
Jingning Han committed
61
62
}

63
64
65
66
67
68
void build_inter_predictors(MACROBLOCKD *xd, int plane,
#if CONFIG_MOTION_VAR
                            int mi_col_offset, int mi_row_offset,
#endif  // CONFIG_MOTION_VAR
                            int block, int bw, int bh, int x, int y, int w,
                            int h, int mi_x, int mi_y) {
Jingning Han's avatar
Jingning Han committed
69
  struct macroblockd_plane *const pd = &xd->plane[plane];
70
71
72
#if CONFIG_MOTION_VAR
  const MODE_INFO *mi = xd->mi[mi_col_offset + xd->mi_stride * mi_row_offset];
#else
Jingning Han's avatar
Jingning Han committed
73
  const MODE_INFO *mi = xd->mi[0];
74
#endif  // CONFIG_MOTION_VAR
Jingning Han's avatar
Jingning Han committed
75
76
77
  const int is_compound = has_second_ref(&mi->mbmi);
  int ref;

78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#if CONFIG_SUB8X8_MC
  if (mi->mbmi.sb_type < BLOCK_8X8 && plane > 0) {
    // block size in log2
    const int b4_wl = b_width_log2_lookup[mi->mbmi.sb_type];
    const int b4_hl = b_height_log2_lookup[mi->mbmi.sb_type];
    const int b8_sl = b_width_log2_lookup[BLOCK_8X8];

    // block size
    const int b4_w = 1 << b4_wl;
    const int b4_h = 1 << b4_hl;
    const int b8_s = 1 << b8_sl;
    int idx, idy;

    const int x_base = x;
    const int y_base = y;

    // processing unit size
    const int x_step = w >> (b8_sl - b4_wl);
    const int y_step = h >> (b8_sl - b4_hl);

    for (idy = 0; idy < b8_s; idy += b4_h) {
      for (idx = 0; idx < b8_s; idx += b4_w) {
        const int chr_idx = (idy * 2) + idx;
        for (ref = 0; ref < 1 + is_compound; ++ref) {
          const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
          struct buf_2d *const pre_buf = &pd->pre[ref];
          struct buf_2d *const dst_buf = &pd->dst;
          uint8_t *dst = dst_buf->buf;
          const MV mv = mi->bmi[chr_idx].as_mv[ref].as_mv;
          const MV mv_q4 = clamp_mv_to_umv_border_sb(
              xd, &mv, bw, bh, pd->subsampling_x, pd->subsampling_y);
          uint8_t *pre;
          MV32 scaled_mv;
          int xs, ys, subpel_x, subpel_y;
          const int is_scaled = av1_is_scaled(sf);

          x = x_base + idx * x_step;
          y = y_base + idy * y_step;

          dst += dst_buf->stride * y + x;

          if (is_scaled) {
            pre =
                pre_buf->buf + scaled_buffer_offset(x, y, pre_buf->stride, sf);
            scaled_mv = av1_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf);
            xs = sf->x_step_q4;
            ys = sf->y_step_q4;
          } else {
            pre = pre_buf->buf + y * pre_buf->stride + x;
            scaled_mv.row = mv_q4.row;
            scaled_mv.col = mv_q4.col;
            xs = ys = 16;
          }

          subpel_x = scaled_mv.col & SUBPEL_MASK;
          subpel_y = scaled_mv.row & SUBPEL_MASK;
          pre += (scaled_mv.row >> SUBPEL_BITS) * pre_buf->stride +
                 (scaled_mv.col >> SUBPEL_BITS);

#if CONFIG_AOM_HIGHBITDEPTH
          if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
            high_inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
                                 subpel_x, subpel_y, sf, x_step, y_step, ref,
                                 &mi->mbmi.interp_filter, xs, ys, xd->bd);
          } else {
            inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
                            subpel_x, subpel_y, sf, x_step, y_step, ref,
                            &mi->mbmi.interp_filter, xs, ys);
          }
#else
          inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride, subpel_x,
                          subpel_y, sf, x_step, y_step, ref,
                          &mi->mbmi.interp_filter, xs, ys);
#endif
        }
      }
    }
    return;
  }
#endif

Jingning Han's avatar
Jingning Han committed
159
160
161
162
163
164
  for (ref = 0; ref < 1 + is_compound; ++ref) {
    const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
    struct buf_2d *const pre_buf = &pd->pre[ref];
    struct buf_2d *const dst_buf = &pd->dst;
    uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
    const MV mv = mi->mbmi.sb_type < BLOCK_8X8
clang-format's avatar
clang-format committed
165
166
                      ? average_split_mvs(pd, mi, ref, block)
                      : mi->mbmi.mv[ref].as_mv;
Jingning Han's avatar
Jingning Han committed
167
168
169
170
171
172

    // TODO(jkoleszar): This clamping is done in the incorrect place for the
    // scaling case. It needs to be done on the scaled MV, not the pre-scaling
    // MV. Note however that it performs the subsampling aware scaling so
    // that the result is always q4.
    // mv_precision precision is MV_PRECISION_Q4.
clang-format's avatar
clang-format committed
173
174
    const MV mv_q4 = clamp_mv_to_umv_border_sb(
        xd, &mv, bw, bh, pd->subsampling_x, pd->subsampling_y);
Jingning Han's avatar
Jingning Han committed
175
176
177
178

    uint8_t *pre;
    MV32 scaled_mv;
    int xs, ys, subpel_x, subpel_y;
179
    const int is_scaled = av1_is_scaled(sf);
Jingning Han's avatar
Jingning Han committed
180
181
182

    if (is_scaled) {
      pre = pre_buf->buf + scaled_buffer_offset(x, y, pre_buf->stride, sf);
183
      scaled_mv = av1_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf);
Jingning Han's avatar
Jingning Han committed
184
185
186
187
188
189
190
191
192
193
      xs = sf->x_step_q4;
      ys = sf->y_step_q4;
    } else {
      pre = pre_buf->buf + (y * pre_buf->stride + x);
      scaled_mv.row = mv_q4.row;
      scaled_mv.col = mv_q4.col;
      xs = ys = 16;
    }
    subpel_x = scaled_mv.col & SUBPEL_MASK;
    subpel_y = scaled_mv.row & SUBPEL_MASK;
clang-format's avatar
clang-format committed
194
195
    pre += (scaled_mv.row >> SUBPEL_BITS) * pre_buf->stride +
           (scaled_mv.col >> SUBPEL_BITS);
Jingning Han's avatar
Jingning Han committed
196

197
#if CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
198
    if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
clang-format's avatar
clang-format committed
199
      high_inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride, subpel_x,
200
201
                           subpel_y, sf, w, h, ref, &mi->mbmi.interp_filter, xs,
                           ys, xd->bd);
Jingning Han's avatar
Jingning Han committed
202
    } else {
clang-format's avatar
clang-format committed
203
      inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride, subpel_x,
204
                      subpel_y, sf, w, h, ref, &mi->mbmi.interp_filter, xs, ys);
Jingning Han's avatar
Jingning Han committed
205
206
    }
#else
clang-format's avatar
clang-format committed
207
    inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride, subpel_x,
208
                    subpel_y, sf, w, h, ref, &mi->mbmi.interp_filter, xs, ys);
209
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
210
211
212
  }
}

clang-format's avatar
clang-format committed
213
214
void av1_build_inter_predictor_sub8x8(MACROBLOCKD *xd, int plane, int i, int ir,
                                      int ic, int mi_row, int mi_col) {
215
216
217
218
219
220
221
222
223
224
225
226
227
  struct macroblockd_plane *const pd = &xd->plane[plane];
  MODE_INFO *const mi = xd->mi[0];
  const BLOCK_SIZE plane_bsize = get_plane_block_size(mi->mbmi.sb_type, pd);
  const int width = 4 * num_4x4_blocks_wide_lookup[plane_bsize];
  const int height = 4 * num_4x4_blocks_high_lookup[plane_bsize];

  uint8_t *const dst = &pd->dst.buf[(ir * pd->dst.stride + ic) << 2];
  int ref;
  const int is_compound = has_second_ref(&mi->mbmi);

  for (ref = 0; ref < 1 + is_compound; ++ref) {
    const uint8_t *pre =
        &pd->pre[ref].buf[(ir * pd->pre[ref].stride + ic) << 2];
228
#if CONFIG_AOM_HIGHBITDEPTH
clang-format's avatar
clang-format committed
229
    if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
230
      av1_highbd_build_inter_predictor(
clang-format's avatar
clang-format committed
231
232
          pre, pd->pre[ref].stride, dst, pd->dst.stride,
          &mi->bmi[i].as_mv[ref].as_mv, &xd->block_refs[ref]->sf, width, height,
233
234
          ref, &mi->mbmi.interp_filter, MV_PRECISION_Q3,
          mi_col * MI_SIZE + 4 * ic, mi_row * MI_SIZE + 4 * ir, xd->bd);
clang-format's avatar
clang-format committed
235
    } else {
236
      av1_build_inter_predictor(
clang-format's avatar
clang-format committed
237
238
          pre, pd->pre[ref].stride, dst, pd->dst.stride,
          &mi->bmi[i].as_mv[ref].as_mv, &xd->block_refs[ref]->sf, width, height,
239
240
          ref, &mi->mbmi.interp_filter, MV_PRECISION_Q3,
          mi_col * MI_SIZE + 4 * ic, mi_row * MI_SIZE + 4 * ir);
clang-format's avatar
clang-format committed
241
    }
242
#else
243
    av1_build_inter_predictor(
clang-format's avatar
clang-format committed
244
245
        pre, pd->pre[ref].stride, dst, pd->dst.stride,
        &mi->bmi[i].as_mv[ref].as_mv, &xd->block_refs[ref]->sf, width, height,
246
247
        ref, &mi->mbmi.interp_filter, MV_PRECISION_Q3,
        mi_col * MI_SIZE + 4 * ic, mi_row * MI_SIZE + 4 * ir);
248
#endif  // CONFIG_AOM_HIGHBITDEPTH
249
250
251
  }
}

Jingning Han's avatar
Jingning Han committed
252
253
254
255
256
257
258
static void build_inter_predictors_for_planes(MACROBLOCKD *xd, BLOCK_SIZE bsize,
                                              int mi_row, int mi_col,
                                              int plane_from, int plane_to) {
  int plane;
  const int mi_x = mi_col * MI_SIZE;
  const int mi_y = mi_row * MI_SIZE;
  for (plane = plane_from; plane <= plane_to; ++plane) {
259
260
261
    const struct macroblockd_plane *pd = &xd->plane[plane];
    const int bw = 4 * num_4x4_blocks_wide_lookup[bsize] >> pd->subsampling_x;
    const int bh = 4 * num_4x4_blocks_high_lookup[bsize] >> pd->subsampling_y;
Jingning Han's avatar
Jingning Han committed
262
263

    if (xd->mi[0]->mbmi.sb_type < BLOCK_8X8) {
264
265
266
267
268
269
270
      const PARTITION_TYPE bp = bsize - xd->mi[0]->mbmi.sb_type;
      const int have_vsplit = bp != PARTITION_HORZ;
      const int have_hsplit = bp != PARTITION_VERT;
      const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x);
      const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y);
      const int pw = 8 >> (have_vsplit | pd->subsampling_x);
      const int ph = 8 >> (have_hsplit | pd->subsampling_y);
271
      int x, y;
272
      assert(bp != PARTITION_NONE && bp < PARTITION_TYPES);
Jingning Han's avatar
Jingning Han committed
273
      assert(bsize == BLOCK_8X8);
274
      assert(pw * num_4x4_w == bw && ph * num_4x4_h == bh);
Jingning Han's avatar
Jingning Han committed
275
276
      for (y = 0; y < num_4x4_h; ++y)
        for (x = 0; x < num_4x4_w; ++x)
277
278
279
280
281
282
          build_inter_predictors(xd, plane,
#if CONFIG_MOTION_VAR
                                 0, 0,
#endif  // CONFIG_MOTION_VAR
                                 y * 2 + x, bw, bh, 4 * x, 4 * y, pw, ph, mi_x,
                                 mi_y);
Jingning Han's avatar
Jingning Han committed
283
    } else {
284
285
286
287
288
      build_inter_predictors(xd, plane,
#if CONFIG_MOTION_VAR
                             0, 0,
#endif  // CONFIG_MOTION_VAR
                             0, bw, bh, 0, 0, bw, bh, mi_x, mi_y);
Jingning Han's avatar
Jingning Han committed
289
290
291
292
    }
  }
}

293
void av1_build_inter_predictors_sby(MACROBLOCKD *xd, int mi_row, int mi_col,
clang-format's avatar
clang-format committed
294
                                    BLOCK_SIZE bsize) {
Jingning Han's avatar
Jingning Han committed
295
296
297
  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0, 0);
}

298
void av1_build_inter_predictors_sbp(MACROBLOCKD *xd, int mi_row, int mi_col,
clang-format's avatar
clang-format committed
299
                                    BLOCK_SIZE bsize, int plane) {
Jingning Han's avatar
Jingning Han committed
300
301
302
  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, plane, plane);
}

303
void av1_build_inter_predictors_sbuv(MACROBLOCKD *xd, int mi_row, int mi_col,
clang-format's avatar
clang-format committed
304
                                     BLOCK_SIZE bsize) {
Jingning Han's avatar
Jingning Han committed
305
306
307
308
  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 1,
                                    MAX_MB_PLANE - 1);
}

309
void av1_build_inter_predictors_sb(MACROBLOCKD *xd, int mi_row, int mi_col,
clang-format's avatar
clang-format committed
310
                                   BLOCK_SIZE bsize) {
Jingning Han's avatar
Jingning Han committed
311
312
313
314
  build_inter_predictors_for_planes(xd, bsize, mi_row, mi_col, 0,
                                    MAX_MB_PLANE - 1);
}

315
void av1_setup_dst_planes(struct macroblockd_plane planes[MAX_MB_PLANE],
clang-format's avatar
clang-format committed
316
317
                          const YV12_BUFFER_CONFIG *src, int mi_row,
                          int mi_col) {
Jingning Han's avatar
Jingning Han committed
318
  uint8_t *const buffers[MAX_MB_PLANE] = { src->y_buffer, src->u_buffer,
clang-format's avatar
clang-format committed
319
                                           src->v_buffer };
Jingning Han's avatar
Jingning Han committed
320
  const int strides[MAX_MB_PLANE] = { src->y_stride, src->uv_stride,
clang-format's avatar
clang-format committed
321
                                      src->uv_stride };
Jingning Han's avatar
Jingning Han committed
322
323
324
325
326
327
328
329
330
  int i;

  for (i = 0; i < MAX_MB_PLANE; ++i) {
    struct macroblockd_plane *const pd = &planes[i];
    setup_pred_plane(&pd->dst, buffers[i], strides[i], mi_row, mi_col, NULL,
                     pd->subsampling_x, pd->subsampling_y);
  }
}

331
void av1_setup_pre_planes(MACROBLOCKD *xd, int idx,
clang-format's avatar
clang-format committed
332
333
                          const YV12_BUFFER_CONFIG *src, int mi_row, int mi_col,
                          const struct scale_factors *sf) {
Jingning Han's avatar
Jingning Han committed
334
335
336
  if (src != NULL) {
    int i;
    uint8_t *const buffers[MAX_MB_PLANE] = { src->y_buffer, src->u_buffer,
clang-format's avatar
clang-format committed
337
                                             src->v_buffer };
Jingning Han's avatar
Jingning Han committed
338
    const int strides[MAX_MB_PLANE] = { src->y_stride, src->uv_stride,
clang-format's avatar
clang-format committed
339
                                        src->uv_stride };
Jingning Han's avatar
Jingning Han committed
340
341
342
343
344
345
346
    for (i = 0; i < MAX_MB_PLANE; ++i) {
      struct macroblockd_plane *const pd = &xd->plane[i];
      setup_pred_plane(&pd->pre[idx], buffers[i], strides[i], mi_row, mi_col,
                       sf, pd->subsampling_x, pd->subsampling_y);
    }
  }
}
347
348

#if CONFIG_MOTION_VAR
349
350
// obmc_mask_N[overlap_position]
static const uint8_t obmc_mask_1[1] = { 55 };
351

352
static const uint8_t obmc_mask_2[2] = { 45, 62 };
353

354
static const uint8_t obmc_mask_4[4] = { 39, 50, 59, 64 };
355

356
static const uint8_t obmc_mask_8[8] = { 36, 42, 48, 53, 57, 61, 63, 64 };
357

358
359
static const uint8_t obmc_mask_16[16] = { 34, 37, 40, 43, 46, 49, 52, 54,
                                          56, 58, 60, 61, 63, 64, 64, 64 };
360

361
362
363
364
static const uint8_t obmc_mask_32[32] = { 33, 35, 36, 38, 40, 41, 43, 44,
                                          45, 47, 48, 50, 51, 52, 53, 55,
                                          56, 57, 58, 59, 60, 60, 61, 62,
                                          62, 63, 63, 64, 64, 64, 64, 64 };
365

366
const uint8_t *av1_get_obmc_mask(int length) {
367
  switch (length) {
368
369
370
371
372
373
374
    case 1: return obmc_mask_1;
    case 2: return obmc_mask_2;
    case 4: return obmc_mask_4;
    case 8: return obmc_mask_8;
    case 16: return obmc_mask_16;
    case 32: return obmc_mask_32;
    default: assert(0); return NULL;
375
376
377
378
379
380
381
  }
}

// This function combines motion compensated predictions that is generated by
// top/left neighboring blocks' inter predictors with the regular inter
// prediction. We assume the original prediction (bmc) is stored in
// xd->plane[].dst.buf
382
void av1_build_obmc_inter_prediction(const AV1_COMMON *cm, MACROBLOCKD *xd,
383
                                     int mi_row, int mi_col,
384
385
386
387
                                     uint8_t *above[MAX_MB_PLANE],
                                     const int above_stride[MAX_MB_PLANE],
                                     uint8_t *left[MAX_MB_PLANE],
                                     const int left_stride[MAX_MB_PLANE]) {
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
  const TileInfo *const tile = &xd->tile;
  BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
  int plane, i, mi_step;
  const int above_available = mi_row > tile->mi_row_start;
#if CONFIG_AOM_HIGHBITDEPTH
  int is_hbd = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) ? 1 : 0;
#endif  // CONFIG_AOM_HIGHBITDEPTH

  // handle above row
  for (i = 0; above_available && i < AOMMIN(xd->n8_w, cm->mi_cols - mi_col);
       i += mi_step) {
    int mi_row_offset = -1;
    int mi_col_offset = i;
    MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
    MB_MODE_INFO *mbmi = &mi->mbmi;
    int overlap;

    mi_step = AOMMIN(xd->n8_w, num_8x8_blocks_wide_lookup[mbmi->sb_type]);

    if (!is_neighbor_overlappable(mbmi)) continue;

    overlap = num_4x4_blocks_high_lookup[bsize] << 1;

    for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
      const struct macroblockd_plane *pd = &xd->plane[plane];
413
      const int bw = (mi_step * MI_SIZE) >> pd->subsampling_x;
414
      const int bh = overlap >> pd->subsampling_y;
415
416
417
418
419
420
      const int dst_stride = pd->dst.stride;
      uint8_t *dst = &pd->dst.buf[(i * MI_SIZE) >> pd->subsampling_x];
      const int tmp_stride = above_stride[plane];
      const uint8_t *const tmp =
          &above[plane][(i * MI_SIZE) >> pd->subsampling_x];
      const uint8_t *const mask = av1_get_obmc_mask(bh);
421
422

#if CONFIG_AOM_HIGHBITDEPTH
423
424
425
426
      if (is_hbd)
        aom_highbd_blend_a64_vmask(dst, dst_stride, dst, dst_stride, tmp,
                                   tmp_stride, mask, bh, bw, xd->bd);
      else
427
#endif  // CONFIG_AOM_HIGHBITDEPTH
428
429
        aom_blend_a64_vmask(dst, dst_stride, dst, dst_stride, tmp, tmp_stride,
                            mask, bh, bw);
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
    }
  }  // each mi in the above row

  // handle left column
  if (mi_col - 1 < tile->mi_col_start) return;

  for (i = 0; i < AOMMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
    int mi_row_offset = i;
    int mi_col_offset = -1;
    int overlap;
    MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
    MB_MODE_INFO *mbmi = &mi->mbmi;

    mi_step = AOMMIN(xd->n8_h, num_8x8_blocks_high_lookup[mbmi->sb_type]);

    if (!is_neighbor_overlappable(mbmi)) continue;

    overlap = num_4x4_blocks_wide_lookup[bsize] << 1;

    for (plane = 0; plane < MAX_MB_PLANE; ++plane) {
      const struct macroblockd_plane *pd = &xd->plane[plane];
451
      const int bw = overlap >> pd->subsampling_x;
452
453
      const int bh = (mi_step * MI_SIZE) >> pd->subsampling_y;
      const int dst_stride = pd->dst.stride;
454
      uint8_t *dst =
455
456
457
458
459
          &pd->dst.buf[(i * MI_SIZE * dst_stride) >> pd->subsampling_y];
      const int tmp_stride = left_stride[plane];
      const uint8_t *const tmp =
          &left[plane][(i * MI_SIZE * tmp_stride) >> pd->subsampling_y];
      const uint8_t *const mask = av1_get_obmc_mask(bw);
460
461

#if CONFIG_AOM_HIGHBITDEPTH
462
463
464
465
      if (is_hbd)
        aom_highbd_blend_a64_hmask(dst, dst_stride, dst, dst_stride, tmp,
                                   tmp_stride, mask, bh, bw, xd->bd);
      else
466
#endif  // CONFIG_AOM_HIGHBITDEPTH
467
468
        aom_blend_a64_hmask(dst, dst_stride, dst, dst_stride, tmp, tmp_stride,
                            mask, bh, bw);
469
470
471
472
    }
  }  // each mi in the left column
}

473
void av1_build_prediction_by_above_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
474
475
                                         int mi_row, int mi_col,
                                         uint8_t *tmp_buf[MAX_MB_PLANE],
476
                                         const int tmp_stride[MAX_MB_PLANE]) {
477
478
479
  const TileInfo *const tile = &xd->tile;
  BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
  int i, j, mi_step, ref;
Yue Chen's avatar
Yue Chen committed
480
  int mb_to_right_edge_base = xd->mb_to_right_edge;
481
482
483

  if (mi_row <= tile->mi_row_start) return;

Yue Chen's avatar
Yue Chen committed
484
  xd->mb_to_bottom_edge += xd->n8_h * 32;
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
  for (i = 0; i < AOMMIN(xd->n8_w, cm->mi_cols - mi_col); i += mi_step) {
    int mi_row_offset = -1;
    int mi_col_offset = i;
    int mi_x, mi_y, bw, bh;
    MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
    MB_MODE_INFO *mbmi = &mi->mbmi;

    mi_step = AOMMIN(xd->n8_w, num_8x8_blocks_wide_lookup[mbmi->sb_type]);

    if (!is_neighbor_overlappable(mbmi)) continue;

    for (j = 0; j < MAX_MB_PLANE; ++j) {
      struct macroblockd_plane *const pd = &xd->plane[j];
      setup_pred_plane(&pd->dst, tmp_buf[j], tmp_stride[j], 0, i, NULL,
                       pd->subsampling_x, pd->subsampling_y);
    }
    for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
502
503
      const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
      const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME];
504
505
506
507
508
509
510
511
512
513

      xd->block_refs[ref] = ref_buf;
      if ((!av1_is_valid_scale(&ref_buf->sf)))
        aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
                           "Reference frame has invalid dimensions");
      av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row, mi_col + i,
                           &ref_buf->sf);
    }

    xd->mb_to_left_edge = -(((mi_col + i) * MI_SIZE) * 8);
Yue Chen's avatar
Yue Chen committed
514
515
    xd->mb_to_right_edge =
        mb_to_right_edge_base + (xd->n8_w - i - mi_step) * 64;
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
    mi_x = (mi_col + i) << MI_SIZE_LOG2;
    mi_y = mi_row << MI_SIZE_LOG2;

    for (j = 0; j < MAX_MB_PLANE; ++j) {
      const struct macroblockd_plane *pd = &xd->plane[j];
      bw = (mi_step << MI_SIZE_LOG2) >> pd->subsampling_x;
      bh = AOMMAX((num_4x4_blocks_high_lookup[bsize] << 1) >> pd->subsampling_y,
                  4);

      if (mbmi->sb_type < BLOCK_8X8) {
        const PARTITION_TYPE bp = BLOCK_8X8 - mbmi->sb_type;
        const int have_vsplit = bp != PARTITION_HORZ;
        const int have_hsplit = bp != PARTITION_VERT;
        const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x);
        const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y);
        const int pw = 8 >> (have_vsplit | pd->subsampling_x);
        int x, y;

        for (y = 0; y < num_4x4_h; ++y)
          for (x = 0; x < num_4x4_w; ++x) {
            if ((bp == PARTITION_HORZ || bp == PARTITION_SPLIT) && y == 0 &&
                !pd->subsampling_y)
              continue;

            build_inter_predictors(xd, j, mi_col_offset, mi_row_offset,
                                   y * 2 + x, bw, bh, 4 * x, 0, pw, bh, mi_x,
                                   mi_y);
          }
      } else {
        build_inter_predictors(xd, j, mi_col_offset, mi_row_offset, 0, bw, bh,
                               0, 0, bw, bh, mi_x, mi_y);
      }
    }
  }
  xd->mb_to_left_edge = -((mi_col * MI_SIZE) * 8);
Yue Chen's avatar
Yue Chen committed
551
552
  xd->mb_to_right_edge = mb_to_right_edge_base;
  xd->mb_to_bottom_edge -= xd->n8_h * 32;
553
554
}

555
void av1_build_prediction_by_left_preds(const AV1_COMMON *cm, MACROBLOCKD *xd,
556
557
                                        int mi_row, int mi_col,
                                        uint8_t *tmp_buf[MAX_MB_PLANE],
558
                                        const int tmp_stride[MAX_MB_PLANE]) {
559
560
561
  const TileInfo *const tile = &xd->tile;
  BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type;
  int i, j, mi_step, ref;
Yue Chen's avatar
Yue Chen committed
562
  int mb_to_bottom_edge_base = xd->mb_to_bottom_edge;
563
564
565

  if (mi_col - 1 < tile->mi_col_start) return;

Yue Chen's avatar
Yue Chen committed
566
  xd->mb_to_right_edge += xd->n8_w * 32;
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
  for (i = 0; i < AOMMIN(xd->n8_h, cm->mi_rows - mi_row); i += mi_step) {
    int mi_row_offset = i;
    int mi_col_offset = -1;
    int mi_x, mi_y, bw, bh;
    MODE_INFO *mi = xd->mi[mi_col_offset + mi_row_offset * xd->mi_stride];
    MB_MODE_INFO *mbmi = &mi->mbmi;

    mi_step = AOMMIN(xd->n8_h, num_8x8_blocks_high_lookup[mbmi->sb_type]);

    if (!is_neighbor_overlappable(mbmi)) continue;

    for (j = 0; j < MAX_MB_PLANE; ++j) {
      struct macroblockd_plane *const pd = &xd->plane[j];
      setup_pred_plane(&pd->dst, tmp_buf[j], tmp_stride[j], i, 0, NULL,
                       pd->subsampling_x, pd->subsampling_y);
    }
    for (ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
584
585
      const MV_REFERENCE_FRAME frame = mbmi->ref_frame[ref];
      const RefBuffer *const ref_buf = &cm->frame_refs[frame - LAST_FRAME];
586
587
588
589
590
591
592
593
594
595

      xd->block_refs[ref] = ref_buf;
      if ((!av1_is_valid_scale(&ref_buf->sf)))
        aom_internal_error(xd->error_info, AOM_CODEC_UNSUP_BITSTREAM,
                           "Reference frame has invalid dimensions");
      av1_setup_pre_planes(xd, ref, ref_buf->buf, mi_row + i, mi_col,
                           &ref_buf->sf);
    }

    xd->mb_to_top_edge = -(((mi_row + i) * MI_SIZE) * 8);
Yue Chen's avatar
Yue Chen committed
596
597
    xd->mb_to_bottom_edge =
        mb_to_bottom_edge_base + (xd->n8_h - i - mi_step) * 64;
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
    mi_x = mi_col << MI_SIZE_LOG2;
    mi_y = (mi_row + i) << MI_SIZE_LOG2;

    for (j = 0; j < MAX_MB_PLANE; ++j) {
      const struct macroblockd_plane *pd = &xd->plane[j];
      bw = AOMMAX((num_4x4_blocks_wide_lookup[bsize] << 1) >> pd->subsampling_x,
                  4);
      bh = (mi_step << MI_SIZE_LOG2) >> pd->subsampling_y;

      if (mbmi->sb_type < BLOCK_8X8) {
        const PARTITION_TYPE bp = BLOCK_8X8 - mbmi->sb_type;
        const int have_vsplit = bp != PARTITION_HORZ;
        const int have_hsplit = bp != PARTITION_VERT;
        const int num_4x4_w = 2 >> ((!have_vsplit) | pd->subsampling_x);
        const int num_4x4_h = 2 >> ((!have_hsplit) | pd->subsampling_y);
        const int ph = 8 >> (have_hsplit | pd->subsampling_y);
        int x, y;

        for (y = 0; y < num_4x4_h; ++y)
          for (x = 0; x < num_4x4_w; ++x) {
            if ((bp == PARTITION_VERT || bp == PARTITION_SPLIT) && x == 0 &&
                !pd->subsampling_x)
              continue;

            build_inter_predictors(xd, j, mi_col_offset, mi_row_offset,
                                   y * 2 + x, bw, bh, 0, 4 * y, bw, ph, mi_x,
                                   mi_y);
          }
      } else {
        build_inter_predictors(xd, j, mi_col_offset, mi_row_offset, 0, bw, bh,
                               0, 0, bw, bh, mi_x, mi_y);
      }
    }
  }
  xd->mb_to_top_edge = -((mi_row * MI_SIZE) * 8);
Yue Chen's avatar
Yue Chen committed
633
634
  xd->mb_to_bottom_edge = mb_to_bottom_edge_base;
  xd->mb_to_right_edge -= xd->n8_w * 32;
635
}
636

637
void av1_build_obmc_inter_predictors_sb(const AV1_COMMON *cm, MACROBLOCKD *xd,
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
                                        int mi_row, int mi_col) {
#if CONFIG_AOM_HIGHBITDEPTH
  DECLARE_ALIGNED(16, uint8_t, tmp_buf1[2 * MAX_MB_PLANE * MAX_SB_SQUARE]);
  DECLARE_ALIGNED(16, uint8_t, tmp_buf2[2 * MAX_MB_PLANE * MAX_SB_SQUARE]);
#else
  DECLARE_ALIGNED(16, uint8_t, tmp_buf1[MAX_MB_PLANE * MAX_SB_SQUARE]);
  DECLARE_ALIGNED(16, uint8_t, tmp_buf2[MAX_MB_PLANE * MAX_SB_SQUARE]);
#endif  // CONFIG_AOM_HIGHBITDEPTH
  uint8_t *dst_buf1[MAX_MB_PLANE], *dst_buf2[MAX_MB_PLANE];
  const int dst_stride1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE,
                                          MAX_SB_SIZE };
  const int dst_stride2[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE,
                                          MAX_SB_SIZE };

#if CONFIG_AOM_HIGHBITDEPTH
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
    int len = sizeof(uint16_t);
    dst_buf1[0] = CONVERT_TO_BYTEPTR(tmp_buf1);
    dst_buf1[1] = CONVERT_TO_BYTEPTR(tmp_buf1 + MAX_SB_SQUARE * len);
    dst_buf1[2] = CONVERT_TO_BYTEPTR(tmp_buf1 + MAX_SB_SQUARE * 2 * len);
    dst_buf2[0] = CONVERT_TO_BYTEPTR(tmp_buf2);
    dst_buf2[1] = CONVERT_TO_BYTEPTR(tmp_buf2 + MAX_SB_SQUARE * len);
    dst_buf2[2] = CONVERT_TO_BYTEPTR(tmp_buf2 + MAX_SB_SQUARE * 2 * len);
  } else {
#endif  // CONFIG_AOM_HIGHBITDEPTH
    dst_buf1[0] = tmp_buf1;
    dst_buf1[1] = tmp_buf1 + MAX_SB_SQUARE;
    dst_buf1[2] = tmp_buf1 + MAX_SB_SQUARE * 2;
    dst_buf2[0] = tmp_buf2;
    dst_buf2[1] = tmp_buf2 + MAX_SB_SQUARE;
    dst_buf2[2] = tmp_buf2 + MAX_SB_SQUARE * 2;
#if CONFIG_AOM_HIGHBITDEPTH
  }
#endif  // CONFIG_AOM_HIGHBITDEPTH
  av1_build_prediction_by_above_preds(cm, xd, mi_row, mi_col, dst_buf1,
                                      dst_stride1);
  av1_build_prediction_by_left_preds(cm, xd, mi_row, mi_col, dst_buf2,
                                     dst_stride2);
  av1_setup_dst_planes(xd->plane, get_frame_new_buffer(cm), mi_row, mi_col);
677
678
  av1_build_obmc_inter_prediction(cm, xd, mi_row, mi_col, dst_buf1, dst_stride1,
                                  dst_buf2, dst_stride2);
679
}
680
#endif  // CONFIG_MOTION_VAR