reconinter.c 115 KB
Newer Older
Jingning Han's avatar
Jingning Han committed
1
/*
Yaowu Xu's avatar
Yaowu Xu committed
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
Jingning Han's avatar
Jingning Han committed
3
 *
Yaowu Xu's avatar
Yaowu Xu committed
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>

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

Yaowu Xu's avatar
Yaowu Xu committed
18
#include "aom/aom_integer.h"
19
#include "aom_dsp/blend.h"
Jingning Han's avatar
Jingning Han committed
20

21
22
23
#include "av1/common/blockd.h"
#include "av1/common/reconinter.h"
#include "av1/common/reconintra.h"
Yue Chen's avatar
Yue Chen committed
24
#if CONFIG_MOTION_VAR
25
#include "av1/common/onyxc_int.h"
Yue Chen's avatar
Yue Chen committed
26
#endif  // CONFIG_MOTION_VAR
Yue Chen's avatar
Yue Chen committed
27
#if CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
28
#include "av1/common/warped_motion.h"
Yue Chen's avatar
Yue Chen committed
29
#endif  // CONFIG_GLOBAL_MOTION || CONFIG_WARPED_MOTION
Jingning Han's avatar
Jingning Han committed
30

31
#if CONFIG_EXT_INTER
32

clang-format's avatar
clang-format committed
33
#define NSMOOTHERS 1
34
static int get_masked_weight(int m, int smoothness) {
clang-format's avatar
clang-format committed
35
36
#define SMOOTHER_LEN 32
  static const uint8_t smoothfn[NSMOOTHERS][2 * SMOOTHER_LEN + 1] = { {
clang-format's avatar
clang-format committed
37
38
39
40
      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
      0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  2,  4,  7,  13, 21, 32, 43,
      51, 57, 60, 62, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
      64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
clang-format's avatar
clang-format committed
41
  } };
42
43
44
45
46
  if (m < -SMOOTHER_LEN)
    return 0;
  else if (m > SMOOTHER_LEN)
    return (1 << WEDGE_WEIGHT_BITS);
  else
47
    return smoothfn[smoothness][m + SMOOTHER_LEN];
48
49
}

50
// [smoother][negative][direction]
clang-format's avatar
clang-format committed
51
52
53
DECLARE_ALIGNED(16, static uint8_t,
                wedge_mask_obl[NSMOOTHERS][2][WEDGE_DIRECTIONS]
                              [MASK_MASTER_SIZE * MASK_MASTER_SIZE]);
54

clang-format's avatar
clang-format committed
55
56
DECLARE_ALIGNED(16, static uint8_t,
                wedge_signflip_lookup[BLOCK_SIZES][MAX_WEDGE_TYPES]);
57

58
59
// 3 * MAX_WEDGE_SQUARE is an easy to compute and fairly tight upper bound
// on the sum of all mask sizes up to an including MAX_WEDGE_SQUARE.
clang-format's avatar
clang-format committed
60
61
DECLARE_ALIGNED(16, static uint8_t,
                wedge_mask_buf[2 * MAX_WEDGE_TYPES * 3 * MAX_WEDGE_SQUARE]);
62
63
64

static wedge_masks_type wedge_masks[BLOCK_SIZES][2];

65
66
67
// Some unused wedge codebooks left temporarily to facilitate experiments.
// To be removed when setteld.
static wedge_code_type wedge_codebook_8_hgtw[8] = {
clang-format's avatar
clang-format committed
68
69
70
71
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
  { WEDGE_OBLIQUE27, 4, 2 },  { WEDGE_OBLIQUE27, 4, 6 },
  { WEDGE_OBLIQUE153, 4, 2 }, { WEDGE_OBLIQUE153, 4, 6 },
72
73
};

74
static wedge_code_type wedge_codebook_8_hltw[8] = {
clang-format's avatar
clang-format committed
75
76
77
78
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
  { WEDGE_OBLIQUE63, 2, 4 },  { WEDGE_OBLIQUE63, 6, 4 },
  { WEDGE_OBLIQUE117, 2, 4 }, { WEDGE_OBLIQUE117, 6, 4 },
79
80
};

81
static wedge_code_type wedge_codebook_8_heqw[8] = {
clang-format's avatar
clang-format committed
82
83
84
85
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
  { WEDGE_HORIZONTAL, 4, 2 }, { WEDGE_HORIZONTAL, 4, 6 },
  { WEDGE_VERTICAL, 2, 4 },   { WEDGE_VERTICAL, 6, 4 },
86
87
};

88
89
#if !USE_LARGE_WEDGE_CODEBOOK
static const wedge_code_type wedge_codebook_16_hgtw[16] = {
clang-format's avatar
clang-format committed
90
91
92
93
94
95
96
97
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
  { WEDGE_HORIZONTAL, 4, 2 }, { WEDGE_HORIZONTAL, 4, 4 },
  { WEDGE_HORIZONTAL, 4, 6 }, { WEDGE_VERTICAL, 4, 4 },
  { WEDGE_OBLIQUE27, 4, 2 },  { WEDGE_OBLIQUE27, 4, 6 },
  { WEDGE_OBLIQUE153, 4, 2 }, { WEDGE_OBLIQUE153, 4, 6 },
  { WEDGE_OBLIQUE63, 2, 4 },  { WEDGE_OBLIQUE63, 6, 4 },
  { WEDGE_OBLIQUE117, 2, 4 }, { WEDGE_OBLIQUE117, 6, 4 },
Debargha Mukherjee's avatar
Debargha Mukherjee committed
98
};
99

100
static const wedge_code_type wedge_codebook_16_hltw[16] = {
clang-format's avatar
clang-format committed
101
102
103
104
105
106
107
108
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
  { WEDGE_VERTICAL, 2, 4 },   { WEDGE_VERTICAL, 4, 4 },
  { WEDGE_VERTICAL, 6, 4 },   { WEDGE_HORIZONTAL, 4, 4 },
  { WEDGE_OBLIQUE27, 4, 2 },  { WEDGE_OBLIQUE27, 4, 6 },
  { WEDGE_OBLIQUE153, 4, 2 }, { WEDGE_OBLIQUE153, 4, 6 },
  { WEDGE_OBLIQUE63, 2, 4 },  { WEDGE_OBLIQUE63, 6, 4 },
  { WEDGE_OBLIQUE117, 2, 4 }, { WEDGE_OBLIQUE117, 6, 4 },
109
110
};

111
static const wedge_code_type wedge_codebook_16_heqw[16] = {
clang-format's avatar
clang-format committed
112
113
114
115
116
117
118
119
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
  { WEDGE_HORIZONTAL, 4, 2 }, { WEDGE_HORIZONTAL, 4, 6 },
  { WEDGE_VERTICAL, 2, 4 },   { WEDGE_VERTICAL, 6, 4 },
  { WEDGE_OBLIQUE27, 4, 2 },  { WEDGE_OBLIQUE27, 4, 6 },
  { WEDGE_OBLIQUE153, 4, 2 }, { WEDGE_OBLIQUE153, 4, 6 },
  { WEDGE_OBLIQUE63, 2, 4 },  { WEDGE_OBLIQUE63, 6, 4 },
  { WEDGE_OBLIQUE117, 2, 4 }, { WEDGE_OBLIQUE117, 6, 4 },
120
121
};

122
const wedge_params_type wedge_params_lookup[BLOCK_SIZES] = {
123
124
125
126
127
#if CONFIG_CB4X4
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
#endif
clang-format's avatar
clang-format committed
128
129
130
131
132
133
134
135
136
137
138
139
140
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
  { 4, wedge_codebook_16_heqw, wedge_signflip_lookup[3], 0, wedge_masks[3] },
  { 4, wedge_codebook_16_hgtw, wedge_signflip_lookup[4], 0, wedge_masks[4] },
  { 4, wedge_codebook_16_hltw, wedge_signflip_lookup[5], 0, wedge_masks[5] },
  { 4, wedge_codebook_16_heqw, wedge_signflip_lookup[6], 0, wedge_masks[6] },
  { 4, wedge_codebook_16_hgtw, wedge_signflip_lookup[7], 0, wedge_masks[7] },
  { 4, wedge_codebook_16_hltw, wedge_signflip_lookup[8], 0, wedge_masks[8] },
  { 4, wedge_codebook_16_heqw, wedge_signflip_lookup[9], 0, wedge_masks[9] },
  { 0, wedge_codebook_8_hgtw, wedge_signflip_lookup[10], 0, wedge_masks[10] },
  { 0, wedge_codebook_8_hltw, wedge_signflip_lookup[11], 0, wedge_masks[11] },
  { 0, wedge_codebook_8_heqw, wedge_signflip_lookup[12], 0, wedge_masks[12] },
141
#if CONFIG_EXT_PARTITION
clang-format's avatar
clang-format committed
142
143
144
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
145
#endif  // CONFIG_EXT_PARTITION
146
147
};

148
149
150
#else

static const wedge_code_type wedge_codebook_32_hgtw[32] = {
clang-format's avatar
clang-format committed
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
  { WEDGE_HORIZONTAL, 4, 2 }, { WEDGE_HORIZONTAL, 4, 4 },
  { WEDGE_HORIZONTAL, 4, 6 }, { WEDGE_VERTICAL, 4, 4 },
  { WEDGE_OBLIQUE27, 4, 1 },  { WEDGE_OBLIQUE27, 4, 2 },
  { WEDGE_OBLIQUE27, 4, 3 },  { WEDGE_OBLIQUE27, 4, 5 },
  { WEDGE_OBLIQUE27, 4, 6 },  { WEDGE_OBLIQUE27, 4, 7 },
  { WEDGE_OBLIQUE153, 4, 1 }, { WEDGE_OBLIQUE153, 4, 2 },
  { WEDGE_OBLIQUE153, 4, 3 }, { WEDGE_OBLIQUE153, 4, 5 },
  { WEDGE_OBLIQUE153, 4, 6 }, { WEDGE_OBLIQUE153, 4, 7 },
  { WEDGE_OBLIQUE63, 1, 4 },  { WEDGE_OBLIQUE63, 2, 4 },
  { WEDGE_OBLIQUE63, 3, 4 },  { WEDGE_OBLIQUE63, 5, 4 },
  { WEDGE_OBLIQUE63, 6, 4 },  { WEDGE_OBLIQUE63, 7, 4 },
  { WEDGE_OBLIQUE117, 1, 4 }, { WEDGE_OBLIQUE117, 2, 4 },
  { WEDGE_OBLIQUE117, 3, 4 }, { WEDGE_OBLIQUE117, 5, 4 },
  { WEDGE_OBLIQUE117, 6, 4 }, { WEDGE_OBLIQUE117, 7, 4 },
167
168
};

169
static const wedge_code_type wedge_codebook_32_hltw[32] = {
clang-format's avatar
clang-format committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
  { WEDGE_VERTICAL, 2, 4 },   { WEDGE_VERTICAL, 4, 4 },
  { WEDGE_VERTICAL, 6, 4 },   { WEDGE_HORIZONTAL, 4, 4 },
  { WEDGE_OBLIQUE27, 4, 1 },  { WEDGE_OBLIQUE27, 4, 2 },
  { WEDGE_OBLIQUE27, 4, 3 },  { WEDGE_OBLIQUE27, 4, 5 },
  { WEDGE_OBLIQUE27, 4, 6 },  { WEDGE_OBLIQUE27, 4, 7 },
  { WEDGE_OBLIQUE153, 4, 1 }, { WEDGE_OBLIQUE153, 4, 2 },
  { WEDGE_OBLIQUE153, 4, 3 }, { WEDGE_OBLIQUE153, 4, 5 },
  { WEDGE_OBLIQUE153, 4, 6 }, { WEDGE_OBLIQUE153, 4, 7 },
  { WEDGE_OBLIQUE63, 1, 4 },  { WEDGE_OBLIQUE63, 2, 4 },
  { WEDGE_OBLIQUE63, 3, 4 },  { WEDGE_OBLIQUE63, 5, 4 },
  { WEDGE_OBLIQUE63, 6, 4 },  { WEDGE_OBLIQUE63, 7, 4 },
  { WEDGE_OBLIQUE117, 1, 4 }, { WEDGE_OBLIQUE117, 2, 4 },
  { WEDGE_OBLIQUE117, 3, 4 }, { WEDGE_OBLIQUE117, 5, 4 },
  { WEDGE_OBLIQUE117, 6, 4 }, { WEDGE_OBLIQUE117, 7, 4 },
186
187
};

188
static const wedge_code_type wedge_codebook_32_heqw[32] = {
clang-format's avatar
clang-format committed
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  { WEDGE_OBLIQUE27, 4, 4 },  { WEDGE_OBLIQUE63, 4, 4 },
  { WEDGE_OBLIQUE117, 4, 4 }, { WEDGE_OBLIQUE153, 4, 4 },
  { WEDGE_HORIZONTAL, 4, 2 }, { WEDGE_HORIZONTAL, 4, 6 },
  { WEDGE_VERTICAL, 2, 4 },   { WEDGE_VERTICAL, 6, 4 },
  { WEDGE_OBLIQUE27, 4, 1 },  { WEDGE_OBLIQUE27, 4, 2 },
  { WEDGE_OBLIQUE27, 4, 3 },  { WEDGE_OBLIQUE27, 4, 5 },
  { WEDGE_OBLIQUE27, 4, 6 },  { WEDGE_OBLIQUE27, 4, 7 },
  { WEDGE_OBLIQUE153, 4, 1 }, { WEDGE_OBLIQUE153, 4, 2 },
  { WEDGE_OBLIQUE153, 4, 3 }, { WEDGE_OBLIQUE153, 4, 5 },
  { WEDGE_OBLIQUE153, 4, 6 }, { WEDGE_OBLIQUE153, 4, 7 },
  { WEDGE_OBLIQUE63, 1, 4 },  { WEDGE_OBLIQUE63, 2, 4 },
  { WEDGE_OBLIQUE63, 3, 4 },  { WEDGE_OBLIQUE63, 5, 4 },
  { WEDGE_OBLIQUE63, 6, 4 },  { WEDGE_OBLIQUE63, 7, 4 },
  { WEDGE_OBLIQUE117, 1, 4 }, { WEDGE_OBLIQUE117, 2, 4 },
  { WEDGE_OBLIQUE117, 3, 4 }, { WEDGE_OBLIQUE117, 5, 4 },
  { WEDGE_OBLIQUE117, 6, 4 }, { WEDGE_OBLIQUE117, 7, 4 },
205
206
};

207
const wedge_params_type wedge_params_lookup[BLOCK_SIZES] = {
208
209
210
211
212
#if CONFIG_CB4X4
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
#endif
clang-format's avatar
clang-format committed
213
214
215
216
217
218
219
220
221
222
223
224
225
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
  { 5, wedge_codebook_32_heqw, wedge_signflip_lookup[3], 0, wedge_masks[3] },
  { 5, wedge_codebook_32_hgtw, wedge_signflip_lookup[4], 0, wedge_masks[4] },
  { 5, wedge_codebook_32_hltw, wedge_signflip_lookup[5], 0, wedge_masks[5] },
  { 5, wedge_codebook_32_heqw, wedge_signflip_lookup[6], 0, wedge_masks[6] },
  { 5, wedge_codebook_32_hgtw, wedge_signflip_lookup[7], 0, wedge_masks[7] },
  { 5, wedge_codebook_32_hltw, wedge_signflip_lookup[8], 0, wedge_masks[8] },
  { 5, wedge_codebook_32_heqw, wedge_signflip_lookup[9], 0, wedge_masks[9] },
  { 0, wedge_codebook_8_hgtw, wedge_signflip_lookup[10], 0, wedge_masks[10] },
  { 0, wedge_codebook_8_hltw, wedge_signflip_lookup[11], 0, wedge_masks[11] },
  { 0, wedge_codebook_8_heqw, wedge_signflip_lookup[12], 0, wedge_masks[12] },
Debargha Mukherjee's avatar
Debargha Mukherjee committed
226
#if CONFIG_EXT_PARTITION
clang-format's avatar
clang-format committed
227
228
229
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
  { 0, NULL, NULL, 0, NULL },
Debargha Mukherjee's avatar
Debargha Mukherjee committed
230
#endif  // CONFIG_EXT_PARTITION
231
};
232
#endif  // USE_LARGE_WEDGE_CODEBOOK
233

clang-format's avatar
clang-format committed
234
static const uint8_t *get_wedge_mask_inplace(int wedge_index, int neg,
235
                                             BLOCK_SIZE sb_type) {
Debargha Mukherjee's avatar
Debargha Mukherjee committed
236
  const uint8_t *master;
237
238
  const int bh = block_size_high[sb_type];
  const int bw = block_size_wide[sb_type];
239
240
241
  const wedge_code_type *a =
      wedge_params_lookup[sb_type].codebook + wedge_index;
  const int smoother = wedge_params_lookup[sb_type].smoother;
242
  int woff, hoff;
243
244
245
246
247
248
249
  const uint8_t wsignflip = wedge_params_lookup[sb_type].signflip[wedge_index];

  assert(wedge_index >= 0 &&
         wedge_index < (1 << get_wedge_bits_lookup(sb_type)));
  woff = (a->x_offset * bw) >> 3;
  hoff = (a->y_offset * bh) >> 3;
  master = wedge_mask_obl[smoother][neg ^ wsignflip][a->direction] +
clang-format's avatar
clang-format committed
250
251
           MASK_MASTER_STRIDE * (MASK_MASTER_SIZE / 2 - hoff) +
           MASK_MASTER_SIZE / 2 - woff;
Debargha Mukherjee's avatar
Debargha Mukherjee committed
252
253
254
  return master;
}

Yaowu Xu's avatar
Yaowu Xu committed
255
256
257
const uint8_t *av1_get_soft_mask(int wedge_index, int wedge_sign,
                                 BLOCK_SIZE sb_type, int offset_x,
                                 int offset_y) {
258
  const uint8_t *mask =
259
      get_wedge_mask_inplace(wedge_index, wedge_sign, sb_type);
clang-format's avatar
clang-format committed
260
  if (mask) mask -= (offset_x + offset_y * MASK_MASTER_STRIDE);
261
  return mask;
262
263
}

264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
#if CONFIG_COMPOUND_SEGMENT
static uint8_t *invert_mask(uint8_t *mask_inv_buffer, const uint8_t *const mask,
                            int h, int w, int stride) {
  int i, j;

  for (i = 0; i < h; ++i)
    for (j = 0; j < w; ++j) {
      mask_inv_buffer[i * stride + j] =
          AOM_BLEND_A64_MAX_ALPHA - mask[i * stride + j];
    }
  return mask_inv_buffer;
}
#endif  // CONFIG_COMPOUND_SEGMENT

const uint8_t *av1_get_compound_type_mask_inverse(
    const INTERINTER_COMPOUND_DATA *const comp_data,
#if CONFIG_COMPOUND_SEGMENT
    uint8_t *mask_buffer, int h, int w, int stride,
#endif
    BLOCK_SIZE sb_type) {
284
285
286
  assert(is_masked_compound_type(comp_data->type));
  switch (comp_data->type) {
    case COMPOUND_WEDGE:
287
288
      return av1_get_contiguous_soft_mask(comp_data->wedge_index,
                                          !comp_data->wedge_sign, sb_type);
289
290
#if CONFIG_COMPOUND_SEGMENT
    case COMPOUND_SEG:
291
      return invert_mask(mask_buffer, comp_data->seg_mask, h, w, stride);
292
#endif  // CONFIG_COMPOUND_SEGMENT
293
294
295
    default: assert(0); return NULL;
  }
}
296

297
298
299
300
301
302
303
const uint8_t *av1_get_compound_type_mask(
    const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type) {
  assert(is_masked_compound_type(comp_data->type));
  switch (comp_data->type) {
    case COMPOUND_WEDGE:
      return av1_get_contiguous_soft_mask(comp_data->wedge_index,
                                          comp_data->wedge_sign, sb_type);
304
#if CONFIG_COMPOUND_SEGMENT
305
306
307
308
309
310
311
    case COMPOUND_SEG: return comp_data->seg_mask;
#endif  // CONFIG_COMPOUND_SEGMENT
    default: assert(0); return NULL;
  }
}

#if CONFIG_COMPOUND_SEGMENT
312
313
314
#if COMPOUND_SEGMENT_TYPE == 0
static void uniform_mask(uint8_t *mask, int which_inverse, BLOCK_SIZE sb_type,
                         int h, int w, int mask_val) {
315
316
317
318
319
320
321
322
323
324
  int i, j;
  int block_stride = block_size_wide[sb_type];
  for (i = 0; i < h; ++i)
    for (j = 0; j < w; ++j) {
      mask[i * block_stride + j] =
          which_inverse ? AOM_BLEND_A64_MAX_ALPHA - mask_val : mask_val;
    }
}

void build_compound_seg_mask(uint8_t *mask, SEG_MASK_TYPE mask_type,
325
326
327
328
329
330
331
                             const uint8_t *src0, int src0_stride,
                             const uint8_t *src1, int src1_stride,
                             BLOCK_SIZE sb_type, int h, int w) {
  (void)src0;
  (void)src1;
  (void)src0_stride;
  (void)src1_stride;
332
333
334
335
336
  switch (mask_type) {
    case UNIFORM_45: uniform_mask(mask, 0, sb_type, h, w, 45); break;
    case UNIFORM_45_INV: uniform_mask(mask, 1, sb_type, h, w, 45); break;
    default: assert(0);
  }
337
}
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380

#if CONFIG_AOM_HIGHBITDEPTH
void build_compound_seg_mask_highbd(uint8_t *mask, SEG_MASK_TYPE mask_type,
                                    const uint8_t *src0, int src0_stride,
                                    const uint8_t *src1, int src1_stride,
                                    BLOCK_SIZE sb_type, int h, int w, int bd) {
  (void)src0;
  (void)src1;
  (void)src0_stride;
  (void)src1_stride;
  (void)bd;
  switch (mask_type) {
    case UNIFORM_45: uniform_mask(mask, 0, sb_type, h, w, 45); break;
    case UNIFORM_45_INV: uniform_mask(mask, 1, sb_type, h, w, 45); break;
    default: assert(0);
  }
}
#endif  // CONFIG_AOM_HIGHBITDEPTH

#elif COMPOUND_SEGMENT_TYPE == 1
#define DIFF_FACTOR 16
static void diffwtd_mask(uint8_t *mask, int which_inverse, int mask_base,
                         const uint8_t *src0, int src0_stride,
                         const uint8_t *src1, int src1_stride,
                         BLOCK_SIZE sb_type, int h, int w) {
  int i, j, m, diff;
  int block_stride = block_size_wide[sb_type];
  for (i = 0; i < h; ++i) {
    for (j = 0; j < w; ++j) {
      diff =
          abs((int)src0[i * src0_stride + j] - (int)src1[i * src1_stride + j]);
      m = clamp(mask_base + (diff / DIFF_FACTOR), 0, AOM_BLEND_A64_MAX_ALPHA);
      mask[i * block_stride + j] =
          which_inverse ? AOM_BLEND_A64_MAX_ALPHA - m : m;
    }
  }
}

void build_compound_seg_mask(uint8_t *mask, SEG_MASK_TYPE mask_type,
                             const uint8_t *src0, int src0_stride,
                             const uint8_t *src1, int src1_stride,
                             BLOCK_SIZE sb_type, int h, int w) {
  switch (mask_type) {
Yaowu Xu's avatar
Yaowu Xu committed
381
382
    case DIFFWTD_42:
      diffwtd_mask(mask, 0, 42, src0, src0_stride, src1, src1_stride, sb_type,
383
384
                   h, w);
      break;
Yaowu Xu's avatar
Yaowu Xu committed
385
386
    case DIFFWTD_42_INV:
      diffwtd_mask(mask, 1, 42, src0, src0_stride, src1, src1_stride, sb_type,
387
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
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
                   h, w);
      break;
    default: assert(0);
  }
}

#if CONFIG_AOM_HIGHBITDEPTH
static void diffwtd_mask_highbd(uint8_t *mask, int which_inverse, int mask_base,
                                const uint16_t *src0, int src0_stride,
                                const uint16_t *src1, int src1_stride,
                                BLOCK_SIZE sb_type, int h, int w, int bd) {
  int i, j, m, diff;
  int block_stride = block_size_wide[sb_type];
  for (i = 0; i < h; ++i) {
    for (j = 0; j < w; ++j) {
      diff = abs((int)src0[i * src0_stride + j] -
                 (int)src1[i * src1_stride + j]) >>
             (bd - 8);
      m = clamp(mask_base + (diff / DIFF_FACTOR), 0, AOM_BLEND_A64_MAX_ALPHA);
      mask[i * block_stride + j] =
          which_inverse ? AOM_BLEND_A64_MAX_ALPHA - m : m;
    }
  }
}

void build_compound_seg_mask_highbd(uint8_t *mask, SEG_MASK_TYPE mask_type,
                                    const uint8_t *src0, int src0_stride,
                                    const uint8_t *src1, int src1_stride,
                                    BLOCK_SIZE sb_type, int h, int w, int bd) {
  switch (mask_type) {
    case DIFFWTD_42:
      diffwtd_mask_highbd(mask, 0, 42, CONVERT_TO_SHORTPTR(src0), src0_stride,
                          CONVERT_TO_SHORTPTR(src1), src1_stride, sb_type, h, w,
                          bd);
      break;
    case DIFFWTD_42_INV:
      diffwtd_mask_highbd(mask, 1, 42, CONVERT_TO_SHORTPTR(src0), src0_stride,
                          CONVERT_TO_SHORTPTR(src1), src1_stride, sb_type, h, w,
                          bd);
      break;
    default: assert(0);
  }
}
#endif  // CONFIG_AOM_HIGHBITDEPTH
#endif  // COMPOUND_SEGMENT_TYPE
432
#endif  // CONFIG_COMPOUND_SEGMENT
433

434
static void init_wedge_master_masks() {
435
436
437
438
  int i, j, s;
  const int w = MASK_MASTER_SIZE;
  const int h = MASK_MASTER_SIZE;
  const int stride = MASK_MASTER_STRIDE;
clang-format's avatar
clang-format committed
439
  const int a[2] = { 2, 1 };
440
441
442
443
444
445
446
447
  const double asqrt = sqrt(a[0] * a[0] + a[1] * a[1]);
  for (s = 0; s < NSMOOTHERS; s++) {
    for (i = 0; i < h; ++i)
      for (j = 0; j < w; ++j) {
        int x = (2 * j + 1 - w);
        int y = (2 * i + 1 - h);
        int m = (int)rint((a[0] * x + a[1] * y) / asqrt);
        wedge_mask_obl[s][1][WEDGE_OBLIQUE63][i * stride + j] =
clang-format's avatar
clang-format committed
448
449
            wedge_mask_obl[s][1][WEDGE_OBLIQUE27][j * stride + i] =
                get_masked_weight(m, s);
450
        wedge_mask_obl[s][1][WEDGE_OBLIQUE117][i * stride + w - 1 - j] =
clang-format's avatar
clang-format committed
451
452
            wedge_mask_obl[s][1][WEDGE_OBLIQUE153][(w - 1 - j) * stride + i] =
                (1 << WEDGE_WEIGHT_BITS) - get_masked_weight(m, s);
453
        wedge_mask_obl[s][0][WEDGE_OBLIQUE63][i * stride + j] =
clang-format's avatar
clang-format committed
454
455
            wedge_mask_obl[s][0][WEDGE_OBLIQUE27][j * stride + i] =
                (1 << WEDGE_WEIGHT_BITS) - get_masked_weight(m, s);
456
        wedge_mask_obl[s][0][WEDGE_OBLIQUE117][i * stride + w - 1 - j] =
clang-format's avatar
clang-format committed
457
458
            wedge_mask_obl[s][0][WEDGE_OBLIQUE153][(w - 1 - j) * stride + i] =
                get_masked_weight(m, s);
459
        wedge_mask_obl[s][1][WEDGE_VERTICAL][i * stride + j] =
clang-format's avatar
clang-format committed
460
461
            wedge_mask_obl[s][1][WEDGE_HORIZONTAL][j * stride + i] =
                get_masked_weight(x, s);
462
        wedge_mask_obl[s][0][WEDGE_VERTICAL][i * stride + j] =
clang-format's avatar
clang-format committed
463
464
            wedge_mask_obl[s][0][WEDGE_HORIZONTAL][j * stride + i] =
                (1 << WEDGE_WEIGHT_BITS) - get_masked_weight(x, s);
465
466
      }
  }
467
468
469
470
471
472
473
474
475
}

// If the signs for the wedges for various blocksizes are
// inconsistent flip the sign flag. Do it only once for every
// wedge codebook.
static void init_wedge_signs() {
  BLOCK_SIZE sb_type;
  memset(wedge_signflip_lookup, 0, sizeof(wedge_signflip_lookup));
  for (sb_type = BLOCK_4X4; sb_type < BLOCK_SIZES; ++sb_type) {
476
477
    const int bw = block_size_wide[sb_type];
    const int bh = block_size_high[sb_type];
478
479
480
481
482
483
484
485
    const wedge_params_type wedge_params = wedge_params_lookup[sb_type];
    const int wbits = wedge_params.bits;
    const int wtypes = 1 << wbits;
    int i, w;
    if (wbits == 0) continue;
    for (w = 0; w < wtypes; ++w) {
      const uint8_t *mask = get_wedge_mask_inplace(w, 0, sb_type);
      int sum = 0;
clang-format's avatar
clang-format committed
486
487
      for (i = 0; i < bw; ++i) sum += mask[i];
      for (i = 0; i < bh; ++i) sum += mask[i * MASK_MASTER_STRIDE];
488
489
490
491
492
493
494
495
496
497
498
499
      sum = (sum + (bw + bh) / 2) / (bw + bh);
      wedge_params.signflip[w] = (sum < 32);
    }
  }
}

static void init_wedge_masks() {
  uint8_t *dst = wedge_mask_buf;
  BLOCK_SIZE bsize;
  memset(wedge_masks, 0, sizeof(wedge_masks));
  for (bsize = BLOCK_4X4; bsize < BLOCK_SIZES; ++bsize) {
    const uint8_t *mask;
500
501
    const int bw = block_size_wide[bsize];
    const int bh = block_size_high[bsize];
502
503
504
505
506
507
508
    const wedge_params_type *wedge_params = &wedge_params_lookup[bsize];
    const int wbits = wedge_params->bits;
    const int wtypes = 1 << wbits;
    int w;
    if (wbits == 0) continue;
    for (w = 0; w < wtypes; ++w) {
      mask = get_wedge_mask_inplace(w, 0, bsize);
Yaowu Xu's avatar
Yaowu Xu committed
509
      aom_convolve_copy(mask, MASK_MASTER_STRIDE, dst, bw, NULL, 0, NULL, 0, bw,
clang-format's avatar
clang-format committed
510
                        bh);
511
512
513
514
      wedge_params->masks[0][w] = dst;
      dst += bw * bh;

      mask = get_wedge_mask_inplace(w, 1, bsize);
Yaowu Xu's avatar
Yaowu Xu committed
515
      aom_convolve_copy(mask, MASK_MASTER_STRIDE, dst, bw, NULL, 0, NULL, 0, bw,
clang-format's avatar
clang-format committed
516
                        bh);
517
518
519
520
521
522
523
524
      wedge_params->masks[1][w] = dst;
      dst += bw * bh;
    }
    assert(sizeof(wedge_mask_buf) >= (size_t)(dst - wedge_mask_buf));
  }
}

// Equation of line: f(x, y) = a[0]*(x - a[2]*w/8) + a[1]*(y - a[3]*h/8) = 0
Yaowu Xu's avatar
Yaowu Xu committed
525
void av1_init_wedge_masks() {
526
  init_wedge_master_masks();
527
  init_wedge_signs();
528
  init_wedge_masks();
529
530
}

531
532
#if CONFIG_SUPERTX
static void build_masked_compound_wedge_extend(
clang-format's avatar
clang-format committed
533
534
535
    uint8_t *dst, int dst_stride, const uint8_t *src0, int src0_stride,
    const uint8_t *src1, int src1_stride, int wedge_index, int wedge_sign,
    BLOCK_SIZE sb_type, int wedge_offset_x, int wedge_offset_y, int h, int w) {
536
537
  const int subh = (2 << b_height_log2_lookup[sb_type]) == h;
  const int subw = (2 << b_width_log2_lookup[sb_type]) == w;
Yaowu Xu's avatar
Yaowu Xu committed
538
539
540
  const uint8_t *mask = av1_get_soft_mask(wedge_index, wedge_sign, sb_type,
                                          wedge_offset_x, wedge_offset_y);
  aom_blend_a64_mask(dst, dst_stride, src0, src0_stride, src1, src1_stride,
clang-format's avatar
clang-format committed
541
                     mask, MASK_MASTER_STRIDE, h, w, subh, subw);
542
543
}

Yaowu Xu's avatar
Yaowu Xu committed
544
#if CONFIG_AOM_HIGHBITDEPTH
545
static void build_masked_compound_wedge_extend_highbd(
clang-format's avatar
clang-format committed
546
547
548
549
    uint8_t *dst_8, int dst_stride, const uint8_t *src0_8, int src0_stride,
    const uint8_t *src1_8, int src1_stride, int wedge_index, int wedge_sign,
    BLOCK_SIZE sb_type, int wedge_offset_x, int wedge_offset_y, int h, int w,
    int bd) {
550
551
  const int subh = (2 << b_height_log2_lookup[sb_type]) == h;
  const int subw = (2 << b_width_log2_lookup[sb_type]) == w;
Yaowu Xu's avatar
Yaowu Xu committed
552
553
554
  const uint8_t *mask = av1_get_soft_mask(wedge_index, wedge_sign, sb_type,
                                          wedge_offset_x, wedge_offset_y);
  aom_highbd_blend_a64_mask(dst_8, dst_stride, src0_8, src0_stride, src1_8,
clang-format's avatar
clang-format committed
555
556
                            src1_stride, mask, MASK_MASTER_STRIDE, h, w, subh,
                            subw, bd);
557
}
Yaowu Xu's avatar
Yaowu Xu committed
558
#endif  // CONFIG_AOM_HIGHBITDEPTH
559
#endif  // CONFIG_SUPERTX
560

561
562
563
564
565
static void build_masked_compound(
    uint8_t *dst, int dst_stride, const uint8_t *src0, int src0_stride,
    const uint8_t *src1, int src1_stride,
    const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type, int h,
    int w) {
566
567
568
569
  // Derive subsampling from h and w passed in. May be refactored to
  // pass in subsampling factors directly.
  const int subh = (2 << b_height_log2_lookup[sb_type]) == h;
  const int subw = (2 << b_width_log2_lookup[sb_type]) == w;
570
  const uint8_t *mask = av1_get_compound_type_mask(comp_data, sb_type);
Yaowu Xu's avatar
Yaowu Xu committed
571
  aom_blend_a64_mask(dst, dst_stride, src0, src0_stride, src1, src1_stride,
572
                     mask, block_size_wide[sb_type], h, w, subh, subw);
573
574
}

Yaowu Xu's avatar
Yaowu Xu committed
575
#if CONFIG_AOM_HIGHBITDEPTH
576
static void build_masked_compound_highbd(
clang-format's avatar
clang-format committed
577
    uint8_t *dst_8, int dst_stride, const uint8_t *src0_8, int src0_stride,
578
579
580
    const uint8_t *src1_8, int src1_stride,
    const INTERINTER_COMPOUND_DATA *const comp_data, BLOCK_SIZE sb_type, int h,
    int w, int bd) {
581
582
583
584
  // Derive subsampling from h and w passed in. May be refactored to
  // pass in subsampling factors directly.
  const int subh = (2 << b_height_log2_lookup[sb_type]) == h;
  const int subw = (2 << b_width_log2_lookup[sb_type]) == w;
585
586
587
  const uint8_t *mask = av1_get_compound_type_mask(comp_data, sb_type);
  // const uint8_t *mask =
  //     av1_get_contiguous_soft_mask(wedge_index, wedge_sign, sb_type);
588
589
590
  aom_highbd_blend_a64_mask(dst_8, dst_stride, src0_8, src0_stride, src1_8,
                            src1_stride, mask, block_size_wide[sb_type], h, w,
                            subh, subw, bd);
591
}
Yaowu Xu's avatar
Yaowu Xu committed
592
#endif  // CONFIG_AOM_HIGHBITDEPTH
593

Yaowu Xu's avatar
Yaowu Xu committed
594
595
596
597
598
void av1_make_masked_inter_predictor(const uint8_t *pre, int pre_stride,
                                     uint8_t *dst, int dst_stride,
                                     const int subpel_x, const int subpel_y,
                                     const struct scale_factors *sf, int w,
                                     int h,
599
#if CONFIG_DUAL_FILTER
James Zern's avatar
James Zern committed
600
                                     const InterpFilter *interp_filter,
601
#else
James Zern's avatar
James Zern committed
602
                                     const InterpFilter interp_filter,
603
#endif
Yaowu Xu's avatar
Yaowu Xu committed
604
                                     int xs, int ys,
605
#if CONFIG_SUPERTX
Yaowu Xu's avatar
Yaowu Xu committed
606
                                     int wedge_offset_x, int wedge_offset_y,
607
#endif  // CONFIG_SUPERTX
608
609
610
611
612
613
#if CONFIG_COMPOUND_SEGMENT
                                     int plane,
#endif  // CONFIG_COMPOUND_SEGMENT
                                     MACROBLOCKD *xd) {
  MODE_INFO *mi = xd->mi[0];
  INTERINTER_COMPOUND_DATA *comp_data = &mi->mbmi.interinter_compound_data;
clang-format's avatar
clang-format committed
614
615
// The prediction filter types used here should be those for
// the second reference block.
Geza Lore's avatar
Geza Lore committed
616
#if CONFIG_DUAL_FILTER
James Zern's avatar
James Zern committed
617
  InterpFilter tmp_ipf[4] = {
Geza Lore's avatar
Geza Lore committed
618
    interp_filter[2], interp_filter[3], interp_filter[2], interp_filter[3],
619
  };
Geza Lore's avatar
Geza Lore committed
620
#else
James Zern's avatar
James Zern committed
621
  InterpFilter tmp_ipf = interp_filter;
Geza Lore's avatar
Geza Lore committed
622
#endif  // CONFIG_DUAL_FILTER
623
  ConvolveParams conv_params = get_conv_params(0);
Yaowu Xu's avatar
Yaowu Xu committed
624
#if CONFIG_AOM_HIGHBITDEPTH
625
  DECLARE_ALIGNED(16, uint8_t, tmp_dst_[2 * MAX_SB_SQUARE]);
clang-format's avatar
clang-format committed
626
627
628
  uint8_t *tmp_dst = (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
                         ? CONVERT_TO_BYTEPTR(tmp_dst_)
                         : tmp_dst_;
Yaowu Xu's avatar
Yaowu Xu committed
629
  av1_make_inter_predictor(pre, pre_stride, tmp_dst, MAX_SB_SIZE, subpel_x,
630
631
                           subpel_y, sf, w, h, &conv_params, tmp_ipf, xs, ys,
                           xd);
632
633
#if CONFIG_SUPERTX
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
634
    build_masked_compound_wedge_extend_highbd(
clang-format's avatar
clang-format committed
635
        dst, dst_stride, dst, dst_stride, tmp_dst, MAX_SB_SIZE,
636
637
        comp_data->wedge_index, comp_data->wedge_sign, mi->mbmi.sb_type,
        wedge_offset_x, wedge_offset_y, h, w, xd->bd);
638
  else
639
    build_masked_compound_wedge_extend(
clang-format's avatar
clang-format committed
640
        dst, dst_stride, dst, dst_stride, tmp_dst, MAX_SB_SIZE,
641
642
        comp_data->wedge_index, comp_data->wedge_sign, mi->mbmi.sb_type,
        wedge_offset_x, wedge_offset_y, h, w);
643
#else
644
645
646
647
648
649
650
651
652
653
654
655
#if CONFIG_COMPOUND_SEGMENT
  if (!plane && comp_data->type == COMPOUND_SEG) {
    if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
      build_compound_seg_mask_highbd(comp_data->seg_mask, comp_data->mask_type,
                                     dst, dst_stride, tmp_dst, MAX_SB_SIZE,
                                     mi->mbmi.sb_type, h, w, xd->bd);
    else
      build_compound_seg_mask(comp_data->seg_mask, comp_data->mask_type, dst,
                              dst_stride, tmp_dst, MAX_SB_SIZE,
                              mi->mbmi.sb_type, h, w);
  }
#endif  // CONFIG_COMPOUND_SEGMENT
656
  if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
657
658
659
    build_masked_compound_highbd(dst, dst_stride, dst, dst_stride, tmp_dst,
                                 MAX_SB_SIZE, comp_data, mi->mbmi.sb_type, h, w,
                                 xd->bd);
660
  else
661
662
    build_masked_compound(dst, dst_stride, dst, dst_stride, tmp_dst,
                          MAX_SB_SIZE, comp_data, mi->mbmi.sb_type, h, w);
663
#endif  // CONFIG_SUPERTX
Yaowu Xu's avatar
Yaowu Xu committed
664
#else   // CONFIG_AOM_HIGHBITDEPTH
665
  DECLARE_ALIGNED(16, uint8_t, tmp_dst[MAX_SB_SQUARE]);
Yaowu Xu's avatar
Yaowu Xu committed
666
  av1_make_inter_predictor(pre, pre_stride, tmp_dst, MAX_SB_SIZE, subpel_x,
667
668
                           subpel_y, sf, w, h, &conv_params, tmp_ipf, xs, ys,
                           xd);
669
#if CONFIG_SUPERTX
670
671
672
673
  build_masked_compound_wedge_extend(dst, dst_stride, dst, dst_stride, tmp_dst,
                                     MAX_SB_SIZE, comp_data->wedge_index,
                                     comp_data->wedge_sign, mi->mbmi.sb_type,
                                     wedge_offset_x, wedge_offset_y, h, w);
674
#else
675
676
#if CONFIG_COMPOUND_SEGMENT
  if (!plane && comp_data->type == COMPOUND_SEG)
677
678
679
    build_compound_seg_mask(comp_data->seg_mask, comp_data->mask_type, dst,
                            dst_stride, tmp_dst, MAX_SB_SIZE, mi->mbmi.sb_type,
                            h, w);
680
#endif  // CONFIG_COMPOUND_SEGMENT
681
682
  build_masked_compound(dst, dst_stride, dst, dst_stride, tmp_dst, MAX_SB_SIZE,
                        comp_data, mi->mbmi.sb_type, h, w);
683
#endif  // CONFIG_SUPERTX
Yaowu Xu's avatar
Yaowu Xu committed
684
#endif  // CONFIG_AOM_HIGHBITDEPTH
685
686
687
#if CONFIG_COMPOUND_SEGMENT
  (void)plane;
#endif  // CONFIG_COMPOUND_SEGMENT
688
689
}
#endif  // CONFIG_EXT_INTER
690

Yaowu Xu's avatar
Yaowu Xu committed
691
692
#if CONFIG_AOM_HIGHBITDEPTH
void av1_highbd_build_inter_predictor(
clang-format's avatar
clang-format committed
693
694
    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,
695
#if CONFIG_DUAL_FILTER
James Zern's avatar
James Zern committed
696
    const InterpFilter *interp_filter,
697
#else
James Zern's avatar
James Zern committed
698
    const InterpFilter interp_filter,
699
#endif
clang-format's avatar
clang-format committed
700
    enum mv_precision precision, int x, int y, int bd) {
Jingning Han's avatar
Jingning Han committed
701
702
703
  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 };
Yaowu Xu's avatar
Yaowu Xu committed
704
  MV32 mv = av1_scale_mv(&mv_q4, x, y, sf);
Jingning Han's avatar
Jingning Han committed
705
706
707
708
709
  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);

710
  highbd_inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y,
711
712
                         sf, w, h, ref, interp_filter, sf->x_step_q4,
                         sf->y_step_q4, bd);
Jingning Han's avatar
Jingning Han committed
713
}
Yaowu Xu's avatar
Yaowu Xu committed
714
#endif  // CONFIG_AOM_HIGHBITDEPTH
Jingning Han's avatar
Jingning Han committed
715

Yaowu Xu's avatar
Yaowu Xu committed
716
717
718
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,
719
                               ConvolveParams *conv_params,
720
#if CONFIG_DUAL_FILTER
James Zern's avatar
James Zern committed
721
                               const InterpFilter *interp_filter,
722
#else
James Zern's avatar
James Zern committed
723
                               const InterpFilter interp_filter,
724
#endif
Yaowu Xu's avatar
Yaowu Xu committed
725
                               enum mv_precision precision, int x, int y) {
Jingning Han's avatar
Jingning Han committed
726
727
728
  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 };
Yaowu Xu's avatar
Yaowu Xu committed
729
  MV32 mv = av1_scale_mv(&mv_q4, x, y, sf);
Jingning Han's avatar
Jingning Han committed
730
731
732
733
734
  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
735
  inter_predictor(src, src_stride, dst, dst_stride, subpel_x, subpel_y, sf, w,
736
                  h, conv_params, interp_filter, sf->x_step_q4, sf->y_step_q4);
Jingning Han's avatar
Jingning Han committed
737
738
}

Angie Chiang's avatar
Angie Chiang committed
739
740
741
742
743
744
745
typedef struct SubpelParams {
  int xs;
  int ys;
  int subpel_x;
  int subpel_y;
} SubpelParams;

746
void build_inter_predictors(MACROBLOCKD *xd, int plane,
Yue Chen's avatar
Yue Chen committed
747
#if CONFIG_MOTION_VAR
748
                            int mi_col_offset, int mi_row_offset,
Yue Chen's avatar
Yue Chen committed
749
#endif  // CONFIG_MOTION_VAR
clang-format's avatar
clang-format committed
750
751
                            int block, int bw, int bh, int x, int y, int w,
                            int h,
752
753
754
#if CONFIG_SUPERTX && CONFIG_EXT_INTER
                            int wedge_offset_x, int wedge_offset_y,
#endif  // CONFIG_SUPERTX && CONFIG_EXT_INTER
755
                            int mi_x, int mi_y) {
Jingning Han's avatar
Jingning Han committed
756
  struct macroblockd_plane *const pd = &xd->plane[plane];
Yue Chen's avatar
Yue Chen committed
757
#if CONFIG_MOTION_VAR
758
  const MODE_INFO *mi = xd->mi[mi_col_offset + xd->mi_stride * mi_row_offset];
Yue Chen's avatar
Yue Chen committed
759
#if !CONFIG_CB4X4
760
  const int build_for_obmc = !(mi_col_offset == 0 && mi_row_offset == 0);
Yue Chen's avatar
Yue Chen committed
761
#endif
762
#else
Jingning Han's avatar
Jingning Han committed
763
  const MODE_INFO *mi = xd->mi[0];
Yue Chen's avatar
Yue Chen committed
764
#endif  // CONFIG_MOTION_VAR
Jingning Han's avatar
Jingning Han committed
765
766
  const int is_compound = has_second_ref(&mi->mbmi);
  int ref;
767
#if CONFIG_GLOBAL_MOTION
768
  WarpedMotionParams *gm[2];
769
770
771
  int is_global[2];
  for (ref = 0; ref < 1 + is_compound; ++ref) {
    gm[ref] = &xd->global_motion[mi->mbmi.ref_frame[ref]];
clang-format's avatar
clang-format committed
772
    is_global[ref] =
773
        (get_y_mode(mi, block) == ZEROMV && gm[ref]->wmtype > TRANSLATION);
774
775
  }
  // TODO(sarahparker) remove these once gm works with all experiments
clang-format's avatar
clang-format committed
776
777
  (void)gm;
  (void)is_global;
778
#endif  // CONFIG_GLOBAL_MOTION
Jingning Han's avatar
Jingning Han committed
779

780
781
782
783
#if CONFIG_CB4X4
  (void)block;
#endif

784
785
// TODO(sarahparker) enable the use of DUAL_FILTER in warped motion functions
// in order to allow GLOBAL_MOTION and DUAL_FILTER to work together
786
#if CONFIG_SUB8X8_MC
787
788
789
#if CONFIG_MOTION_VAR
  if (mi->mbmi.sb_type < BLOCK_8X8 && plane > 0 && !build_for_obmc) {
#else
790
  if (mi->mbmi.sb_type < BLOCK_8X8 && plane > 0) {
791
#endif  // CONFIG_MOTION_VAR
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
    // 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;
Yaowu Xu's avatar
Yaowu Xu committed
824
          const int is_scaled = av1_is_scaled(sf);
825
          ConvolveParams conv_params = get_conv_params(ref);
826
827
828
829
830
831
832
833
834

          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);
Yaowu Xu's avatar
Yaowu Xu committed
835
            scaled_mv = av1_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf);
836
837
838
839
840
841
842
843
844
845
846
847
848
            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);
849

850
#if CONFIG_EXT_INTER
851
852
          if (ref &&
              is_masked_compound_type(mi->mbmi.interinter_compound_data.type))
Yaowu Xu's avatar
Yaowu Xu committed
853
            av1_make_masked_inter_predictor(
854
855
856
857
858
                pre, pre_buf->stride, dst, dst_buf->stride, subpel_x, subpel_y,
                sf, w, h, mi->mbmi.interp_filter, xs, ys,
#if CONFIG_SUPERTX
                wedge_offset_x, wedge_offset_y,
#endif  // CONFIG_SUPERTX
859
860
861
#if CONFIG_COMPOUND_SEGMENT
                plane,
#endif  // CONFIG_COMPOUND_SEGMENT
862
863
864
                xd);
          else
#endif  // CONFIG_EXT_INTER
Yaowu Xu's avatar
Yaowu Xu committed
865
866
            av1_make_inter_predictor(pre, pre_buf->stride, dst, dst_buf->stride,
                                     subpel_x, subpel_y, sf, x_step, y_step,
867
868
                                     &conv_params, mi->mbmi.interp_filter, xs,
                                     ys, xd);
869
        }
870
871
872
873
874
875
      }
    }
    return;
  }
#endif

Angie Chiang's avatar
Angie Chiang committed
876
  {
Jingning Han's avatar
Jingning Han committed
877
878
    struct buf_2d *const dst_buf = &pd->dst;
    uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
Angie Chiang's avatar
Angie Chiang committed
879
880
881
    uint8_t *pre[2];
    MV32 scaled_mv[2];
    SubpelParams subpel_params[2];
Angie Chiang's avatar
Angie Chiang committed
882
883
884
#if CONVOLVE_POST_ROUNDING
    int32_t tmp_dst[MAX_SB_SIZE * MAX_SB_SIZE];
#endif  // CONVOLVE_POST_ROUNDING
Angie Chiang's avatar
Angie Chiang committed
885
886
887
888

    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];
889
#if CONFIG_CB4X4
Angie Chiang's avatar
Angie Chiang committed
890
      const MV mv = mi->mbmi.mv[ref].as_mv;
891
#else
Angie Chiang's avatar
Angie Chiang committed
892
893
      const MV mv =
          mi->mbmi.sb_type < BLOCK_8X8
894
#if CONFIG_MOTION_VAR
Angie Chiang's avatar
Angie Chiang committed
895
896
              ? (build_for_obmc ? mi->bmi[block].as_mv[ref].as_mv
                                : average_split_mvs(pd, mi, ref, block))
897
#else
Angie Chiang's avatar
Angie Chiang committed
898
              ? average_split_mvs(pd, mi, ref, block)
899
#endif  // CONFIG_MOTION_VAR
Angie Chiang's avatar
Angie Chiang committed
900
              : mi->mbmi.mv[ref].as_mv;
901
#endif
Jingning Han's avatar
Jingning Han committed
902

Angie Chiang's avatar
Angie Chiang committed
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
      // 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.
      const MV mv_q4 = clamp_mv_to_umv_border_sb(
          xd, &mv, bw, bh, pd->subsampling_x, pd->subsampling_y);

      const int is_scaled = av1_is_scaled(sf);

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

Angie Chiang's avatar
Angie Chiang committed
927
928
929
930
931
      subpel_params[ref].subpel_x = scaled_mv[ref].col & SUBPEL_MASK;
      subpel_params[ref].subpel_y = scaled_mv[ref].row & SUBPEL_MASK;
      pre[ref] += (scaled_mv[ref].row >> SUBPEL_BITS) * pre_buf->stride +
                  (scaled_mv[ref].col >> SUBPEL_BITS);
    }
Jingning Han's avatar
Jingning Han committed
932

Angie Chiang's avatar
Angie Chiang committed
933
934
935
    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];
Angie Chiang's avatar
Angie Chiang committed
936
937
938
939
940
941
#if CONVOLVE_POST_ROUNDING
      ConvolveParams conv_params =
          get_conv_params_no_round(ref, tmp_dst, MAX_SB_SIZE);
#else
      ConvolveParams conv_params = get_conv_params(ref);
#endif  // CONVOLVE_POST_ROUNDING
942
#if CONFIG_EXT_INTER
Angie Chiang's avatar
Angie Chiang committed
943
944
945
946
947
948
949
      if (ref &&
          is_masked_compound_type(mi->mbmi.interinter_compound_data.type))
        av1_make_masked_inter_predictor(
            pre[ref], pre_buf->stride, dst, dst_buf->stride,
            subpel_params[ref].subpel_x, subpel_params[ref].subpel_y, sf, w, h,
            mi->mbmi.interp_filter, subpel_params[ref].xs,
            subpel_params[ref].ys,
950
#if CONFIG_SUPERTX
Angie Chiang's avatar
Angie Chiang committed
951
            wedge_offset_x, wedge_offset_y,
952
#endif  // CONFIG_SUPERTX
953
#if CONFIG_COMPOUND_SEGMENT
Angie Chiang's avatar
Angie Chiang committed
954
            plane,
955
#endif  // CONFIG_COMPOUND_SEGMENT
Angie Chiang's avatar
Angie Chiang committed
956
957
            xd);
      else
958
959
#else  // CONFIG_EXT_INTER
#if CONFIG_GLOBAL_MOTION
Angie Chiang's avatar
Angie Chiang committed
960
961
      if (is_global[ref])
        av1_warp_plane(gm[ref],
Yaowu Xu's avatar
Yaowu Xu committed
962
#if CONFIG_AOM_HIGHBITDEPTH
Angie Chiang's avatar
Angie Chiang committed
963
                       xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
Yaowu Xu's avatar
Yaowu Xu committed
964
#endif  // CONFIG_AOM_HIGHBITDEPTH
Angie Chiang's avatar
Angie Chiang committed
965
966
967
968
969
970
                       pre_buf->buf0, pre_buf->width, pre_buf->height,
                       pre_buf->stride, dst, (mi_x >> pd->subsampling_x) + x,
                       (mi_y >> pd->subsampling_y) + y, w, h, dst_buf->stride,
                       pd->subsampling_x, pd->subsampling_y,
                       subpel_params[ref].xs, subpel_params[ref].ys, ref);
      else
971
#endif  // CONFIG_GLOBAL_MOTION
972
#endif  // CONFIG_EXT_INTER
Angie Chiang's avatar
Angie Chiang committed
973
974
975
976
977
978
        av1_make_inter_predictor(
            pre[ref], pre_buf->stride, dst, dst_buf->stride,
            subpel_params[ref].subpel_x, subpel_params[ref].subpel_y, sf, w, h,
            &conv_params, mi->mbmi.interp_filter, subpel_params[ref].xs,
            subpel_params[ref].ys, xd);
    }
Angie Chiang's avatar
Angie Chiang committed
979
980

#if CONVOLVE_POST_ROUNDING
981
982
983
984
985
// TODO(angiebird): This part needs optimization
#if CONFIG_AOM_HIGHBITDEPTH
    if (!(xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH))
      av1_convolve_rounding(tmp_dst, MAX_SB_SIZE, dst, dst_buf->stride, w, h);
#else
Angie Chiang's avatar
Angie Chiang committed
986
    av1_convolve_rounding(tmp_dst, MAX_SB_SIZE, dst, dst_buf->stride, w, h);
987
#endif
Angie Chiang's avatar
Angie Chiang committed
988
#endif  // CONVOLVE_POST_ROUNDING
Jingning Han's avatar
Jingning Han committed
989
990
991
  }
}

Yaowu Xu's avatar
Yaowu Xu committed
992
993
void av1_build_inter_predictor_sub8x8(MACROBLOCKD *xd, int plane, int i, int ir,
                                      int ic, int mi_row, int mi_col) {
994
995
996
  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);
997
998
  const int width = block_size_wide[plane_bsize];
  const int height = block_size_high[plane_bsize];
999
1000
1001
1002
1003
  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) {
1004
    ConvolveParams conv_params = get_conv_params(ref);
1005
1006
    const uint8_t *pre =
        &pd->pre[ref].buf[(ir * pd->pre[ref].stride + ic) << 2];
Yaowu Xu's avatar
Yaowu Xu committed
1007
#if CONFIG_AOM_HIGHBITDEPTH
clang-format's avatar
clang-format committed
1008
    if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH) {
Yaowu Xu's avatar
Yaowu Xu committed
1009
      av1_highbd_build_inter_predictor(
clang-format's avatar
clang-format committed
1010
1011
1012
1013
1014
          pre, pd->pre[ref].stride, dst, pd->dst.stride,
          &mi->bmi[i].as_mv[ref].as_mv, &xd->block_refs[ref]->sf, width, height,
          ref, mi->mbmi.interp_filter, MV_PRECISION_Q3,
          mi_col * MI_SIZE + 4 * ic, mi_row * MI_SIZE + 4 * ir, xd->bd);
    } else {