reconinter.c 114 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
}
#endif  // CONFIG_EXT_INTER
687

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

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

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

Angie Chiang's avatar
Angie Chiang committed
736
737
738
739
740
741
742
typedef struct SubpelParams {
  int xs;
  int ys;
  int subpel_x;
  int subpel_y;
} SubpelParams;

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

777
778
779
780
#if CONFIG_CB4X4
  (void)block;
#endif

781
782
// TODO(sarahparker) enable the use of DUAL_FILTER in warped motion functions
// in order to allow GLOBAL_MOTION and DUAL_FILTER to work together
783
#if CONFIG_SUB8X8_MC
784
785
786
#if CONFIG_MOTION_VAR
  if (mi->mbmi.sb_type < BLOCK_8X8 && plane > 0 && !build_for_obmc) {
#else
787
  if (mi->mbmi.sb_type < BLOCK_8X8 && plane > 0) {
788
#endif  // CONFIG_MOTION_VAR
789
790
791
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
    // 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
821
          const int is_scaled = av1_is_scaled(sf);
822
          ConvolveParams conv_params = get_conv_params(ref);
823
824
825
826
827
828
829
830
831

          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
832
            scaled_mv = av1_scale_mv(&mv_q4, mi_x + x, mi_y + y, sf);
833
834
835
836
837
838
839
840
841
842
843
844
845
            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);
846

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

Angie Chiang's avatar
Angie Chiang committed
873
  {
Jingning Han's avatar
Jingning Han committed
874
875
    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
876
877
878
    uint8_t *pre[2];
    MV32 scaled_mv[2];
    SubpelParams subpel_params[2];
Angie Chiang's avatar
Angie Chiang committed
879
880
881
#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
882
883
884
885

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

Angie Chiang's avatar
Angie Chiang committed
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
      // 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;
      }
923

Angie Chiang's avatar
Angie Chiang committed
924
925
926
927
928
      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
929

Angie Chiang's avatar
Angie Chiang committed
930
931
932
    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
933
934
935
936
937
938
#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
939
#if CONFIG_EXT_INTER
Angie Chiang's avatar
Angie Chiang committed
940
941
942
943
944
945
946
      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,
947
#if CONFIG_SUPERTX
Angie Chiang's avatar
Angie Chiang committed
948
            wedge_offset_x, wedge_offset_y,
949
#endif  // CONFIG_SUPERTX
950
#if CONFIG_COMPOUND_SEGMENT
Angie Chiang's avatar
Angie Chiang committed
951
            plane,
952
#endif  // CONFIG_COMPOUND_SEGMENT
Angie Chiang's avatar
Angie Chiang committed
953
954
            xd);
      else
955
956
#else  // CONFIG_EXT_INTER
#if CONFIG_GLOBAL_MOTION
Angie Chiang's avatar
Angie Chiang committed
957
958
      if (is_global[ref])
        av1_warp_plane(gm[ref],
Yaowu Xu's avatar
Yaowu Xu committed
959
#if CONFIG_AOM_HIGHBITDEPTH
Angie Chiang's avatar
Angie Chiang committed
960
                       xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH, xd->bd,
Yaowu Xu's avatar
Yaowu Xu committed
961
#endif  // CONFIG_AOM_HIGHBITDEPTH
Angie Chiang's avatar
Angie Chiang committed
962
963
964
965
966
967
                       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
968
#endif  // CONFIG_GLOBAL_MOTION
969
#endif  // CONFIG_EXT_INTER
Angie Chiang's avatar
Angie Chiang committed
970
971
972
973
974
975
        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
976
977

#if CONVOLVE_POST_ROUNDING
978
979
980
981
982
// 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
983
    av1_convolve_rounding(tmp_dst, MAX_SB_SIZE, dst, dst_buf->stride, w, h);
984
#endif
Angie Chiang's avatar
Angie Chiang committed
985
#endif  // CONVOLVE_POST_ROUNDING
Jingning Han's avatar
Jingning Han committed
986
987
988
  }
}

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