Coverage Report

Created: 2026-08-31 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/svt-av1/Source/Lib/Codec/inter_prediction.c
Line
Count
Source
1
/*
2
* Copyright(c) 2019 Intel Corporation
3
* Copyright (c) 2016, Alliance for Open Media. All rights reserved
4
*
5
* This source code is subject to the terms of the BSD 3-Clause Clear License and
6
* the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear License
7
* was not distributed with this source code in the LICENSE file, you can
8
* obtain it at https://www.aomedia.org/license. If the Alliance for Open
9
* Media Patent License 1.0 was not distributed with this source code in the
10
* PATENTS file, you can obtain it at https://www.aomedia.org/license/patent-license.
11
*/
12
13
#include <stdlib.h>
14
15
#include "inter_prediction.h"
16
#include "convolve.h"
17
#include "common_dsp_rtcd.h"
18
#include "utility.h"
19
#include "pic_operators.h"
20
21
0
#define SCALE_SUBPEL_BITS 10
22
0
#define SCALE_SUBPEL_SHIFTS (1 << SCALE_SUBPEL_BITS)
23
0
#define SCALE_SUBPEL_MASK (SCALE_SUBPEL_SHIFTS - 1)
24
0
#define SCALE_EXTRA_BITS (SCALE_SUBPEL_BITS - SUBPEL_BITS)
25
26
void svt_aom_pack_block(uint8_t* in8_bit_buffer, uint32_t in8_stride, uint8_t* inn_bit_buffer, uint32_t inn_stride,
27
0
                        uint16_t* out16_bit_buffer, uint32_t out_stride, uint32_t width, uint32_t height) {
28
0
    svt_aom_pack2d_src(
29
0
        in8_bit_buffer, in8_stride, inn_bit_buffer, inn_stride, out16_bit_buffer, out_stride, width, height);
30
0
}
31
32
const int             div_mult[32] = {0,    16384, 8192, 5461, 4096, 3276, 2730, 2340, 2048, 1820, 1638,
33
                                      1489, 1365,  1260, 1170, 1092, 1024, 963,  910,  862,  819,  780,
34
                                      744,  712,   682,  655,  630,  606,  585,  564,  546,  528};
35
static WedgeMasksType wedge_masks[BLOCK_SIZES_ALL][2];
36
37
0
int svt_aom_is_masked_compound_type(COMPOUND_TYPE type) {
38
0
    return (type == COMPOUND_WEDGE || type == COMPOUND_DIFFWTD);
39
0
}
40
41
void svt_aom_highbd_subtract_block_c(int rows, int cols, int16_t* diff, ptrdiff_t diff_stride, const uint8_t* src8,
42
0
                                     ptrdiff_t src_stride, const uint8_t* pred8, ptrdiff_t pred_stride, int bd) {
43
0
    uint16_t* src  = (uint16_t*)(src8);
44
0
    uint16_t* pred = (uint16_t*)(pred8);
45
0
    (void)bd;
46
47
0
    for (int r = 0; r < rows; r++) {
48
0
        for (int c = 0; c < cols; c++) {
49
0
            diff[c] = src[c] - pred[c];
50
0
        }
51
52
0
        diff += diff_stride;
53
0
        pred += pred_stride;
54
0
        src += src_stride;
55
0
    }
56
0
}
57
58
void svt_aom_subtract_block_c(int rows, int cols, int16_t* diff, ptrdiff_t diff_stride, const uint8_t* src,
59
0
                              ptrdiff_t src_stride, const uint8_t* pred, ptrdiff_t pred_stride) {
60
0
    for (int r = 0; r < rows; r++) {
61
0
        for (int c = 0; c < cols; c++) {
62
0
            diff[c] = src[c] - pred[c];
63
0
        }
64
65
0
        diff += diff_stride;
66
0
        pred += pred_stride;
67
0
        src += src_stride;
68
0
    }
69
0
}
70
71
static void diffwtd_mask(uint8_t* mask, int which_inverse, int mask_base, const uint8_t* src0, int src0_stride,
72
0
                         const uint8_t* src1, int src1_stride, int h, int w) {
73
0
    for (int i = 0; i < h; ++i) {
74
0
        for (int j = 0; j < w; ++j) {
75
0
            int diff        = abs((int)src0[i * src0_stride + j] - (int)src1[i * src1_stride + j]);
76
0
            int m           = clamp(mask_base + (diff / DIFF_FACTOR), 0, AOM_BLEND_A64_MAX_ALPHA);
77
0
            mask[i * w + j] = which_inverse ? AOM_BLEND_A64_MAX_ALPHA - m : m;
78
0
        }
79
0
    }
80
0
}
81
82
static AOM_FORCE_INLINE void diffwtd_mask_highbd(uint8_t* mask, int which_inverse, int mask_base, const uint16_t* src0,
83
                                                 int src0_stride, const uint16_t* src1, int src1_stride, int h, int w,
84
0
                                                 const unsigned int bd) {
85
0
    assert(bd >= 8);
86
0
    if (bd == 8) {
87
0
        if (which_inverse) {
88
0
            for (int i = 0; i < h; ++i) {
89
0
                for (int j = 0; j < w; ++j) {
90
0
                    int          diff = abs((int)src0[j] - (int)src1[j]) / DIFF_FACTOR;
91
0
                    unsigned int m    = negative_to_zero(mask_base + diff);
92
0
                    m                 = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
93
0
                    mask[j]           = AOM_BLEND_A64_MAX_ALPHA - m;
94
0
                }
95
0
                src0 += src0_stride;
96
0
                src1 += src1_stride;
97
0
                mask += w;
98
0
            }
99
0
        } else {
100
0
            for (int i = 0; i < h; ++i) {
101
0
                for (int j = 0; j < w; ++j) {
102
0
                    int          diff = abs((int)src0[j] - (int)src1[j]) / DIFF_FACTOR;
103
0
                    unsigned int m    = negative_to_zero(mask_base + diff);
104
0
                    m                 = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
105
0
                    mask[j]           = m;
106
0
                }
107
0
                src0 += src0_stride;
108
0
                src1 += src1_stride;
109
0
                mask += w;
110
0
            }
111
0
        }
112
0
    } else {
113
0
        const unsigned int bd_shift = bd - 8;
114
0
        if (which_inverse) {
115
0
            for (int i = 0; i < h; ++i) {
116
0
                for (int j = 0; j < w; ++j) {
117
0
                    int          diff = (abs((int)src0[j] - (int)src1[j]) >> bd_shift) / DIFF_FACTOR;
118
0
                    unsigned int m    = negative_to_zero(mask_base + diff);
119
0
                    m                 = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
120
0
                    mask[j]           = AOM_BLEND_A64_MAX_ALPHA - m;
121
0
                }
122
0
                src0 += src0_stride;
123
0
                src1 += src1_stride;
124
0
                mask += w;
125
0
            }
126
0
        } else {
127
0
            for (int i = 0; i < h; ++i) {
128
0
                for (int j = 0; j < w; ++j) {
129
0
                    int          diff = (abs((int)src0[j] - (int)src1[j]) >> bd_shift) / DIFF_FACTOR;
130
0
                    unsigned int m    = negative_to_zero(mask_base + diff);
131
0
                    m                 = AOMMIN(m, AOM_BLEND_A64_MAX_ALPHA);
132
0
                    mask[j]           = m;
133
0
                }
134
0
                src0 += src0_stride;
135
0
                src1 += src1_stride;
136
0
                mask += w;
137
0
            }
138
0
        }
139
0
    }
140
0
}
141
142
void svt_av1_build_compound_diffwtd_mask_highbd_c(uint8_t* mask, DIFFWTD_MASK_TYPE mask_type, const uint8_t* src0,
143
                                                  int src0_stride, const uint8_t* src1, int src1_stride, int h, int w,
144
0
                                                  int bd) {
145
0
    switch (mask_type) {
146
0
    case DIFFWTD_38:
147
0
        diffwtd_mask_highbd(mask, 0, 38, (uint16_t*)src0, src0_stride, (uint16_t*)src1, src1_stride, h, w, bd);
148
0
        break;
149
0
    case DIFFWTD_38_INV:
150
0
        diffwtd_mask_highbd(mask, 1, 38, (uint16_t*)src0, src0_stride, (uint16_t*)src1, src1_stride, h, w, bd);
151
0
        break;
152
0
    default:
153
0
        assert(0);
154
0
    }
155
0
}
156
157
void svt_av1_build_compound_diffwtd_mask_c(uint8_t* mask, DIFFWTD_MASK_TYPE mask_type, const uint8_t* src0,
158
0
                                           int src0_stride, const uint8_t* src1, int src1_stride, int h, int w) {
159
0
    switch (mask_type) {
160
0
    case DIFFWTD_38:
161
0
        diffwtd_mask(mask, 0, 38, src0, src0_stride, src1, src1_stride, h, w);
162
0
        break;
163
0
    case DIFFWTD_38_INV:
164
0
        diffwtd_mask(mask, 1, 38, src0, src0_stride, src1, src1_stride, h, w);
165
0
        break;
166
0
    default:
167
0
        assert(0);
168
0
    }
169
0
}
170
171
// Note: Expect val to be in q4 precision
172
0
static INLINE int32_t scaled_x(int32_t val, const ScaleFactors* sf) {
173
0
    const int     off  = (sf->x_scale_fp - (1 << REF_SCALE_SHIFT)) * (1 << (SUBPEL_BITS - 1));
174
0
    const int64_t tval = (int64_t)val * sf->x_scale_fp + off;
175
0
    return (int)ROUND_POWER_OF_TWO_SIGNED_64(tval, REF_SCALE_SHIFT - SCALE_EXTRA_BITS);
176
0
}
177
178
// Note: Expect val to be in q4 precision
179
0
static INLINE int32_t scaled_y(int32_t val, const ScaleFactors* sf) {
180
0
    const int32_t off  = (sf->y_scale_fp - (1 << REF_SCALE_SHIFT)) * (1 << (SUBPEL_BITS - 1));
181
0
    const int64_t tval = (int64_t)val * sf->y_scale_fp + off;
182
0
    return (int32_t)ROUND_POWER_OF_TWO_SIGNED_64(tval, REF_SCALE_SHIFT - SCALE_EXTRA_BITS);
183
0
}
184
185
// Note: Expect val to be in q4 precision
186
0
static int32_t unscaled_value(int32_t val, const ScaleFactors* sf) {
187
0
    (void)sf;
188
0
    return val << SCALE_EXTRA_BITS;
189
0
}
190
191
962
static int32_t get_fixed_point_scale_factor(int32_t other_size, int32_t this_size) {
192
    // Calculate scaling factor once for each reference frame
193
    // and use fixed point scaling factors in decoding and encoding routines.
194
    // Hardware implementations can calculate scale factor in device driver
195
    // and use multiplication and shifting on hardware instead of division.
196
962
    return ((other_size << REF_SCALE_SHIFT) + this_size / 2) / this_size;
197
962
}
198
199
// Given the fixed point scale, calculate coarse point scale.
200
962
static int32_t fixed_point_scale_to_coarse_point_scale(int32_t scale_fp) {
201
962
    return ROUND_POWER_OF_TWO(scale_fp, REF_SCALE_SHIFT - SCALE_SUBPEL_BITS);
202
962
}
203
204
481
void svt_av1_setup_scale_factors_for_frame(ScaleFactors* sf, int other_w, int other_h, int this_w, int this_h) {
205
481
    if (!valid_ref_frame_size(other_w, other_h, this_w, this_h)) {
206
0
        sf->x_scale_fp = REF_INVALID_SCALE;
207
0
        sf->y_scale_fp = REF_INVALID_SCALE;
208
0
        sf->is_scaled  = 0;
209
0
        return;
210
0
    }
211
212
481
    sf->x_scale_fp = get_fixed_point_scale_factor(other_w, this_w);
213
481
    sf->y_scale_fp = get_fixed_point_scale_factor(other_h, this_h);
214
215
481
    sf->x_step_q4 = fixed_point_scale_to_coarse_point_scale(sf->x_scale_fp);
216
481
    sf->y_step_q4 = fixed_point_scale_to_coarse_point_scale(sf->y_scale_fp);
217
218
481
    sf->is_scaled = av1_is_scaled(sf);
219
481
    if (sf->is_scaled) {
220
0
        sf->scale_value_x = scaled_x;
221
0
        sf->scale_value_y = scaled_y;
222
481
    } else {
223
481
        sf->scale_value_x = unscaled_value;
224
481
        sf->scale_value_y = unscaled_value;
225
481
    }
226
481
}
227
228
0
static INLINE int32_t has_scale(int32_t xs, int32_t ys) {
229
0
    return xs != SCALE_SUBPEL_SHIFTS || ys != SCALE_SUBPEL_SHIFTS;
230
0
}
231
232
0
static INLINE void revert_scale_extra_bits(SubpelParams* sp) {
233
0
    sp->subpel_x >>= SCALE_EXTRA_BITS;
234
0
    sp->subpel_y >>= SCALE_EXTRA_BITS;
235
0
    sp->xs >>= SCALE_EXTRA_BITS;
236
0
    sp->ys >>= SCALE_EXTRA_BITS;
237
0
    assert(sp->subpel_x < SUBPEL_SHIFTS);
238
0
    assert(sp->subpel_y < SUBPEL_SHIFTS);
239
0
    assert(sp->xs <= SUBPEL_SHIFTS);
240
0
    assert(sp->ys <= SUBPEL_SHIFTS);
241
0
}
242
243
DECLARE_ALIGNED(256, const InterpKernel, sub_pel_filters_8[SUBPEL_SHIFTS]) = {{0, 0, 0, 128, 0, 0, 0, 0},
244
                                                                              {0, 2, -6, 126, 8, -2, 0, 0},
245
                                                                              {0, 2, -10, 122, 18, -4, 0, 0},
246
                                                                              {0, 2, -12, 116, 28, -8, 2, 0},
247
                                                                              {0, 2, -14, 110, 38, -10, 2, 0},
248
                                                                              {0, 2, -14, 102, 48, -12, 2, 0},
249
                                                                              {0, 2, -16, 94, 58, -12, 2, 0},
250
                                                                              {0, 2, -14, 84, 66, -12, 2, 0},
251
                                                                              {0, 2, -14, 76, 76, -14, 2, 0},
252
                                                                              {0, 2, -12, 66, 84, -14, 2, 0},
253
                                                                              {0, 2, -12, 58, 94, -16, 2, 0},
254
                                                                              {0, 2, -12, 48, 102, -14, 2, 0},
255
                                                                              {0, 2, -10, 38, 110, -14, 2, 0},
256
                                                                              {0, 2, -8, 28, 116, -12, 2, 0},
257
                                                                              {0, 0, -4, 18, 122, -10, 2, 0},
258
                                                                              {0, 0, -2, 8, 126, -6, 2, 0}};
259
DECLARE_ALIGNED(256, const InterpKernel, sub_pel_filters_4[SUBPEL_SHIFTS]) = {{0, 0, 0, 128, 0, 0, 0, 0},
260
                                                                              {0, 0, -4, 126, 8, -2, 0, 0},
261
                                                                              {0, 0, -8, 122, 18, -4, 0, 0},
262
                                                                              {0, 0, -10, 116, 28, -6, 0, 0},
263
                                                                              {0, 0, -12, 110, 38, -8, 0, 0},
264
                                                                              {0, 0, -12, 102, 48, -10, 0, 0},
265
                                                                              {0, 0, -14, 94, 58, -10, 0, 0},
266
                                                                              {0, 0, -12, 84, 66, -10, 0, 0},
267
                                                                              {0, 0, -12, 76, 76, -12, 0, 0},
268
                                                                              {0, 0, -10, 66, 84, -12, 0, 0},
269
                                                                              {0, 0, -10, 58, 94, -14, 0, 0},
270
                                                                              {0, 0, -10, 48, 102, -12, 0, 0},
271
                                                                              {0, 0, -8, 38, 110, -12, 0, 0},
272
                                                                              {0, 0, -6, 28, 116, -10, 0, 0},
273
                                                                              {0, 0, -4, 18, 122, -8, 0, 0},
274
                                                                              {0, 0, -2, 8, 126, -4, 0, 0}};
275
276
#define MAX_FILTER_TAP 8
277
278
0
int svt_aom_get_relative_dist_enc(SeqHeader* seq_header, int ref_hint, int order_hint) {
279
0
    int diff, m;
280
0
    if (!seq_header->order_hint_info.enable_order_hint) {
281
0
        return 0;
282
0
    }
283
0
    diff = ref_hint - order_hint;
284
0
    m    = 1 << (seq_header->order_hint_info.order_hint_bits - 1);
285
0
    diff = (diff & (m - 1)) - (diff & m);
286
0
    return diff;
287
0
}
288
289
static const int quant_dist_weight[4][2]          = {{2, 3}, {2, 5}, {2, 7}, {1, MAX_FRAME_DISTANCE}};
290
static const int quant_dist_lookup_table[2][4][2] = {
291
    {{9, 7}, {11, 5}, {12, 4}, {13, 3}},
292
    {{7, 9}, {5, 11}, {4, 12}, {3, 13}},
293
};
294
295
void svt_av1_dist_wtd_comp_weight_assign(SeqHeader* seq_header, int cur_frame_index, int bck_frame_index,
296
                                         int fwd_frame_index, int compound_idx, int order_idx, int* fwd_offset,
297
0
                                         int* bck_offset, int* use_dist_wtd_comp_avg, int is_compound) {
298
0
    assert(fwd_offset != NULL && bck_offset != NULL);
299
0
    if (!is_compound || compound_idx) {
300
0
        *use_dist_wtd_comp_avg = 0;
301
0
        return;
302
0
    }
303
304
0
    *use_dist_wtd_comp_avg = 1;
305
306
0
    int d0 = clamp(
307
0
        abs(svt_aom_get_relative_dist_enc(seq_header, fwd_frame_index, cur_frame_index)), 0, MAX_FRAME_DISTANCE);
308
0
    int d1 = clamp(
309
0
        abs(svt_aom_get_relative_dist_enc(seq_header, cur_frame_index, bck_frame_index)), 0, MAX_FRAME_DISTANCE);
310
311
0
    const int order = d0 <= d1;
312
313
0
    if (d0 == 0 || d1 == 0) {
314
0
        *fwd_offset = quant_dist_lookup_table[order_idx][3][order];
315
0
        *bck_offset = quant_dist_lookup_table[order_idx][3][1 - order];
316
0
        return;
317
0
    }
318
319
0
    int i;
320
0
    for (i = 0; i < 3; ++i) {
321
0
        int c0    = quant_dist_weight[i][order];
322
0
        int c1    = quant_dist_weight[i][!order];
323
0
        int d0_c0 = d0 * c0;
324
0
        int d1_c1 = d1 * c1;
325
0
        if ((d0 > d1 && d0_c0 < d1_c1) || (d0 <= d1 && d0_c0 > d1_c1)) {
326
0
            break;
327
0
        }
328
0
    }
329
330
0
    *fwd_offset = quant_dist_lookup_table[order_idx][i][order];
331
0
    *bck_offset = quant_dist_lookup_table[order_idx][i][1 - order];
332
0
}
333
334
void svt_av1_convolve_2d_sr_c(const uint8_t* src, int32_t src_stride, uint8_t* dst, int32_t dst_stride, int32_t w,
335
                              int32_t h, const InterpFilterParams* filter_params_x,
336
                              const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
337
0
                              const int32_t subpel_y_q4, ConvolveParams* conv_params) {
338
0
    int16_t       im_block[(MAX_SB_SIZE + MAX_FILTER_TAP - 1) * MAX_SB_SIZE];
339
0
    int32_t       im_h      = h + filter_params_y->taps - 1;
340
0
    int32_t       im_stride = w;
341
0
    const int32_t fo_vert   = filter_params_y->taps / 2 - 1;
342
0
    const int32_t fo_horiz  = filter_params_x->taps / 2 - 1;
343
0
    const int32_t bd        = 8;
344
0
    const int32_t bits      = FILTER_BITS * 2 - conv_params->round_0 - conv_params->round_1;
345
346
    // horizontal filter
347
0
    const uint8_t* src_horiz = src - fo_vert * src_stride;
348
0
    const int16_t* x_filter  = av1_get_interp_filter_subpel_kernel(*filter_params_x, subpel_x_q4 & SUBPEL_MASK);
349
0
    for (int32_t y = 0; y < im_h; ++y) {
350
0
        for (int32_t x = 0; x < w; ++x) {
351
0
            int32_t sum = (1 << (bd + FILTER_BITS - 1));
352
0
            for (int32_t k = 0; k < filter_params_x->taps; ++k) {
353
0
                sum += x_filter[k] * src_horiz[y * src_stride + x - fo_horiz + k];
354
0
            }
355
0
            assert(0 <= sum && sum < (1 << (bd + FILTER_BITS + 1)));
356
0
            im_block[y * im_stride + x] = (int16_t)ROUND_POWER_OF_TWO(sum, conv_params->round_0);
357
0
        }
358
0
    }
359
360
    // vertical filter
361
0
    int16_t*       src_vert    = im_block + fo_vert * im_stride;
362
0
    const int16_t* y_filter    = av1_get_interp_filter_subpel_kernel(*filter_params_y, subpel_y_q4 & SUBPEL_MASK);
363
0
    const int32_t  offset_bits = bd + 2 * FILTER_BITS - conv_params->round_0;
364
0
    for (int32_t y = 0; y < h; ++y) {
365
0
        for (int32_t x = 0; x < w; ++x) {
366
0
            int32_t sum = 1 << offset_bits;
367
0
            for (int32_t k = 0; k < filter_params_y->taps; ++k) {
368
0
                sum += y_filter[k] * src_vert[(y - fo_vert + k) * im_stride + x];
369
0
            }
370
0
            assert(0 <= sum && sum < (1 << (offset_bits + 2)));
371
0
            int16_t res             = (ConvBufType)(ROUND_POWER_OF_TWO(sum, conv_params->round_1) -
372
0
                                        ((1 << (offset_bits - conv_params->round_1)) +
373
0
                                         (1 << (offset_bits - conv_params->round_1 - 1))));
374
0
            dst[y * dst_stride + x] = (uint8_t)clip_pixel_highbd(ROUND_POWER_OF_TWO(res, bits), 8);
375
0
        }
376
0
    }
377
0
}
378
379
void svt_av1_convolve_y_sr_c(const uint8_t* src, int32_t src_stride, uint8_t* dst, int32_t dst_stride, int32_t w,
380
                             int32_t h, const InterpFilterParams* filter_params_x,
381
                             const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
382
0
                             const int32_t subpel_y_q4, ConvolveParams* conv_params) {
383
0
    assert(filter_params_y != NULL);
384
0
    const int32_t fo_vert = filter_params_y->taps / 2 - 1;
385
0
    (void)filter_params_x;
386
0
    (void)subpel_x_q4;
387
0
    (void)conv_params;
388
389
0
    assert(conv_params->round_0 <= FILTER_BITS);
390
0
    assert(((conv_params->round_0 + conv_params->round_1) <= (FILTER_BITS + 1)) ||
391
0
           ((conv_params->round_0 + conv_params->round_1) == (2 * FILTER_BITS)));
392
393
    // vertical filter
394
0
    const int16_t* y_filter = av1_get_interp_filter_subpel_kernel(*filter_params_y, subpel_y_q4 & SUBPEL_MASK);
395
396
0
    for (int32_t y = 0; y < h; ++y) {
397
0
        for (int32_t x = 0; x < w; ++x) {
398
0
            int32_t res = 0;
399
0
            for (int32_t k = 0; k < filter_params_y->taps; ++k) {
400
0
                res += y_filter[k] * src[(y - fo_vert + k) * src_stride + x];
401
0
            }
402
0
            dst[y * dst_stride + x] = (uint8_t)clip_pixel_highbd(ROUND_POWER_OF_TWO(res, FILTER_BITS), 8);
403
0
        }
404
0
    }
405
0
}
406
407
void svt_av1_convolve_x_sr_c(const uint8_t* src, int32_t src_stride, uint8_t* dst, int32_t dst_stride, int32_t w,
408
                             int32_t h, const InterpFilterParams* filter_params_x,
409
                             const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
410
0
                             const int32_t subpel_y_q4, ConvolveParams* conv_params) {
411
0
    const int32_t fo_horiz = filter_params_x->taps / 2 - 1;
412
0
    const int32_t bits     = FILTER_BITS - conv_params->round_0;
413
0
    (void)filter_params_y;
414
0
    (void)subpel_y_q4;
415
0
    (void)conv_params;
416
417
0
    assert(bits >= 0);
418
0
    assert((FILTER_BITS - conv_params->round_1) >= 0 ||
419
0
           ((conv_params->round_0 + conv_params->round_1) == 2 * FILTER_BITS));
420
421
    // horizontal filter
422
0
    const int16_t* x_filter = av1_get_interp_filter_subpel_kernel(*filter_params_x, subpel_x_q4 & SUBPEL_MASK);
423
424
0
    for (int32_t y = 0; y < h; ++y) {
425
0
        for (int32_t x = 0; x < w; ++x) {
426
0
            int32_t res = 0;
427
0
            for (int32_t k = 0; k < filter_params_x->taps; ++k) {
428
0
                res += x_filter[k] * src[y * src_stride + x - fo_horiz + k];
429
0
            }
430
0
            res                     = ROUND_POWER_OF_TWO(res, conv_params->round_0);
431
0
            dst[y * dst_stride + x] = (uint8_t)clip_pixel_highbd(ROUND_POWER_OF_TWO(res, bits), 8);
432
0
        }
433
0
    }
434
0
}
435
436
void svt_av1_convolve_2d_copy_sr_c(const uint8_t* src, int32_t src_stride, uint8_t* dst, int32_t dst_stride, int32_t w,
437
                                   int32_t h, const InterpFilterParams* filter_params_x,
438
                                   const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
439
0
                                   const int32_t subpel_y_q4, ConvolveParams* conv_params) {
440
0
    (void)filter_params_x;
441
0
    (void)filter_params_y;
442
0
    (void)subpel_x_q4;
443
0
    (void)subpel_y_q4;
444
0
    (void)conv_params;
445
446
0
    for (int32_t y = 0; y < h; ++y) {
447
0
        for (int32_t x = 0; x < w; ++x) {
448
0
            dst[y * dst_stride + x] = src[y * src_stride + x];
449
0
        }
450
0
    }
451
0
}
452
453
void svt_av1_convolve_2d_scale_c(const uint8_t* src, int src_stride, uint8_t* dst8, int dst8_stride, int w, int h,
454
                                 const InterpFilterParams* filter_params_x, const InterpFilterParams* filter_params_y,
455
                                 const int subpel_x_qn, const int x_step_qn, const int subpel_y_qn, const int y_step_qn,
456
0
                                 ConvolveParams* conv_params) {
457
0
    int16_t        im_block[(2 * MAX_SB_SIZE + MAX_FILTER_TAP) * MAX_SB_SIZE];
458
0
    int            im_h         = (((h - 1) * y_step_qn + subpel_y_qn) >> SCALE_SUBPEL_BITS) + filter_params_y->taps;
459
0
    CONV_BUF_TYPE* dst16        = conv_params->dst;
460
0
    const int      dst16_stride = conv_params->dst_stride;
461
0
    const int      bits         = FILTER_BITS * 2 - conv_params->round_0 - conv_params->round_1;
462
0
    assert(bits >= 0);
463
0
    int       im_stride = w;
464
0
    const int fo_vert   = filter_params_y->taps / 2 - 1;
465
0
    const int fo_horiz  = filter_params_x->taps / 2 - 1;
466
0
    const int bd        = 8;
467
468
    // horizontal filter
469
0
    const uint8_t* src_horiz = src - fo_vert * src_stride;
470
0
    for (int y = 0; y < im_h; ++y) {
471
0
        int x_qn = subpel_x_qn;
472
0
        for (int x = 0; x < w; ++x, x_qn += x_step_qn) {
473
0
            const uint8_t* const src_x        = &src_horiz[(x_qn >> SCALE_SUBPEL_BITS)];
474
0
            const int            x_filter_idx = (x_qn & SCALE_SUBPEL_MASK) >> SCALE_EXTRA_BITS;
475
0
            assert(x_filter_idx < SUBPEL_SHIFTS);
476
0
            const int16_t* x_filter = av1_get_interp_filter_subpel_kernel(*filter_params_x, x_filter_idx);
477
0
            int32_t        sum      = (1 << (bd + FILTER_BITS - 1));
478
0
            for (int k = 0; k < filter_params_x->taps; ++k) {
479
0
                sum += x_filter[k] * src_x[k - fo_horiz];
480
0
            }
481
0
            assert(0 <= sum && sum < (1 << (bd + FILTER_BITS + 1)));
482
0
            im_block[y * im_stride + x] = (int16_t)ROUND_POWER_OF_TWO(sum, conv_params->round_0);
483
0
        }
484
0
        src_horiz += src_stride;
485
0
    }
486
487
    // vertical filter
488
0
    int16_t*  src_vert    = im_block + fo_vert * im_stride;
489
0
    const int offset_bits = bd + 2 * FILTER_BITS - conv_params->round_0;
490
0
    for (int x = 0; x < w; ++x) {
491
0
        int y_qn = subpel_y_qn;
492
0
        for (int y = 0; y < h; ++y, y_qn += y_step_qn) {
493
0
            const int16_t* src_y        = &src_vert[(y_qn >> SCALE_SUBPEL_BITS) * im_stride];
494
0
            const int      y_filter_idx = (y_qn & SCALE_SUBPEL_MASK) >> SCALE_EXTRA_BITS;
495
0
            assert(y_filter_idx < SUBPEL_SHIFTS);
496
0
            const int16_t* y_filter = av1_get_interp_filter_subpel_kernel(*filter_params_y, y_filter_idx);
497
0
            int32_t        sum      = 1 << offset_bits;
498
0
            for (int k = 0; k < filter_params_y->taps; ++k) {
499
0
                sum += y_filter[k] * src_y[(k - fo_vert) * im_stride];
500
0
            }
501
0
            assert(0 <= sum && sum < (1 << (offset_bits + 2)));
502
0
            CONV_BUF_TYPE res = ROUND_POWER_OF_TWO(sum, conv_params->round_1);
503
0
            if (conv_params->is_compound) {
504
0
                if (conv_params->do_average) {
505
0
                    int32_t tmp = dst16[y * dst16_stride + x];
506
0
                    if (conv_params->use_dist_wtd_comp_avg) {
507
0
                        tmp = tmp * conv_params->fwd_offset + res * conv_params->bck_offset;
508
0
                        tmp = tmp >> DIST_PRECISION_BITS;
509
0
                    } else {
510
0
                        tmp += res;
511
0
                        tmp = tmp >> 1;
512
0
                    }
513
                    /* Subtract round offset and convolve round */
514
0
                    tmp = tmp -
515
0
                        ((1 << (offset_bits - conv_params->round_1)) + (1 << (offset_bits - conv_params->round_1 - 1)));
516
0
                    dst8[y * dst8_stride + x] = clip_pixel(ROUND_POWER_OF_TWO(tmp, bits));
517
0
                } else {
518
0
                    dst16[y * dst16_stride + x] = res;
519
0
                }
520
0
            } else {
521
                /* Subtract round offset and convolve round */
522
0
                int32_t tmp = res -
523
0
                    ((1 << (offset_bits - conv_params->round_1)) + (1 << (offset_bits - conv_params->round_1 - 1)));
524
0
                dst8[y * dst8_stride + x] = clip_pixel(ROUND_POWER_OF_TWO(tmp, bits));
525
0
            }
526
0
        }
527
0
        src_vert++;
528
0
    }
529
0
}
530
531
void svt_av1_jnt_convolve_2d_c(const uint8_t* src, int32_t src_stride, uint8_t* dst8, int32_t dst8_stride, int32_t w,
532
                               int32_t h, const InterpFilterParams* filter_params_x,
533
                               const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
534
0
                               const int32_t subpel_y_q4, ConvolveParams* conv_params) {
535
0
    ConvBufType*  dst        = conv_params->dst;
536
0
    int32_t       dst_stride = conv_params->dst_stride;
537
0
    int16_t       im_block[(MAX_SB_SIZE + MAX_FILTER_TAP - 1) * MAX_SB_SIZE];
538
0
    int32_t       im_h       = h + filter_params_y->taps - 1;
539
0
    int32_t       im_stride  = w;
540
0
    const int32_t fo_vert    = filter_params_y->taps / 2 - 1;
541
0
    const int32_t fo_horiz   = filter_params_x->taps / 2 - 1;
542
0
    const int32_t bd         = 8;
543
0
    const int32_t round_bits = 2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1;
544
545
    // horizontal filter
546
0
    const uint8_t* src_horiz = src - fo_vert * src_stride;
547
0
    const int16_t* x_filter  = av1_get_interp_filter_subpel_kernel(*filter_params_x, subpel_x_q4 & SUBPEL_MASK);
548
0
    for (int32_t y = 0; y < im_h; ++y) {
549
0
        for (int32_t x = 0; x < w; ++x) {
550
0
            int32_t sum = (1 << (bd + FILTER_BITS - 1));
551
0
            for (int32_t k = 0; k < filter_params_x->taps; ++k) {
552
0
                sum += x_filter[k] * src_horiz[y * src_stride + x - fo_horiz + k];
553
0
            }
554
0
            assert(0 <= sum && sum < (1 << (bd + FILTER_BITS + 1)));
555
0
            im_block[y * im_stride + x] = (int16_t)ROUND_POWER_OF_TWO(sum, conv_params->round_0);
556
0
        }
557
0
    }
558
559
    // vertical filter
560
0
    int16_t*       src_vert    = im_block + fo_vert * im_stride;
561
0
    const int16_t* y_filter    = av1_get_interp_filter_subpel_kernel(*filter_params_y, subpel_y_q4 & SUBPEL_MASK);
562
0
    const int32_t  offset_bits = bd + 2 * FILTER_BITS - conv_params->round_0;
563
0
    for (int32_t y = 0; y < h; ++y) {
564
0
        for (int32_t x = 0; x < w; ++x) {
565
0
            int32_t sum = 1 << offset_bits;
566
0
            for (int32_t k = 0; k < filter_params_y->taps; ++k) {
567
0
                sum += y_filter[k] * src_vert[(y - fo_vert + k) * im_stride + x];
568
0
            }
569
0
            assert(0 <= sum && sum < (1 << (offset_bits + 2)));
570
0
            ConvBufType res = (ConvBufType)ROUND_POWER_OF_TWO(sum, conv_params->round_1);
571
0
            if (conv_params->do_average) {
572
0
                int32_t tmp = dst[y * dst_stride + x];
573
0
                if (conv_params->use_jnt_comp_avg) {
574
0
                    tmp = tmp * conv_params->fwd_offset + res * conv_params->bck_offset;
575
0
                    tmp = tmp >> DIST_PRECISION_BITS;
576
0
                } else {
577
0
                    tmp += res;
578
0
                    tmp = tmp >> 1;
579
0
                }
580
0
                tmp -= (1 << (offset_bits - conv_params->round_1)) + (1 << (offset_bits - conv_params->round_1 - 1));
581
0
                dst8[y * dst8_stride + x] = (uint8_t)clip_pixel_highbd(ROUND_POWER_OF_TWO(tmp, round_bits), 8);
582
0
            } else {
583
0
                dst[y * dst_stride + x] = res;
584
0
            }
585
0
        }
586
0
    }
587
0
}
588
589
void svt_av1_jnt_convolve_y_c(const uint8_t* src, int32_t src_stride, uint8_t* dst8, int32_t dst8_stride, int32_t w,
590
                              int32_t h, const InterpFilterParams* filter_params_x,
591
                              const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
592
0
                              const int32_t subpel_y_q4, ConvolveParams* conv_params) {
593
0
    ConvBufType*  dst          = conv_params->dst;
594
0
    int32_t       dst_stride   = conv_params->dst_stride;
595
0
    const int32_t fo_vert      = filter_params_y->taps / 2 - 1;
596
0
    const int32_t bits         = FILTER_BITS - conv_params->round_0;
597
0
    const int32_t bd           = 8;
598
0
    const int32_t offset_bits  = bd + 2 * FILTER_BITS - conv_params->round_0;
599
0
    const int32_t round_offset = (1 << (offset_bits - conv_params->round_1)) +
600
0
        (1 << (offset_bits - conv_params->round_1 - 1));
601
0
    const int32_t round_bits = 2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1;
602
0
    (void)filter_params_x;
603
0
    (void)subpel_x_q4;
604
605
    // vertical filter
606
0
    const int16_t* y_filter = av1_get_interp_filter_subpel_kernel(*filter_params_y, subpel_y_q4 & SUBPEL_MASK);
607
0
    for (int32_t y = 0; y < h; ++y) {
608
0
        for (int32_t x = 0; x < w; ++x) {
609
0
            int32_t res = 0;
610
0
            for (int32_t k = 0; k < filter_params_y->taps; ++k) {
611
0
                res += y_filter[k] * src[(y - fo_vert + k) * src_stride + x];
612
0
            }
613
0
            res *= (1 << bits);
614
0
            res = ROUND_POWER_OF_TWO(res, conv_params->round_1) + round_offset;
615
616
0
            if (conv_params->do_average) {
617
0
                int32_t tmp = dst[y * dst_stride + x];
618
0
                if (conv_params->use_jnt_comp_avg) {
619
0
                    tmp = tmp * conv_params->fwd_offset + res * conv_params->bck_offset;
620
0
                    tmp = tmp >> DIST_PRECISION_BITS;
621
0
                } else {
622
0
                    tmp += res;
623
0
                    tmp = tmp >> 1;
624
0
                }
625
0
                tmp -= round_offset;
626
0
                dst8[y * dst8_stride + x] = (uint8_t)clip_pixel_highbd(ROUND_POWER_OF_TWO(tmp, round_bits), 8);
627
0
            } else {
628
0
                dst[y * dst_stride + x] = (ConvBufType)res;
629
0
            }
630
0
        }
631
0
    }
632
0
}
633
634
void svt_av1_jnt_convolve_x_c(const uint8_t* src, int32_t src_stride, uint8_t* dst8, int32_t dst8_stride, int32_t w,
635
                              int32_t h, const InterpFilterParams* filter_params_x,
636
                              const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
637
0
                              const int32_t subpel_y_q4, ConvolveParams* conv_params) {
638
0
    ConvBufType*  dst          = conv_params->dst;
639
0
    int32_t       dst_stride   = conv_params->dst_stride;
640
0
    const int32_t fo_horiz     = filter_params_x->taps / 2 - 1;
641
0
    const int32_t bits         = FILTER_BITS - conv_params->round_1;
642
0
    const int32_t bd           = 8;
643
0
    const int32_t offset_bits  = bd + 2 * FILTER_BITS - conv_params->round_0;
644
0
    const int32_t round_offset = (1 << (offset_bits - conv_params->round_1)) +
645
0
        (1 << (offset_bits - conv_params->round_1 - 1));
646
0
    const int32_t round_bits = 2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1;
647
0
    (void)filter_params_y;
648
0
    (void)subpel_y_q4;
649
650
    // horizontal filter
651
0
    const int16_t* x_filter = av1_get_interp_filter_subpel_kernel(*filter_params_x, subpel_x_q4 & SUBPEL_MASK);
652
0
    for (int32_t y = 0; y < h; ++y) {
653
0
        for (int32_t x = 0; x < w; ++x) {
654
0
            int32_t res = 0;
655
0
            for (int32_t k = 0; k < filter_params_x->taps; ++k) {
656
0
                res += x_filter[k] * src[y * src_stride + x - fo_horiz + k];
657
0
            }
658
0
            res = (1 << bits) * ROUND_POWER_OF_TWO(res, conv_params->round_0);
659
0
            res += round_offset;
660
661
0
            if (conv_params->do_average) {
662
0
                int32_t tmp = dst[y * dst_stride + x];
663
0
                if (conv_params->use_jnt_comp_avg) {
664
0
                    tmp = tmp * conv_params->fwd_offset + res * conv_params->bck_offset;
665
0
                    tmp = tmp >> DIST_PRECISION_BITS;
666
0
                } else {
667
0
                    tmp += res;
668
0
                    tmp = tmp >> 1;
669
0
                }
670
0
                tmp -= round_offset;
671
0
                dst8[y * dst8_stride + x] = (uint8_t)clip_pixel_highbd(ROUND_POWER_OF_TWO(tmp, round_bits), 8);
672
0
            } else {
673
0
                dst[y * dst_stride + x] = (ConvBufType)res;
674
0
            }
675
0
        }
676
0
    }
677
0
}
678
679
void svt_av1_jnt_convolve_2d_copy_c(const uint8_t* src, int32_t src_stride, uint8_t* dst8, int32_t dst8_stride,
680
                                    int32_t w, int32_t h, const InterpFilterParams* filter_params_x,
681
                                    const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
682
0
                                    const int32_t subpel_y_q4, ConvolveParams* conv_params) {
683
0
    ConvBufType*  dst          = conv_params->dst;
684
0
    int32_t       dst_stride   = conv_params->dst_stride;
685
0
    const int32_t bits         = FILTER_BITS * 2 - conv_params->round_1 - conv_params->round_0;
686
0
    const int32_t bd           = 8;
687
0
    const int32_t offset_bits  = bd + 2 * FILTER_BITS - conv_params->round_0;
688
0
    const int32_t round_offset = (1 << (offset_bits - conv_params->round_1)) +
689
0
        (1 << (offset_bits - conv_params->round_1 - 1));
690
0
    (void)filter_params_x;
691
0
    (void)filter_params_y;
692
0
    (void)subpel_x_q4;
693
0
    (void)subpel_y_q4;
694
695
0
    for (int32_t y = 0; y < h; ++y) {
696
0
        for (int32_t x = 0; x < w; ++x) {
697
0
            ConvBufType res = src[y * src_stride + x] << bits;
698
0
            res += (ConvBufType)round_offset;
699
700
0
            if (conv_params->do_average) {
701
0
                int32_t tmp = dst[y * dst_stride + x];
702
0
                if (conv_params->use_jnt_comp_avg) {
703
0
                    tmp = tmp * conv_params->fwd_offset + res * conv_params->bck_offset;
704
0
                    tmp = tmp >> DIST_PRECISION_BITS;
705
0
                } else {
706
0
                    tmp += res;
707
0
                    tmp = tmp >> 1;
708
0
                }
709
0
                tmp -= round_offset;
710
0
                dst8[y * dst8_stride + x] = (uint8_t)clip_pixel_highbd(ROUND_POWER_OF_TWO(tmp, bits), 8);
711
0
            } else {
712
0
                dst[y * dst_stride + x] = res;
713
0
            }
714
0
        }
715
0
    }
716
0
}
717
718
void svt_av1_highbd_convolve_2d_copy_sr_c(const uint16_t* src, int32_t src_stride, uint16_t* dst, int32_t dst_stride,
719
                                          int32_t w, int32_t h, const InterpFilterParams* filter_params_x,
720
                                          const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
721
0
                                          const int32_t subpel_y_q4, ConvolveParams* conv_params, int32_t bd) {
722
0
    (void)filter_params_x;
723
0
    (void)filter_params_y;
724
0
    (void)subpel_x_q4;
725
0
    (void)subpel_y_q4;
726
0
    (void)conv_params;
727
0
    (void)bd;
728
729
0
    for (int32_t y = 0; y < h; ++y) {
730
0
        for (int32_t x = 0; x < w; ++x) {
731
0
            dst[y * dst_stride + x] = src[y * src_stride + x];
732
0
        }
733
0
    }
734
0
}
735
736
void svt_av1_highbd_convolve_x_sr_c(const uint16_t* src, int32_t src_stride, uint16_t* dst, int32_t dst_stride,
737
                                    int32_t w, int32_t h, const InterpFilterParams* filter_params_x,
738
                                    const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
739
0
                                    const int32_t subpel_y_q4, ConvolveParams* conv_params, int32_t bd) {
740
0
    const int32_t fo_horiz = filter_params_x->taps / 2 - 1;
741
0
    const int32_t bits     = FILTER_BITS - conv_params->round_0;
742
0
    (void)filter_params_y;
743
0
    (void)subpel_y_q4;
744
745
0
    assert(bits >= 0);
746
0
    assert((FILTER_BITS - conv_params->round_1) >= 0 ||
747
0
           ((conv_params->round_0 + conv_params->round_1) == 2 * FILTER_BITS));
748
749
    // horizontal filter
750
0
    const int16_t* x_filter = av1_get_interp_filter_subpel_kernel(*filter_params_x, subpel_x_q4 & SUBPEL_MASK);
751
0
    for (int32_t y = 0; y < h; ++y) {
752
0
        for (int32_t x = 0; x < w; ++x) {
753
0
            int32_t res = 0;
754
0
            for (int32_t k = 0; k < filter_params_x->taps; ++k) {
755
0
                res += x_filter[k] * src[y * src_stride + x - fo_horiz + k];
756
0
            }
757
0
            res                     = ROUND_POWER_OF_TWO(res, conv_params->round_0);
758
0
            dst[y * dst_stride + x] = clip_pixel_highbd(ROUND_POWER_OF_TWO(res, bits), bd);
759
0
        }
760
0
    }
761
0
}
762
763
void svt_av1_highbd_convolve_y_sr_c(const uint16_t* src, int32_t src_stride, uint16_t* dst, int32_t dst_stride,
764
                                    int32_t w, int32_t h, const InterpFilterParams* filter_params_x,
765
                                    const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
766
0
                                    const int32_t subpel_y_q4, ConvolveParams* conv_params, int32_t bd) {
767
0
    assert(filter_params_y != NULL);
768
0
    const int32_t fo_vert = filter_params_y->taps / 2 - 1;
769
0
    (void)filter_params_x;
770
0
    (void)subpel_x_q4;
771
0
    (void)conv_params;
772
773
0
    assert(conv_params->round_0 <= FILTER_BITS);
774
0
    assert(((conv_params->round_0 + conv_params->round_1) <= (FILTER_BITS + 1)) ||
775
0
           ((conv_params->round_0 + conv_params->round_1) == (2 * FILTER_BITS)));
776
    // vertical filter
777
0
    const int16_t* y_filter = av1_get_interp_filter_subpel_kernel(*filter_params_y, subpel_y_q4 & SUBPEL_MASK);
778
0
    for (int32_t y = 0; y < h; ++y) {
779
0
        for (int32_t x = 0; x < w; ++x) {
780
0
            int32_t res = 0;
781
0
            for (int32_t k = 0; k < filter_params_y->taps; ++k) {
782
0
                res += y_filter[k] * src[(y - fo_vert + k) * src_stride + x];
783
0
            }
784
0
            dst[y * dst_stride + x] = clip_pixel_highbd(ROUND_POWER_OF_TWO(res, FILTER_BITS), bd);
785
0
        }
786
0
    }
787
0
}
788
789
void svt_av1_highbd_convolve_2d_sr_c(const uint16_t* src, int32_t src_stride, uint16_t* dst, int32_t dst_stride,
790
                                     int32_t w, int32_t h, const InterpFilterParams* filter_params_x,
791
                                     const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
792
0
                                     const int32_t subpel_y_q4, ConvolveParams* conv_params, int32_t bd) {
793
0
    int16_t       im_block[(MAX_SB_SIZE + MAX_FILTER_TAP - 1) * MAX_SB_SIZE];
794
0
    int32_t       im_h      = h + filter_params_y->taps - 1;
795
0
    int32_t       im_stride = w;
796
0
    const int32_t fo_vert   = filter_params_y->taps / 2 - 1;
797
0
    const int32_t fo_horiz  = filter_params_x->taps / 2 - 1;
798
0
    const int32_t bits      = FILTER_BITS * 2 - conv_params->round_0 - conv_params->round_1;
799
0
    assert(bits >= 0);
800
801
    // horizontal filter
802
0
    const uint16_t* src_horiz = src - fo_vert * src_stride;
803
0
    const int16_t*  x_filter  = av1_get_interp_filter_subpel_kernel(*filter_params_x, subpel_x_q4 & SUBPEL_MASK);
804
0
    for (int32_t y = 0; y < im_h; ++y) {
805
0
        for (int32_t x = 0; x < w; ++x) {
806
0
            int32_t sum = (1 << (bd + FILTER_BITS - 1));
807
0
            for (int32_t k = 0; k < filter_params_x->taps; ++k) {
808
0
                sum += x_filter[k] * src_horiz[y * src_stride + x - fo_horiz + k];
809
0
            }
810
0
            assert(0 <= sum && sum < (1 << (bd + FILTER_BITS + 1)));
811
0
            im_block[y * im_stride + x] = (ConvBufType)ROUND_POWER_OF_TWO(sum, conv_params->round_0);
812
0
        }
813
0
    }
814
815
    // vertical filter
816
0
    int16_t*       src_vert    = im_block + fo_vert * im_stride;
817
0
    const int16_t* y_filter    = av1_get_interp_filter_subpel_kernel(*filter_params_y, subpel_y_q4 & SUBPEL_MASK);
818
0
    const int32_t  offset_bits = bd + 2 * FILTER_BITS - conv_params->round_0;
819
0
    for (int32_t y = 0; y < h; ++y) {
820
0
        for (int32_t x = 0; x < w; ++x) {
821
0
            int32_t sum = 1 << offset_bits;
822
0
            for (int32_t k = 0; k < filter_params_y->taps; ++k) {
823
0
                sum += y_filter[k] * src_vert[(y - fo_vert + k) * im_stride + x];
824
0
            }
825
0
            assert(0 <= sum && sum < (1 << (offset_bits + 2)));
826
0
            int32_t res = ROUND_POWER_OF_TWO(sum, conv_params->round_1) -
827
0
                ((1 << (offset_bits - conv_params->round_1)) + (1 << (offset_bits - conv_params->round_1 - 1)));
828
0
            dst[y * dst_stride + x] = clip_pixel_highbd(ROUND_POWER_OF_TWO(res, bits), bd);
829
0
        }
830
0
    }
831
0
}
832
833
void svt_av1_highbd_convolve_2d_scale_c(const uint16_t* src, int src_stride, uint16_t* dst, int dst_stride, int w,
834
                                        int h, const InterpFilterParams* filter_params_x,
835
                                        const InterpFilterParams* filter_params_y, const int subpel_x_qn,
836
                                        const int x_step_qn, const int subpel_y_qn, const int y_step_qn,
837
0
                                        ConvolveParams* conv_params, int bd) {
838
0
    int16_t        im_block[(2 * MAX_SB_SIZE + MAX_FILTER_TAP) * MAX_SB_SIZE];
839
0
    int            im_h         = (((h - 1) * y_step_qn + subpel_y_qn) >> SCALE_SUBPEL_BITS) + filter_params_y->taps;
840
0
    int            im_stride    = w;
841
0
    const int      fo_vert      = filter_params_y->taps / 2 - 1;
842
0
    const int      fo_horiz     = filter_params_x->taps / 2 - 1;
843
0
    CONV_BUF_TYPE* dst16        = conv_params->dst;
844
0
    const int      dst16_stride = conv_params->dst_stride;
845
0
    const int      bits         = FILTER_BITS * 2 - conv_params->round_0 - conv_params->round_1;
846
0
    assert(bits >= 0);
847
    // horizontal filter
848
0
    const uint16_t* src_horiz = src - fo_vert * src_stride;
849
0
    for (int y = 0; y < im_h; ++y) {
850
0
        int x_qn = subpel_x_qn;
851
0
        for (int x = 0; x < w; ++x, x_qn += x_step_qn) {
852
0
            const uint16_t* const src_x        = &src_horiz[(x_qn >> SCALE_SUBPEL_BITS)];
853
0
            const int             x_filter_idx = (x_qn & SCALE_SUBPEL_MASK) >> SCALE_EXTRA_BITS;
854
0
            assert(x_filter_idx < SUBPEL_SHIFTS);
855
0
            const int16_t* x_filter = av1_get_interp_filter_subpel_kernel(*filter_params_x, x_filter_idx);
856
0
            int32_t        sum      = (1 << (bd + FILTER_BITS - 1));
857
0
            for (int k = 0; k < filter_params_x->taps; ++k) {
858
0
                sum += x_filter[k] * src_x[k - fo_horiz];
859
0
            }
860
0
            assert(0 <= sum && sum < (1 << (bd + FILTER_BITS + 1)));
861
0
            im_block[y * im_stride + x] = (int16_t)ROUND_POWER_OF_TWO(sum, conv_params->round_0);
862
0
        }
863
0
        src_horiz += src_stride;
864
0
    }
865
866
    // vertical filter
867
0
    int16_t*  src_vert    = im_block + fo_vert * im_stride;
868
0
    const int offset_bits = bd + 2 * FILTER_BITS - conv_params->round_0;
869
0
    for (int x = 0; x < w; ++x) {
870
0
        int y_qn = subpel_y_qn;
871
0
        for (int y = 0; y < h; ++y, y_qn += y_step_qn) {
872
0
            const int16_t* src_y        = &src_vert[(y_qn >> SCALE_SUBPEL_BITS) * im_stride];
873
0
            const int      y_filter_idx = (y_qn & SCALE_SUBPEL_MASK) >> SCALE_EXTRA_BITS;
874
0
            assert(y_filter_idx < SUBPEL_SHIFTS);
875
0
            const int16_t* y_filter = av1_get_interp_filter_subpel_kernel(*filter_params_y, y_filter_idx);
876
0
            int32_t        sum      = 1 << offset_bits;
877
0
            for (int k = 0; k < filter_params_y->taps; ++k) {
878
0
                sum += y_filter[k] * src_y[(k - fo_vert) * im_stride];
879
0
            }
880
0
            assert(0 <= sum && sum < (1 << (offset_bits + 2)));
881
0
            CONV_BUF_TYPE res = ROUND_POWER_OF_TWO(sum, conv_params->round_1);
882
0
            if (conv_params->is_compound) {
883
0
                if (conv_params->do_average) {
884
0
                    int32_t tmp = dst16[y * dst16_stride + x];
885
0
                    if (conv_params->use_dist_wtd_comp_avg) {
886
0
                        tmp = tmp * conv_params->fwd_offset + res * conv_params->bck_offset;
887
0
                        tmp = tmp >> DIST_PRECISION_BITS;
888
0
                    } else {
889
0
                        tmp += res;
890
0
                        tmp = tmp >> 1;
891
0
                    }
892
                    /* Subtract round offset and convolve round */
893
0
                    tmp = tmp -
894
0
                        ((1 << (offset_bits - conv_params->round_1)) + (1 << (offset_bits - conv_params->round_1 - 1)));
895
0
                    dst[y * dst_stride + x] = clip_pixel_highbd(ROUND_POWER_OF_TWO(tmp, bits), bd);
896
0
                } else {
897
0
                    dst16[y * dst16_stride + x] = res;
898
0
                }
899
0
            } else {
900
                /* Subtract round offset and convolve round */
901
0
                int32_t tmp = res -
902
0
                    ((1 << (offset_bits - conv_params->round_1)) + (1 << (offset_bits - conv_params->round_1 - 1)));
903
0
                dst[y * dst_stride + x] = clip_pixel_highbd(ROUND_POWER_OF_TWO(tmp, bits), bd);
904
0
            }
905
0
        }
906
0
        src_vert++;
907
0
    }
908
0
}
909
910
void svt_av1_highbd_jnt_convolve_x_c(const uint16_t* src, int32_t src_stride, uint16_t* dst16, int32_t dst16_stride,
911
                                     int32_t w, int32_t h, const InterpFilterParams* filter_params_x,
912
                                     const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
913
0
                                     const int32_t subpel_y_q4, ConvolveParams* conv_params, int32_t bd) {
914
0
    ConvBufType*  dst          = conv_params->dst;
915
0
    int32_t       dst_stride   = conv_params->dst_stride;
916
0
    const int32_t fo_horiz     = filter_params_x->taps / 2 - 1;
917
0
    const int32_t bits         = FILTER_BITS - conv_params->round_1;
918
0
    const int32_t offset_bits  = bd + 2 * FILTER_BITS - conv_params->round_0;
919
0
    const int32_t round_offset = (1 << (offset_bits - conv_params->round_1)) +
920
0
        (1 << (offset_bits - conv_params->round_1 - 1));
921
0
    const int32_t round_bits = 2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1;
922
0
    assert(round_bits >= 0);
923
0
    (void)filter_params_y;
924
0
    (void)subpel_y_q4;
925
0
    assert(bits >= 0);
926
    // horizontal filter
927
0
    const int16_t* x_filter = av1_get_interp_filter_subpel_kernel(*filter_params_x, subpel_x_q4 & SUBPEL_MASK);
928
0
    for (int32_t y = 0; y < h; ++y) {
929
0
        for (int32_t x = 0; x < w; ++x) {
930
0
            int32_t res = 0;
931
0
            for (int32_t k = 0; k < filter_params_x->taps; ++k) {
932
0
                res += x_filter[k] * src[y * src_stride + x - fo_horiz + k];
933
0
            }
934
0
            res = (1 << bits) * ROUND_POWER_OF_TWO(res, conv_params->round_0);
935
0
            res += round_offset;
936
937
0
            if (conv_params->do_average) {
938
0
                int32_t tmp = dst[y * dst_stride + x];
939
0
                if (conv_params->use_jnt_comp_avg) {
940
0
                    tmp = tmp * conv_params->fwd_offset + res * conv_params->bck_offset;
941
0
                    tmp = tmp >> DIST_PRECISION_BITS;
942
0
                } else {
943
0
                    tmp += res;
944
0
                    tmp = tmp >> 1;
945
0
                }
946
0
                tmp -= round_offset;
947
0
                dst16[y * dst16_stride + x] = clip_pixel_highbd(ROUND_POWER_OF_TWO(tmp, round_bits), bd);
948
0
            } else {
949
0
                dst[y * dst_stride + x] = (ConvBufType)res;
950
0
            }
951
0
        }
952
0
    }
953
0
}
954
955
void svt_av1_highbd_jnt_convolve_y_c(const uint16_t* src, int32_t src_stride, uint16_t* dst16, int32_t dst16_stride,
956
                                     int32_t w, int32_t h, const InterpFilterParams* filter_params_x,
957
                                     const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
958
0
                                     const int32_t subpel_y_q4, ConvolveParams* conv_params, int32_t bd) {
959
0
    ConvBufType*  dst          = conv_params->dst;
960
0
    int32_t       dst_stride   = conv_params->dst_stride;
961
0
    const int32_t fo_vert      = filter_params_y->taps / 2 - 1;
962
0
    const int32_t bits         = FILTER_BITS - conv_params->round_0;
963
0
    const int32_t offset_bits  = bd + 2 * FILTER_BITS - conv_params->round_0;
964
0
    const int32_t round_offset = (1 << (offset_bits - conv_params->round_1)) +
965
0
        (1 << (offset_bits - conv_params->round_1 - 1));
966
0
    const int32_t round_bits = 2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1;
967
0
    assert(round_bits >= 0);
968
0
    (void)filter_params_x;
969
0
    (void)subpel_x_q4;
970
0
    assert(bits >= 0);
971
    // vertical filter
972
0
    const int16_t* y_filter = av1_get_interp_filter_subpel_kernel(*filter_params_y, subpel_y_q4 & SUBPEL_MASK);
973
0
    for (int32_t y = 0; y < h; ++y) {
974
0
        for (int32_t x = 0; x < w; ++x) {
975
0
            int32_t res = 0;
976
0
            for (int32_t k = 0; k < filter_params_y->taps; ++k) {
977
0
                res += y_filter[k] * src[(y - fo_vert + k) * src_stride + x];
978
0
            }
979
0
            res *= (1 << bits);
980
0
            res = ROUND_POWER_OF_TWO(res, conv_params->round_1) + round_offset;
981
982
0
            if (conv_params->do_average) {
983
0
                int32_t tmp = dst[y * dst_stride + x];
984
0
                if (conv_params->use_jnt_comp_avg) {
985
0
                    tmp = tmp * conv_params->fwd_offset + res * conv_params->bck_offset;
986
0
                    tmp = tmp >> DIST_PRECISION_BITS;
987
0
                } else {
988
0
                    tmp += res;
989
0
                    tmp = tmp >> 1;
990
0
                }
991
0
                tmp -= round_offset;
992
0
                dst16[y * dst16_stride + x] = clip_pixel_highbd(ROUND_POWER_OF_TWO(tmp, round_bits), bd);
993
0
            } else {
994
0
                dst[y * dst_stride + x] = (ConvBufType)res;
995
0
            }
996
0
        }
997
0
    }
998
0
}
999
1000
void svt_av1_highbd_jnt_convolve_2d_copy_c(const uint16_t* src, int32_t src_stride, uint16_t* dst16,
1001
                                           int32_t dst16_stride, int32_t w, int32_t h,
1002
                                           const InterpFilterParams* filter_params_x,
1003
                                           const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
1004
0
                                           const int32_t subpel_y_q4, ConvolveParams* conv_params, int32_t bd) {
1005
0
    ConvBufType*  dst          = conv_params->dst;
1006
0
    int32_t       dst_stride   = conv_params->dst_stride;
1007
0
    const int32_t bits         = FILTER_BITS * 2 - conv_params->round_1 - conv_params->round_0;
1008
0
    const int32_t offset_bits  = bd + 2 * FILTER_BITS - conv_params->round_0;
1009
0
    const int32_t round_offset = (1 << (offset_bits - conv_params->round_1)) +
1010
0
        (1 << (offset_bits - conv_params->round_1 - 1));
1011
0
    assert(bits >= 0);
1012
0
    (void)filter_params_x;
1013
0
    (void)filter_params_y;
1014
0
    (void)subpel_x_q4;
1015
0
    (void)subpel_y_q4;
1016
1017
0
    for (int32_t y = 0; y < h; ++y) {
1018
0
        for (int32_t x = 0; x < w; ++x) {
1019
0
            ConvBufType res = src[y * src_stride + x] << bits;
1020
0
            res += (ConvBufType)round_offset;
1021
0
            if (conv_params->do_average) {
1022
0
                int32_t tmp = dst[y * dst_stride + x];
1023
0
                if (conv_params->use_jnt_comp_avg) {
1024
0
                    tmp = tmp * conv_params->fwd_offset + res * conv_params->bck_offset;
1025
0
                    tmp = tmp >> DIST_PRECISION_BITS;
1026
0
                } else {
1027
0
                    tmp += res;
1028
0
                    tmp = tmp >> 1;
1029
0
                }
1030
0
                tmp -= round_offset;
1031
0
                dst16[y * dst16_stride + x] = clip_pixel_highbd(ROUND_POWER_OF_TWO(tmp, bits), bd);
1032
0
            } else {
1033
0
                dst[y * dst_stride + x] = res;
1034
0
            }
1035
0
        }
1036
0
    }
1037
0
}
1038
1039
void svt_av1_highbd_jnt_convolve_2d_c(const uint16_t* src, int32_t src_stride, uint16_t* dst16, int32_t dst16_stride,
1040
                                      int32_t w, int32_t h, const InterpFilterParams* filter_params_x,
1041
                                      const InterpFilterParams* filter_params_y, const int32_t subpel_x_q4,
1042
                                      const int32_t subpel_y_q4, ConvolveParams* conv_params, int32_t bd)
1043
1044
0
{
1045
0
    int16_t       im_block[(MAX_SB_SIZE + MAX_FILTER_TAP - 1) * MAX_SB_SIZE];
1046
0
    ConvBufType*  dst        = conv_params->dst;
1047
0
    int32_t       dst_stride = conv_params->dst_stride;
1048
0
    int32_t       im_h       = h + filter_params_y->taps - 1;
1049
0
    int32_t       im_stride  = w;
1050
0
    const int32_t fo_vert    = filter_params_y->taps / 2 - 1;
1051
0
    const int32_t fo_horiz   = filter_params_x->taps / 2 - 1;
1052
1053
0
    const int32_t round_bits = 2 * FILTER_BITS - conv_params->round_0 - conv_params->round_1;
1054
0
    assert(round_bits >= 0);
1055
1056
    // horizontal filter
1057
0
    const uint16_t* src_horiz = src - fo_vert * src_stride;
1058
0
    const int16_t*  x_filter  = av1_get_interp_filter_subpel_kernel(*filter_params_x, subpel_x_q4 & SUBPEL_MASK);
1059
0
    for (int y = 0; y < im_h; ++y) {
1060
0
        for (int x = 0; x < w; ++x) {
1061
0
            int32_t sum = (1 << (bd + FILTER_BITS - 1));
1062
0
            for (int k = 0; k < filter_params_x->taps; ++k) {
1063
0
                sum += x_filter[k] * src_horiz[y * src_stride + x - fo_horiz + k];
1064
0
            }
1065
0
            assert(0 <= sum && sum < (1 << (bd + FILTER_BITS + 1)));
1066
0
            (void)bd;
1067
0
            im_block[y * im_stride + x] = (int16_t)ROUND_POWER_OF_TWO(sum, conv_params->round_0);
1068
0
        }
1069
0
    }
1070
1071
    // vertical filter
1072
0
    int16_t*       src_vert    = im_block + fo_vert * im_stride;
1073
0
    const int32_t  offset_bits = bd + 2 * FILTER_BITS - conv_params->round_0;
1074
0
    const int16_t* y_filter    = av1_get_interp_filter_subpel_kernel(*filter_params_y, subpel_y_q4 & SUBPEL_MASK);
1075
0
    for (int y = 0; y < h; ++y) {
1076
0
        for (int x = 0; x < w; ++x) {
1077
0
            int32_t sum = 1 << offset_bits;
1078
0
            for (int k = 0; k < filter_params_y->taps; ++k) {
1079
0
                sum += y_filter[k] * src_vert[(y - fo_vert + k) * im_stride + x];
1080
0
            }
1081
0
            assert(0 <= sum && sum < (1 << (offset_bits + 2)));
1082
0
            ConvBufType res = (ConvBufType)ROUND_POWER_OF_TWO(sum, conv_params->round_1);
1083
0
            if (conv_params->do_average) {
1084
0
                int32_t tmp = dst[y * dst_stride + x];
1085
0
                if (conv_params->use_jnt_comp_avg) {
1086
0
                    tmp = tmp * conv_params->fwd_offset + res * conv_params->bck_offset;
1087
0
                    tmp = tmp >> DIST_PRECISION_BITS;
1088
0
                } else {
1089
0
                    tmp += res;
1090
0
                    tmp = tmp >> 1;
1091
0
                }
1092
0
                tmp -= (1 << (offset_bits - conv_params->round_1)) + (1 << (offset_bits - conv_params->round_1 - 1));
1093
0
                dst16[y * dst16_stride + x] = clip_pixel_highbd(ROUND_POWER_OF_TWO(tmp, round_bits), bd);
1094
0
            } else {
1095
0
                dst[y * dst_stride + x] = res;
1096
0
            }
1097
0
        }
1098
0
    }
1099
0
}
1100
1101
aom_highbd_convolve_fn_t svt_aom_convolveHbd[/*subX*/ 2][/*subY*/ 2][/*bi*/ 2];
1102
1103
1
void svt_aom_asm_set_convolve_hbd_asm_table(void) {
1104
1
    svt_aom_convolveHbd[0][0][0] = svt_av1_highbd_convolve_2d_copy_sr;
1105
1
    svt_aom_convolveHbd[0][0][1] = svt_av1_highbd_jnt_convolve_2d_copy;
1106
1107
1
    svt_aom_convolveHbd[0][1][0] = svt_av1_highbd_convolve_y_sr;
1108
1
    svt_aom_convolveHbd[0][1][1] = svt_av1_highbd_jnt_convolve_y;
1109
1110
1
    svt_aom_convolveHbd[1][0][0] = svt_av1_highbd_convolve_x_sr;
1111
1
    svt_aom_convolveHbd[1][0][1] = svt_av1_highbd_jnt_convolve_x;
1112
1113
1
    svt_aom_convolveHbd[1][1][0] = svt_av1_highbd_convolve_2d_sr;
1114
1
    svt_aom_convolveHbd[1][1][1] = svt_av1_highbd_jnt_convolve_2d;
1115
1
}
1116
1117
AomConvolveFn svt_aom_convolve[/*subX*/ 2][/*subY*/ 2][/*bi*/ 2];
1118
1119
1
void svt_aom_asm_set_convolve_asm_table(void) {
1120
1
    svt_aom_convolve[0][0][0] = svt_av1_convolve_2d_copy_sr;
1121
1
    svt_aom_convolve[0][1][0] = svt_av1_convolve_y_sr;
1122
1
    svt_aom_convolve[1][0][0] = svt_av1_convolve_x_sr;
1123
1
    svt_aom_convolve[1][1][0] = svt_av1_convolve_2d_sr;
1124
1
#if CONFIG_ENABLE_INTER_COMPOUND
1125
    // Compound (jnt) convolve is only reached when is_compound==1 (a block with a
1126
    // 2nd reference). RTC minimal is single-ref (see mrp coupling assert), so these
1127
    // slots are never indexed; guarding them lets LTO strip the jnt_convolve impls.
1128
1
    svt_aom_convolve[0][0][1] = svt_av1_jnt_convolve_2d_copy;
1129
1
    svt_aom_convolve[0][1][1] = svt_av1_jnt_convolve_y;
1130
1
    svt_aom_convolve[1][0][1] = svt_av1_jnt_convolve_x;
1131
1
    svt_aom_convolve[1][1][1] = svt_av1_jnt_convolve_2d;
1132
1
#endif
1133
1
}
1134
1135
DECLARE_ALIGNED(256, const InterpKernel, sub_pel_filters_8sharp[SUBPEL_SHIFTS]) = {{0, 0, 0, 128, 0, 0, 0, 0},
1136
                                                                                   {-2, 2, -6, 126, 8, -2, 2, 0},
1137
                                                                                   {-2, 6, -12, 124, 16, -6, 4, -2},
1138
                                                                                   {-2, 8, -18, 120, 26, -10, 6, -2},
1139
                                                                                   {-4, 10, -22, 116, 38, -14, 6, -2},
1140
                                                                                   {-4, 10, -22, 108, 48, -18, 8, -2},
1141
                                                                                   {-4, 10, -24, 100, 60, -20, 8, -2},
1142
                                                                                   {-4, 10, -24, 90, 70, -22, 10, -2},
1143
                                                                                   {-4, 12, -24, 80, 80, -24, 12, -4},
1144
                                                                                   {-2, 10, -22, 70, 90, -24, 10, -4},
1145
                                                                                   {-2, 8, -20, 60, 100, -24, 10, -4},
1146
                                                                                   {-2, 8, -18, 48, 108, -22, 10, -4},
1147
                                                                                   {-2, 6, -14, 38, 116, -22, 10, -4},
1148
                                                                                   {-2, 6, -10, 26, 120, -18, 8, -2},
1149
                                                                                   {-2, 4, -6, 16, 124, -12, 6, -2},
1150
                                                                                   {0, 2, -2, 8, 126, -6, 2, -2}};
1151
1152
DECLARE_ALIGNED(256, const InterpKernel, sub_pel_filters_8smooth[SUBPEL_SHIFTS]) = {{0, 0, 0, 128, 0, 0, 0, 0},
1153
                                                                                    {0, 2, 28, 62, 34, 2, 0, 0},
1154
                                                                                    {0, 0, 26, 62, 36, 4, 0, 0},
1155
                                                                                    {0, 0, 22, 62, 40, 4, 0, 0},
1156
                                                                                    {0, 0, 20, 60, 42, 6, 0, 0},
1157
                                                                                    {0, 0, 18, 58, 44, 8, 0, 0},
1158
                                                                                    {0, 0, 16, 56, 46, 10, 0, 0},
1159
                                                                                    {0, -2, 16, 54, 48, 12, 0, 0},
1160
                                                                                    {0, -2, 14, 52, 52, 14, -2, 0},
1161
                                                                                    {0, 0, 12, 48, 54, 16, -2, 0},
1162
                                                                                    {0, 0, 10, 46, 56, 16, 0, 0},
1163
                                                                                    {0, 0, 8, 44, 58, 18, 0, 0},
1164
                                                                                    {0, 0, 6, 42, 60, 20, 0, 0},
1165
                                                                                    {0, 0, 4, 40, 62, 22, 0, 0},
1166
                                                                                    {0, 0, 4, 36, 62, 26, 0, 0},
1167
                                                                                    {0, 0, 2, 34, 62, 28, 2, 0}};
1168
DECLARE_ALIGNED(256, const InterpKernel, bilinear_filters[SUBPEL_SHIFTS])        = {{0, 0, 0, 128, 0, 0, 0, 0},
1169
                                                                                    {0, 0, 0, 120, 8, 0, 0, 0},
1170
                                                                                    {0, 0, 0, 112, 16, 0, 0, 0},
1171
                                                                                    {0, 0, 0, 104, 24, 0, 0, 0},
1172
                                                                                    {0, 0, 0, 96, 32, 0, 0, 0},
1173
                                                                                    {0, 0, 0, 88, 40, 0, 0, 0},
1174
                                                                                    {0, 0, 0, 80, 48, 0, 0, 0},
1175
                                                                                    {0, 0, 0, 72, 56, 0, 0, 0},
1176
                                                                                    {0, 0, 0, 64, 64, 0, 0, 0},
1177
                                                                                    {0, 0, 0, 56, 72, 0, 0, 0},
1178
                                                                                    {0, 0, 0, 48, 80, 0, 0, 0},
1179
                                                                                    {0, 0, 0, 40, 88, 0, 0, 0},
1180
                                                                                    {0, 0, 0, 32, 96, 0, 0, 0},
1181
                                                                                    {0, 0, 0, 24, 104, 0, 0, 0},
1182
                                                                                    {0, 0, 0, 16, 112, 0, 0, 0},
1183
                                                                                    {0, 0, 0, 8, 120, 0, 0, 0}};
1184
DECLARE_ALIGNED(256, const InterpKernel, sub_pel_filters_4smooth[SUBPEL_SHIFTS]) = {{0, 0, 0, 128, 0, 0, 0, 0},
1185
                                                                                    {0, 0, 30, 62, 34, 2, 0, 0},
1186
                                                                                    {0, 0, 26, 62, 36, 4, 0, 0},
1187
                                                                                    {0, 0, 22, 62, 40, 4, 0, 0},
1188
                                                                                    {0, 0, 20, 60, 42, 6, 0, 0},
1189
                                                                                    {0, 0, 18, 58, 44, 8, 0, 0},
1190
                                                                                    {0, 0, 16, 56, 46, 10, 0, 0},
1191
                                                                                    {0, 0, 14, 54, 48, 12, 0, 0},
1192
                                                                                    {0, 0, 12, 52, 52, 12, 0, 0},
1193
                                                                                    {0, 0, 12, 48, 54, 14, 0, 0},
1194
                                                                                    {0, 0, 10, 46, 56, 16, 0, 0},
1195
                                                                                    {0, 0, 8, 44, 58, 18, 0, 0},
1196
                                                                                    {0, 0, 6, 42, 60, 20, 0, 0},
1197
                                                                                    {0, 0, 4, 40, 62, 22, 0, 0},
1198
                                                                                    {0, 0, 4, 36, 62, 26, 0, 0},
1199
                                                                                    {0, 0, 2, 34, 62, 30, 0, 0}};
1200
BlockSize svt_aom_scale_chroma_bsize(BlockSize bsize, int32_t subsampling_x, int32_t subsampling_y);
1201
1202
void convolve_2d_for_intrabc(const uint8_t* src, int src_stride, uint8_t* dst, int dst_stride, int w, int h,
1203
0
                             int subpel_x_q4, int subpel_y_q4, ConvolveParams* conv_params) {
1204
0
    const InterpFilterParams* filter_params_x = subpel_x_q4 ? &av1_interp_filter_params_list[BILINEAR] : NULL;
1205
0
    const InterpFilterParams* filter_params_y = subpel_y_q4 ? &av1_interp_filter_params_list[BILINEAR] : NULL;
1206
0
    if (subpel_x_q4 != 0 && subpel_y_q4 != 0) {
1207
0
        svt_av1_convolve_2d_sr(src,
1208
0
                               src_stride,
1209
0
                               dst,
1210
0
                               dst_stride,
1211
0
                               w,
1212
0
                               h,
1213
0
                               (InterpFilterParams*)filter_params_x,
1214
0
                               (InterpFilterParams*)filter_params_y,
1215
0
                               8,
1216
0
                               8,
1217
0
                               conv_params);
1218
0
    } else if (subpel_x_q4 != 0) {
1219
0
        svt_av1_convolve_x_sr(src,
1220
0
                              src_stride,
1221
0
                              dst,
1222
0
                              dst_stride,
1223
0
                              w,
1224
0
                              h,
1225
0
                              (InterpFilterParams*)filter_params_x,
1226
0
                              (InterpFilterParams*)filter_params_y,
1227
0
                              8,
1228
0
                              0,
1229
0
                              conv_params);
1230
0
    } else {
1231
0
        svt_av1_convolve_y_sr(src,
1232
0
                              src_stride,
1233
0
                              dst,
1234
0
                              dst_stride,
1235
0
                              w,
1236
0
                              h,
1237
0
                              (InterpFilterParams*)filter_params_x,
1238
0
                              (InterpFilterParams*)filter_params_y,
1239
0
                              0,
1240
0
                              8,
1241
0
                              conv_params);
1242
0
    }
1243
0
}
1244
1245
void highbd_convolve_2d_for_intrabc(const uint16_t* src, int src_stride, uint16_t* dst, int dst_stride, int w, int h,
1246
0
                                    int subpel_x_q4, int subpel_y_q4, ConvolveParams* conv_params, int bd) {
1247
0
    const InterpFilterParams* filter_params_x = subpel_x_q4 ? &av1_interp_filter_params_list[BILINEAR] : NULL;
1248
0
    const InterpFilterParams* filter_params_y = subpel_y_q4 ? &av1_interp_filter_params_list[BILINEAR] : NULL;
1249
0
    if (subpel_x_q4 != 0 && subpel_y_q4 != 0) {
1250
0
        svt_av1_highbd_convolve_2d_sr(
1251
0
            src, src_stride, dst, dst_stride, w, h, filter_params_x, filter_params_y, 8, 8, conv_params, bd);
1252
0
    } else if (subpel_x_q4 != 0) {
1253
0
        svt_av1_highbd_convolve_x_sr(
1254
0
            src, src_stride, dst, dst_stride, w, h, filter_params_x, filter_params_y, 8, 0, conv_params, bd);
1255
0
    } else {
1256
0
        svt_av1_highbd_convolve_y_sr(
1257
0
            src, src_stride, dst, dst_stride, w, h, filter_params_x, filter_params_y, 0, 8, conv_params, bd);
1258
0
    }
1259
0
}
1260
1261
/*
1262
*/
1263
void svt_inter_predictor_pd0(const uint8_t* src, int32_t src_stride, uint8_t* dst, int32_t dst_stride, int32_t w,
1264
0
                             int32_t h, SubpelParams* subpel_params, ConvolveParams* conv_params) {
1265
0
    const int32_t is_scaled = has_scale(subpel_params->xs, subpel_params->ys);
1266
0
    if (is_scaled) {
1267
0
        InterpFilterParams filter_params_x, filter_params_y;
1268
0
        av1_get_convolve_filter_params(
1269
0
            av1_make_interp_filters(EIGHTTAP_REGULAR, EIGHTTAP_REGULAR), &filter_params_x, &filter_params_y, w, h);
1270
0
        svt_av1_convolve_2d_scale(src,
1271
0
                                  src_stride,
1272
0
                                  dst,
1273
0
                                  dst_stride,
1274
0
                                  w,
1275
0
                                  h,
1276
0
                                  &filter_params_x,
1277
0
                                  &filter_params_y,
1278
0
                                  subpel_params->subpel_x,
1279
0
                                  subpel_params->xs,
1280
0
                                  subpel_params->subpel_y,
1281
0
                                  subpel_params->ys,
1282
0
                                  conv_params);
1283
0
    } else {
1284
0
        UNUSED(subpel_params);
1285
0
        svt_aom_convolve[0][0][conv_params->is_compound](
1286
0
            src, src_stride, dst, dst_stride, w, h, 0, 0, 0, 0, conv_params);
1287
0
    }
1288
0
}
1289
1290
void svt_inter_predictor_light_pd1(uint8_t* src, uint8_t* src_2b, int32_t src_stride, uint8_t* dst, int32_t dst_stride,
1291
                                   int32_t w, int32_t h, InterpFilters interp_filters, SubpelParams* subpel_params,
1292
0
                                   ConvolveParams* conv_params, int32_t bd) {
1293
0
    InterpFilterParams filter_params_x, filter_params_y;
1294
0
    av1_get_convolve_filter_params(interp_filters, &filter_params_x, &filter_params_y, w, h);
1295
0
    const int32_t is_scaled = has_scale(subpel_params->xs, subpel_params->ys);
1296
1297
0
#if CONFIG_ENABLE_HIGH_BIT_DEPTH
1298
0
    if (bd > EB_EIGHT_BIT) {
1299
        // for super-res, the reference frame block might be 2x than predictor in maximum
1300
        // for reference scaling, it might be 4x since both width and height is scaled 2x
1301
        // should pack enough buffer for scaled reference
1302
0
        DECLARE_ALIGNED(16, uint16_t, src16[PACKED_BUFFER_SIZE * 4]);
1303
0
        int32_t src_stride16;
1304
        // pack the reference into temp 16bit buffer
1305
0
        uint8_t  offset       = INTERPOLATION_OFFSET;
1306
0
        uint32_t width_scale  = 1;
1307
0
        uint32_t height_scale = 1;
1308
0
        if (is_scaled) {
1309
0
            width_scale  = subpel_params->xs != SCALE_SUBPEL_SHIFTS ? 2 : 1;
1310
0
            height_scale = subpel_params->ys != SCALE_SUBPEL_SHIFTS ? 2 : 1;
1311
0
        }
1312
        // optimize stride from MAX_SB_SIZE to bwidth to minimum the block buffer size
1313
0
        src_stride16 = w * width_scale + (offset << 1);
1314
        // 16-byte align of src16
1315
0
        if (src_stride16 % 8) {
1316
0
            src_stride16 = ALIGN_POWER_OF_TWO(src_stride16, 3);
1317
0
        }
1318
1319
0
        svt_aom_pack_block(src - offset - (offset * src_stride),
1320
0
                           src_stride,
1321
0
                           src_2b - offset - (offset * src_stride),
1322
0
                           src_stride,
1323
0
                           src16,
1324
0
                           src_stride16,
1325
0
                           w * width_scale + (offset << 1),
1326
0
                           h * height_scale + (offset << 1));
1327
0
        uint16_t* src_10b = src16 + offset + (offset * src_stride16);
1328
0
        uint16_t* dst16   = (uint16_t*)dst;
1329
1330
0
        if (is_scaled) {
1331
0
            svt_av1_highbd_convolve_2d_scale(src_10b,
1332
0
                                             src_stride16,
1333
0
                                             dst16,
1334
0
                                             dst_stride,
1335
0
                                             w,
1336
0
                                             h,
1337
0
                                             &filter_params_x,
1338
0
                                             &filter_params_y,
1339
0
                                             subpel_params->subpel_x,
1340
0
                                             subpel_params->xs,
1341
0
                                             subpel_params->subpel_y,
1342
0
                                             subpel_params->ys,
1343
0
                                             conv_params,
1344
0
                                             bd);
1345
0
        } else {
1346
0
            SubpelParams sp = *subpel_params;
1347
0
            revert_scale_extra_bits(&sp);
1348
0
            svt_aom_convolveHbd[sp.subpel_x != 0][sp.subpel_y != 0][conv_params->is_compound](src_10b,
1349
0
                                                                                              src_stride16,
1350
0
                                                                                              dst16,
1351
0
                                                                                              dst_stride,
1352
0
                                                                                              w,
1353
0
                                                                                              h,
1354
0
                                                                                              &filter_params_x,
1355
0
                                                                                              &filter_params_y,
1356
0
                                                                                              sp.subpel_x,
1357
0
                                                                                              sp.subpel_y,
1358
0
                                                                                              conv_params,
1359
0
                                                                                              bd);
1360
0
        }
1361
0
    } else
1362
#else
1363
    UNUSED(bd);
1364
    UNUSED(src_2b);
1365
#endif
1366
0
    {
1367
0
        if (is_scaled) {
1368
0
            svt_av1_convolve_2d_scale(src,
1369
0
                                      src_stride,
1370
0
                                      dst,
1371
0
                                      dst_stride,
1372
0
                                      w,
1373
0
                                      h,
1374
0
                                      &filter_params_x,
1375
0
                                      &filter_params_y,
1376
0
                                      subpel_params->subpel_x,
1377
0
                                      subpel_params->xs,
1378
0
                                      subpel_params->subpel_y,
1379
0
                                      subpel_params->ys,
1380
0
                                      conv_params);
1381
0
        } else {
1382
0
            SubpelParams sp = *subpel_params;
1383
0
            revert_scale_extra_bits(&sp);
1384
0
            svt_aom_convolve[sp.subpel_x != 0][sp.subpel_y != 0][conv_params->is_compound](src,
1385
0
                                                                                           src_stride,
1386
0
                                                                                           dst,
1387
0
                                                                                           dst_stride,
1388
0
                                                                                           w,
1389
0
                                                                                           h,
1390
0
                                                                                           &filter_params_x,
1391
0
                                                                                           &filter_params_y,
1392
0
                                                                                           sp.subpel_x,
1393
0
                                                                                           sp.subpel_y,
1394
0
                                                                                           conv_params);
1395
0
        }
1396
0
    }
1397
0
}
1398
1399
void svt_inter_predictor(const uint8_t* src, int32_t src_stride, uint8_t* dst, int32_t dst_stride,
1400
                         const SubpelParams* subpel_params, const ScaleFactors* sf, int32_t w, int32_t h,
1401
0
                         ConvolveParams* conv_params, InterpFilters interp_filters, int32_t is_intrabc) {
1402
0
    InterpFilterParams filter_params_x, filter_params_y;
1403
0
    const int32_t      is_scaled = has_scale(subpel_params->xs, subpel_params->ys);
1404
1405
0
    av1_get_convolve_filter_params(interp_filters, &filter_params_x, &filter_params_y, w, h);
1406
1407
0
    assert(conv_params->do_average == 0 || conv_params->do_average == 1);
1408
0
    assert(sf);
1409
0
    UNUSED(sf);
1410
0
    assert(IMPLIES(is_intrabc, !is_scaled));
1411
1412
0
    if (is_scaled) {
1413
0
        if (is_intrabc && (subpel_params->subpel_x != 0 || subpel_params->subpel_y != 0)) {
1414
0
            convolve_2d_for_intrabc(
1415
0
                src, src_stride, dst, dst_stride, w, h, subpel_params->subpel_x, subpel_params->subpel_y, conv_params);
1416
0
            return;
1417
0
        }
1418
0
        if (conv_params->is_compound) {
1419
0
            assert(conv_params->dst != NULL);
1420
0
        }
1421
0
        svt_av1_convolve_2d_scale(src,
1422
0
                                  src_stride,
1423
0
                                  dst,
1424
0
                                  dst_stride,
1425
0
                                  w,
1426
0
                                  h,
1427
0
                                  &filter_params_x,
1428
0
                                  &filter_params_y,
1429
0
                                  subpel_params->subpel_x,
1430
0
                                  subpel_params->xs,
1431
0
                                  subpel_params->subpel_y,
1432
0
                                  subpel_params->ys,
1433
0
                                  conv_params);
1434
0
    } else {
1435
0
        SubpelParams sp = *subpel_params;
1436
0
        revert_scale_extra_bits(&sp);
1437
1438
0
        if (is_intrabc && (sp.subpel_x != 0 || sp.subpel_y != 0)) {
1439
0
            convolve_2d_for_intrabc(src, src_stride, dst, dst_stride, w, h, sp.subpel_x, sp.subpel_y, conv_params);
1440
0
            return;
1441
0
        }
1442
1443
0
        svt_aom_convolve[sp.subpel_x != 0][sp.subpel_y != 0][conv_params->is_compound](src,
1444
0
                                                                                       src_stride,
1445
0
                                                                                       dst,
1446
0
                                                                                       dst_stride,
1447
0
                                                                                       w,
1448
0
                                                                                       h,
1449
0
                                                                                       &filter_params_x,
1450
0
                                                                                       &filter_params_y,
1451
0
                                                                                       sp.subpel_x,
1452
0
                                                                                       sp.subpel_y,
1453
0
                                                                                       conv_params);
1454
0
    }
1455
0
}
1456
1457
void svt_highbd_inter_predictor(const uint16_t* src, int32_t src_stride, uint16_t* dst, int32_t dst_stride,
1458
                                const SubpelParams* subpel_params, const ScaleFactors* sf, int32_t w, int32_t h,
1459
                                ConvolveParams* conv_params, InterpFilters interp_filters, int32_t is_intrabc,
1460
0
                                int32_t bd) {
1461
0
    InterpFilterParams filter_params_x, filter_params_y;
1462
0
    const int32_t      is_scaled = has_scale(subpel_params->xs, subpel_params->ys);
1463
1464
0
    av1_get_convolve_filter_params(interp_filters, &filter_params_x, &filter_params_y, w, h);
1465
1466
0
    assert(conv_params->do_average == 0 || conv_params->do_average == 1);
1467
0
    assert(sf);
1468
0
    UNUSED(sf);
1469
0
    assert(IMPLIES(is_intrabc, !is_scaled));
1470
1471
0
    if (is_scaled) {
1472
0
        if (is_intrabc && (subpel_params->subpel_x != 0 || subpel_params->subpel_y != 0)) {
1473
0
            highbd_convolve_2d_for_intrabc(src,
1474
0
                                           src_stride,
1475
0
                                           dst,
1476
0
                                           dst_stride,
1477
0
                                           w,
1478
0
                                           h,
1479
0
                                           subpel_params->subpel_x,
1480
0
                                           subpel_params->subpel_y,
1481
0
                                           conv_params,
1482
0
                                           bd);
1483
0
            return;
1484
0
        }
1485
0
        if (conv_params->is_compound) {
1486
0
            assert(conv_params->dst != NULL);
1487
0
        }
1488
0
        svt_av1_highbd_convolve_2d_scale(src,
1489
0
                                         src_stride,
1490
0
                                         dst,
1491
0
                                         dst_stride,
1492
0
                                         w,
1493
0
                                         h,
1494
0
                                         &filter_params_x,
1495
0
                                         &filter_params_y,
1496
0
                                         subpel_params->subpel_x,
1497
0
                                         subpel_params->xs,
1498
0
                                         subpel_params->subpel_y,
1499
0
                                         subpel_params->ys,
1500
0
                                         conv_params,
1501
0
                                         bd);
1502
0
    } else {
1503
0
        SubpelParams sp = *subpel_params;
1504
0
        revert_scale_extra_bits(&sp);
1505
1506
0
        if (is_intrabc && (sp.subpel_x != 0 || sp.subpel_y != 0)) {
1507
0
            highbd_convolve_2d_for_intrabc(
1508
0
                src, src_stride, dst, dst_stride, w, h, sp.subpel_x, sp.subpel_y, conv_params, bd);
1509
0
            return;
1510
0
        }
1511
1512
0
        svt_aom_convolveHbd[sp.subpel_x != 0][sp.subpel_y != 0][conv_params->is_compound](src,
1513
0
                                                                                          src_stride,
1514
0
                                                                                          dst,
1515
0
                                                                                          dst_stride,
1516
0
                                                                                          w,
1517
0
                                                                                          h,
1518
0
                                                                                          &filter_params_x,
1519
0
                                                                                          &filter_params_y,
1520
0
                                                                                          sp.subpel_x,
1521
0
                                                                                          sp.subpel_y,
1522
0
                                                                                          conv_params,
1523
0
                                                                                          bd);
1524
0
    }
1525
0
}
1526
1527
#define USE_PRECOMPUTED_WEDGE_SIGN 1
1528
#define USE_PRECOMPUTED_WEDGE_MASK 1
1529
1530
#if USE_PRECOMPUTED_WEDGE_MASK
1531
static const uint8_t wedge_primary_oblique_odd[MASK_PRIMARY_SIZE] = {
1532
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1533
    0,  0,  0,  0,  0,  0,  1,  2,  6,  18, 37, 53, 60, 63, 64, 64, 64, 64, 64, 64, 64, 64,
1534
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1535
};
1536
static const uint8_t wedge_primary_oblique_even[MASK_PRIMARY_SIZE] = {
1537
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1538
    0,  0,  0,  0,  0,  0,  1,  4,  11, 27, 46, 58, 62, 63, 64, 64, 64, 64, 64, 64, 64, 64,
1539
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1540
};
1541
static const uint8_t wedge_primary_vertical[MASK_PRIMARY_SIZE] = {
1542
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
1543
    0,  0,  0,  0,  0,  0,  0,  2,  7,  21, 43, 57, 62, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1544
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
1545
};
1546
1547
DECLARE_ALIGNED(16, static uint8_t, wedge_signflip_lookup[BLOCK_SIZES_ALL][MAX_WEDGE_TYPES]) = {
1548
    {
1549
        0,
1550
        0,
1551
        0,
1552
        0,
1553
        0,
1554
        0,
1555
        0,
1556
        0,
1557
        0,
1558
        0,
1559
        0,
1560
        0,
1561
        0,
1562
        0,
1563
        0,
1564
        0,
1565
    }, // not used
1566
    {
1567
        0,
1568
        0,
1569
        0,
1570
        0,
1571
        0,
1572
        0,
1573
        0,
1574
        0,
1575
        0,
1576
        0,
1577
        0,
1578
        0,
1579
        0,
1580
        0,
1581
        0,
1582
        0,
1583
    }, // not used
1584
    {
1585
        0,
1586
        0,
1587
        0,
1588
        0,
1589
        0,
1590
        0,
1591
        0,
1592
        0,
1593
        0,
1594
        0,
1595
        0,
1596
        0,
1597
        0,
1598
        0,
1599
        0,
1600
        0,
1601
    }, // not used
1602
    {
1603
        1,
1604
        1,
1605
        1,
1606
        1,
1607
        1,
1608
        1,
1609
        1,
1610
        1,
1611
        1,
1612
        1,
1613
        0,
1614
        1,
1615
        1,
1616
        1,
1617
        0,
1618
        1,
1619
    },
1620
    {
1621
        1,
1622
        1,
1623
        1,
1624
        1,
1625
        0,
1626
        1,
1627
        1,
1628
        1,
1629
        1,
1630
        1,
1631
        0,
1632
        1,
1633
        1,
1634
        1,
1635
        0,
1636
        1,
1637
    },
1638
    {
1639
        1,
1640
        1,
1641
        1,
1642
        1,
1643
        0,
1644
        1,
1645
        1,
1646
        1,
1647
        1,
1648
        1,
1649
        0,
1650
        1,
1651
        1,
1652
        1,
1653
        0,
1654
        1,
1655
    },
1656
    {
1657
        1,
1658
        1,
1659
        1,
1660
        1,
1661
        1,
1662
        1,
1663
        1,
1664
        1,
1665
        1,
1666
        1,
1667
        0,
1668
        1,
1669
        1,
1670
        1,
1671
        0,
1672
        1,
1673
    },
1674
    {
1675
        1,
1676
        1,
1677
        1,
1678
        1,
1679
        0,
1680
        1,
1681
        1,
1682
        1,
1683
        1,
1684
        1,
1685
        0,
1686
        1,
1687
        1,
1688
        1,
1689
        0,
1690
        1,
1691
    },
1692
    {
1693
        1,
1694
        1,
1695
        1,
1696
        1,
1697
        0,
1698
        1,
1699
        1,
1700
        1,
1701
        1,
1702
        1,
1703
        0,
1704
        1,
1705
        1,
1706
        1,
1707
        0,
1708
        1,
1709
    },
1710
    {
1711
        1,
1712
        1,
1713
        1,
1714
        1,
1715
        1,
1716
        1,
1717
        1,
1718
        1,
1719
        1,
1720
        1,
1721
        0,
1722
        1,
1723
        1,
1724
        1,
1725
        0,
1726
        1,
1727
    },
1728
    {
1729
        0,
1730
        0,
1731
        0,
1732
        0,
1733
        0,
1734
        0,
1735
        0,
1736
        0,
1737
        0,
1738
        0,
1739
        0,
1740
        0,
1741
        0,
1742
        0,
1743
        0,
1744
        0,
1745
    }, // not used
1746
    {
1747
        0,
1748
        0,
1749
        0,
1750
        0,
1751
        0,
1752
        0,
1753
        0,
1754
        0,
1755
        0,
1756
        0,
1757
        0,
1758
        0,
1759
        0,
1760
        0,
1761
        0,
1762
        0,
1763
    }, // not used
1764
    {
1765
        0,
1766
        0,
1767
        0,
1768
        0,
1769
        0,
1770
        0,
1771
        0,
1772
        0,
1773
        0,
1774
        0,
1775
        0,
1776
        0,
1777
        0,
1778
        0,
1779
        0,
1780
        0,
1781
    }, // not used
1782
    {
1783
        0,
1784
        0,
1785
        0,
1786
        0,
1787
        0,
1788
        0,
1789
        0,
1790
        0,
1791
        0,
1792
        0,
1793
        0,
1794
        0,
1795
        0,
1796
        0,
1797
        0,
1798
        0,
1799
    }, // not used
1800
    {
1801
        0,
1802
        0,
1803
        0,
1804
        0,
1805
        0,
1806
        0,
1807
        0,
1808
        0,
1809
        0,
1810
        0,
1811
        0,
1812
        0,
1813
        0,
1814
        0,
1815
        0,
1816
        0,
1817
    }, // not used
1818
    {
1819
        0,
1820
        0,
1821
        0,
1822
        0,
1823
        0,
1824
        0,
1825
        0,
1826
        0,
1827
        0,
1828
        0,
1829
        0,
1830
        0,
1831
        0,
1832
        0,
1833
        0,
1834
        0,
1835
    }, // not used
1836
    {
1837
        0,
1838
        0,
1839
        0,
1840
        0,
1841
        0,
1842
        0,
1843
        0,
1844
        0,
1845
        0,
1846
        0,
1847
        0,
1848
        0,
1849
        0,
1850
        0,
1851
        0,
1852
        0,
1853
    }, // not used
1854
    {
1855
        0,
1856
        0,
1857
        0,
1858
        0,
1859
        0,
1860
        0,
1861
        0,
1862
        0,
1863
        0,
1864
        0,
1865
        0,
1866
        0,
1867
        0,
1868
        0,
1869
        0,
1870
        0,
1871
    }, // not used
1872
    {
1873
        1,
1874
        1,
1875
        1,
1876
        1,
1877
        0,
1878
        1,
1879
        1,
1880
        1,
1881
        0,
1882
        1,
1883
        0,
1884
        1,
1885
        1,
1886
        1,
1887
        0,
1888
        1,
1889
    },
1890
    {
1891
        1,
1892
        1,
1893
        1,
1894
        1,
1895
        0,
1896
        1,
1897
        1,
1898
        1,
1899
        1,
1900
        1,
1901
        0,
1902
        1,
1903
        0,
1904
        1,
1905
        0,
1906
        1,
1907
    },
1908
    {
1909
        0,
1910
        0,
1911
        0,
1912
        0,
1913
        0,
1914
        0,
1915
        0,
1916
        0,
1917
        0,
1918
        0,
1919
        0,
1920
        0,
1921
        0,
1922
        0,
1923
        0,
1924
        0,
1925
    }, // not used
1926
    {
1927
        0,
1928
        0,
1929
        0,
1930
        0,
1931
        0,
1932
        0,
1933
        0,
1934
        0,
1935
        0,
1936
        0,
1937
        0,
1938
        0,
1939
        0,
1940
        0,
1941
        0,
1942
        0,
1943
    }, // not used
1944
};
1945
1946
static const WedgeCodeType wedge_codebook_16_hgtw[16] = {
1947
    {WEDGE_OBLIQUE27, 4, 4},
1948
    {WEDGE_OBLIQUE63, 4, 4},
1949
    {WEDGE_OBLIQUE117, 4, 4},
1950
    {WEDGE_OBLIQUE153, 4, 4},
1951
    {WEDGE_HORIZONTAL, 4, 2},
1952
    {WEDGE_HORIZONTAL, 4, 4},
1953
    {WEDGE_HORIZONTAL, 4, 6},
1954
    {WEDGE_VERTICAL, 4, 4},
1955
    {WEDGE_OBLIQUE27, 4, 2},
1956
    {WEDGE_OBLIQUE27, 4, 6},
1957
    {WEDGE_OBLIQUE153, 4, 2},
1958
    {WEDGE_OBLIQUE153, 4, 6},
1959
    {WEDGE_OBLIQUE63, 2, 4},
1960
    {WEDGE_OBLIQUE63, 6, 4},
1961
    {WEDGE_OBLIQUE117, 2, 4},
1962
    {WEDGE_OBLIQUE117, 6, 4},
1963
};
1964
1965
static const WedgeCodeType wedge_codebook_16_hltw[16] = {
1966
    {WEDGE_OBLIQUE27, 4, 4},
1967
    {WEDGE_OBLIQUE63, 4, 4},
1968
    {WEDGE_OBLIQUE117, 4, 4},
1969
    {WEDGE_OBLIQUE153, 4, 4},
1970
    {WEDGE_VERTICAL, 2, 4},
1971
    {WEDGE_VERTICAL, 4, 4},
1972
    {WEDGE_VERTICAL, 6, 4},
1973
    {WEDGE_HORIZONTAL, 4, 4},
1974
    {WEDGE_OBLIQUE27, 4, 2},
1975
    {WEDGE_OBLIQUE27, 4, 6},
1976
    {WEDGE_OBLIQUE153, 4, 2},
1977
    {WEDGE_OBLIQUE153, 4, 6},
1978
    {WEDGE_OBLIQUE63, 2, 4},
1979
    {WEDGE_OBLIQUE63, 6, 4},
1980
    {WEDGE_OBLIQUE117, 2, 4},
1981
    {WEDGE_OBLIQUE117, 6, 4},
1982
};
1983
1984
static const WedgeCodeType wedge_codebook_16_heqw[16] = {
1985
    {WEDGE_OBLIQUE27, 4, 4},
1986
    {WEDGE_OBLIQUE63, 4, 4},
1987
    {WEDGE_OBLIQUE117, 4, 4},
1988
    {WEDGE_OBLIQUE153, 4, 4},
1989
    {WEDGE_HORIZONTAL, 4, 2},
1990
    {WEDGE_HORIZONTAL, 4, 6},
1991
    {WEDGE_VERTICAL, 2, 4},
1992
    {WEDGE_VERTICAL, 6, 4},
1993
    {WEDGE_OBLIQUE27, 4, 2},
1994
    {WEDGE_OBLIQUE27, 4, 6},
1995
    {WEDGE_OBLIQUE153, 4, 2},
1996
    {WEDGE_OBLIQUE153, 4, 6},
1997
    {WEDGE_OBLIQUE63, 2, 4},
1998
    {WEDGE_OBLIQUE63, 6, 4},
1999
    {WEDGE_OBLIQUE117, 2, 4},
2000
    {WEDGE_OBLIQUE117, 6, 4},
2001
};
2002
2003
static const WedgeParamsType wedge_params_lookup[BLOCK_SIZES_ALL] = {
2004
    {0, NULL, NULL, NULL},
2005
    {0, NULL, NULL, NULL},
2006
    {0, NULL, NULL, NULL},
2007
    {4, wedge_codebook_16_heqw, wedge_signflip_lookup[BLOCK_8X8], wedge_masks[BLOCK_8X8]},
2008
    {4, wedge_codebook_16_hgtw, wedge_signflip_lookup[BLOCK_8X16], wedge_masks[BLOCK_8X16]},
2009
    {4, wedge_codebook_16_hltw, wedge_signflip_lookup[BLOCK_16X8], wedge_masks[BLOCK_16X8]},
2010
    {4, wedge_codebook_16_heqw, wedge_signflip_lookup[BLOCK_16X16], wedge_masks[BLOCK_16X16]},
2011
    {4, wedge_codebook_16_hgtw, wedge_signflip_lookup[BLOCK_16X32], wedge_masks[BLOCK_16X32]},
2012
    {4, wedge_codebook_16_hltw, wedge_signflip_lookup[BLOCK_32X16], wedge_masks[BLOCK_32X16]},
2013
    {4, wedge_codebook_16_heqw, wedge_signflip_lookup[BLOCK_32X32], wedge_masks[BLOCK_32X32]},
2014
    {0, NULL, NULL, NULL},
2015
    {0, NULL, NULL, NULL},
2016
    {0, NULL, NULL, NULL},
2017
    {0, NULL, NULL, NULL},
2018
    {0, NULL, NULL, NULL},
2019
    {0, NULL, NULL, NULL},
2020
    {0, NULL, NULL, NULL},
2021
    {0, NULL, NULL, NULL},
2022
    {4, wedge_codebook_16_hgtw, wedge_signflip_lookup[BLOCK_8X32], wedge_masks[BLOCK_8X32]},
2023
    {4, wedge_codebook_16_hltw, wedge_signflip_lookup[BLOCK_32X8], wedge_masks[BLOCK_32X8]},
2024
    {0, NULL, NULL, NULL},
2025
    {0, NULL, NULL, NULL},
2026
};
2027
2028
0
int svt_aom_is_interintra_wedge_used(BlockSize bsize) {
2029
0
    return wedge_params_lookup[bsize].bits > 0;
2030
0
}
2031
2032
0
int32_t svt_aom_get_wedge_bits_lookup(BlockSize bsize) {
2033
0
    return wedge_params_lookup[bsize].bits;
2034
0
}
2035
2036
0
const uint8_t* svt_aom_get_contiguous_soft_mask(int wedge_index, int wedge_sign, BlockSize bsize) {
2037
0
    return wedge_params_lookup[bsize].masks[wedge_sign][wedge_index];
2038
0
}
2039
2040
static void aom_convolve_copy_c(const uint8_t* src, ptrdiff_t src_stride, uint8_t* dst, ptrdiff_t dst_stride,
2041
                                const int16_t* filter_x, int filter_x_stride, const int16_t* filter_y,
2042
288
                                int filter_y_stride, int w, int h) {
2043
288
    (void)filter_x;
2044
288
    (void)filter_x_stride;
2045
288
    (void)filter_y;
2046
288
    (void)filter_y_stride;
2047
2048
5.66k
    for (int r = h; r > 0; --r) {
2049
5.37k
        svt_memcpy(dst, src, w);
2050
5.37k
        src += src_stride;
2051
5.37k
        dst += dst_stride;
2052
5.37k
    }
2053
288
}
2054
2055
64
static void shift_copy(const uint8_t* src, uint8_t* dst, int shift, int width) {
2056
64
    if (shift >= 0) {
2057
33
        svt_memcpy(dst + shift, src, width - shift);
2058
33
        memset(dst, src[0], shift);
2059
33
    } else {
2060
31
        shift = -shift;
2061
31
        svt_memcpy(dst, src + shift, width - shift);
2062
31
        memset(dst + width - shift, src[width - 1], shift);
2063
31
    }
2064
64
}
2065
2066
0
int svt_aom_get_wedge_params_bits(BlockSize bsize) {
2067
0
    return wedge_params_lookup[bsize].bits;
2068
0
}
2069
2070
#endif // USE_PRECOMPUTED_WEDGE_MASK
2071
2072
// [negative][direction]
2073
DECLARE_ALIGNED(16, static uint8_t, wedge_mask_obl[2][WEDGE_DIRECTIONS][MASK_PRIMARY_SIZE * MASK_PRIMARY_SIZE]);
2074
2075
// 4 * MAX_WEDGE_SQUARE is an easy to compute and fairly tight upper bound
2076
// on the sum of all mask sizes up to an including MAX_WEDGE_SQUARE.
2077
DECLARE_ALIGNED(16, static uint8_t, wedge_mask_buf[2 * MAX_WEDGE_TYPES * 4 * MAX_WEDGE_SQUARE]);
2078
2079
1
static void init_wedge_primary_masks() {
2080
1
    const int w      = MASK_PRIMARY_SIZE;
2081
1
    const int h      = MASK_PRIMARY_SIZE;
2082
1
    const int stride = MASK_PRIMARY_STRIDE;
2083
    // Note: index [0] stores the primary, and [1] its complement.
2084
1
#if USE_PRECOMPUTED_WEDGE_MASK
2085
    // Generate prototype by shifting the primary
2086
1
    int shift = h / 4;
2087
33
    for (int i = 0; i < h; i += 2) {
2088
32
        shift_copy(
2089
32
            wedge_primary_oblique_even, &wedge_mask_obl[0][WEDGE_OBLIQUE63][i * stride], shift, MASK_PRIMARY_SIZE);
2090
32
        shift--;
2091
32
        shift_copy(
2092
32
            wedge_primary_oblique_odd, &wedge_mask_obl[0][WEDGE_OBLIQUE63][(i + 1) * stride], shift, MASK_PRIMARY_SIZE);
2093
32
        svt_memcpy(&wedge_mask_obl[0][WEDGE_VERTICAL][i * stride],
2094
32
                   wedge_primary_vertical,
2095
32
                   MASK_PRIMARY_SIZE * sizeof(wedge_primary_vertical[0]));
2096
32
        svt_memcpy(&wedge_mask_obl[0][WEDGE_VERTICAL][(i + 1) * stride],
2097
32
                   wedge_primary_vertical,
2098
32
                   MASK_PRIMARY_SIZE * sizeof(wedge_primary_vertical[0]));
2099
32
    }
2100
#else
2101
    static const double smoother_param = 2.85;
2102
    const int           a[2]           = {2, 1};
2103
    const double        asqrt          = sqrt(a[0] * a[0] + a[1] * a[1]);
2104
    for (int i = 0; i < h; i++) {
2105
        for (int j = 0; j < w; ++j) {
2106
            int       x                                        = (2 * j + 1 - w);
2107
            int       y                                        = (2 * i + 1 - h);
2108
            double    d                                        = (a[0] * x + a[1] * y) / asqrt;
2109
            const int msk                                      = (int)rint((1.0 + tanh(d / smoother_param)) * 32);
2110
            wedge_mask_obl[0][WEDGE_OBLIQUE63][i * stride + j] = msk;
2111
            const int mskx                                     = (int)rint((1.0 + tanh(x / smoother_param)) * 32);
2112
            wedge_mask_obl[0][WEDGE_VERTICAL][i * stride + j]  = mskx;
2113
        }
2114
    }
2115
#endif // USE_PRECOMPUTED_WEDGE_MASK
2116
65
    for (int i = 0; i < h; ++i) {
2117
4.16k
        for (int j = 0; j < w; ++j) {
2118
4.09k
            const int msk                                      = wedge_mask_obl[0][WEDGE_OBLIQUE63][i * stride + j];
2119
4.09k
            wedge_mask_obl[0][WEDGE_OBLIQUE27][j * stride + i] = msk;
2120
4.09k
            wedge_mask_obl[0][WEDGE_OBLIQUE117][i * stride + w - 1 - j] =
2121
4.09k
                wedge_mask_obl[0][WEDGE_OBLIQUE153][(w - 1 - j) * stride + i] = (1 << WEDGE_WEIGHT_BITS) - msk;
2122
4.09k
            wedge_mask_obl[1][WEDGE_OBLIQUE63][i * stride + j] = wedge_mask_obl[1][WEDGE_OBLIQUE27][j * stride + i] =
2123
4.09k
                (1 << WEDGE_WEIGHT_BITS) - msk;
2124
4.09k
            wedge_mask_obl[1][WEDGE_OBLIQUE117][i * stride + w - 1 - j] =
2125
4.09k
                wedge_mask_obl[1][WEDGE_OBLIQUE153][(w - 1 - j) * stride + i] = msk;
2126
4.09k
            const int mskx                                      = wedge_mask_obl[0][WEDGE_VERTICAL][i * stride + j];
2127
4.09k
            wedge_mask_obl[0][WEDGE_HORIZONTAL][j * stride + i] = mskx;
2128
4.09k
            wedge_mask_obl[1][WEDGE_VERTICAL][i * stride + j]   = wedge_mask_obl[1][WEDGE_HORIZONTAL][j * stride + i] =
2129
4.09k
                (1 << WEDGE_WEIGHT_BITS) - mskx;
2130
4.09k
        }
2131
64
    }
2132
1
}
2133
2134
#if !USE_PRECOMPUTED_WEDGE_SIGN
2135
// If the signs for the wedges for various BLOCK_SIZES are
2136
// inconsistent flip the sign flag. Do it only once for every
2137
// wedge codebook.
2138
static void init_wedge_signs() {
2139
    memset(wedge_signflip_lookup, 0, sizeof(wedge_signflip_lookup));
2140
    for (BlockSize bsize = BLOCK_4X4; bsize < BLOCK_SIZES_ALL; ++bsize) {
2141
        const int               bw           = block_size_wide[bsize];
2142
        const int               bh           = block_size_high[bsize];
2143
        const wedge_params_type wedge_params = wedge_params_lookup[bsize];
2144
        const int               wbits        = wedge_params.bits;
2145
        const int               wtypes       = 1 << wbits;
2146
2147
        if (wbits) {
2148
            for (int w = 0; w < wtypes; ++w) {
2149
                // Get the mask primary, i.e. index [0]
2150
                const uint8_t* mask = get_wedge_mask_inplace(w, 0, bsize);
2151
                int            avg  = 0;
2152
                for (int i = 0; i < bw; ++i) {
2153
                    avg += mask[i];
2154
                }
2155
                for (int i = 1; i < bh; ++i) {
2156
                    avg += mask[i * MASK_PRIMARY_STRIDE];
2157
                }
2158
                avg = (avg + (bw + bh - 1) / 2) / (bw + bh - 1);
2159
                // Default sign of this wedge is 1 if the average < 32, 0 otherwise.
2160
                // If default sign is 1:
2161
                //   If sign requested is 0, we need to flip the sign and return
2162
                //   the complement i.e. index [1] instead. If sign requested is 1
2163
                //   we need to flip the sign and return index [0] instead.
2164
                // If default sign is 0:
2165
                //   If sign requested is 0, we need to return index [0] the primary
2166
                //   if sign requested is 1, we need to return the complement index [1]
2167
                //   instead.
2168
                wedge_params.signflip[w] = (avg < 32);
2169
            }
2170
        }
2171
    }
2172
}
2173
#endif // !USE_PRECOMPUTED_WEDGE_SIGN
2174
2175
288
static const uint8_t* get_wedge_mask_inplace(int wedge_index, int neg, BlockSize bsize) {
2176
288
    const int bh = block_size_high[bsize];
2177
288
    const int bw = block_size_wide[bsize];
2178
2179
288
    assert(wedge_index >= 0 && wedge_index < (1 << svt_aom_get_wedge_bits_lookup(bsize)));
2180
288
    const WedgeCodeType* a = wedge_params_lookup[bsize].codebook + wedge_index;
2181
288
    int                  woff, hoff;
2182
288
    const uint8_t        wsignflip = wedge_params_lookup[bsize].signflip[wedge_index];
2183
2184
288
    woff = (a->x_offset * bw) >> 3;
2185
288
    hoff = (a->y_offset * bh) >> 3;
2186
288
    return wedge_mask_obl[neg ^ wsignflip][a->direction] + MASK_PRIMARY_STRIDE * (MASK_PRIMARY_SIZE / 2 - hoff) +
2187
288
        MASK_PRIMARY_SIZE / 2 - woff;
2188
288
}
2189
2190
1
static void init_wedge_masks() {
2191
1
    uint8_t* dst = wedge_mask_buf;
2192
1
    memset(wedge_masks, 0, sizeof(wedge_masks));
2193
23
    for (BlockSize bsize = BLOCK_4X4; bsize < BLOCK_SIZES_ALL; ++bsize) {
2194
22
        const int              bw           = block_size_wide[bsize];
2195
22
        const int              bh           = block_size_high[bsize];
2196
22
        const WedgeParamsType* wedge_params = &wedge_params_lookup[bsize];
2197
22
        const int              wbits        = wedge_params->bits;
2198
22
        const int              wtypes       = 1 << wbits;
2199
22
        if (wbits == 0) {
2200
13
            continue;
2201
13
        }
2202
153
        for (int w = 0; w < wtypes; ++w) {
2203
144
            const uint8_t* mask;
2204
144
            mask = get_wedge_mask_inplace(w, 0, bsize);
2205
144
            aom_convolve_copy_c(mask, MASK_PRIMARY_STRIDE, dst, bw, NULL, 0, NULL, 0, bw, bh);
2206
144
            wedge_params->masks[0][w] = dst;
2207
144
            dst += bw * bh;
2208
2209
144
            mask = get_wedge_mask_inplace(w, 1, bsize);
2210
144
            aom_convolve_copy_c(mask, MASK_PRIMARY_STRIDE, dst, bw, NULL, 0, NULL, 0, bw, bh);
2211
144
            wedge_params->masks[1][w] = dst;
2212
144
            dst += bw * bh;
2213
144
        }
2214
9
        assert(sizeof(wedge_mask_buf) >= (size_t)(dst - wedge_mask_buf));
2215
9
    }
2216
1
}
2217
2218
// Equation of line: f(x, y) = a[0]*(x - a[2]*w/8) + a[1]*(y - a[3]*h/8) = 0
2219
1
void svt_av1_init_wedge_masks(void) {
2220
1
    init_wedge_primary_masks();
2221
#if !USE_PRECOMPUTED_WEDGE_SIGN
2222
    init_wedge_signs();
2223
#endif // !USE_PRECOMPUTED_WEDGE_SIGN
2224
1
    init_wedge_masks();
2225
1
}
2226
2227
int svt_aom_is_masked_compound_type(COMPOUND_TYPE type);
2228
2229
/* clang-format off */
2230
static const uint8_t ii_weights1d[MAX_SB_SIZE] = {
2231
    60, 58, 56, 54, 52, 50, 48, 47, 45, 44, 42, 41, 39, 38, 37, 35, 34, 33, 32,
2232
    31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 22, 21, 20, 19, 19, 18, 18, 17, 16,
2233
    16, 15, 15, 14, 14, 13, 13, 12, 12, 12, 11, 11, 10, 10, 10,  9,  9,  9,  8,
2234
    8,  8,  8,  7,  7,  7,  7,  6,  6,  6,  6,  6,  5,  5,  5,  5,  5,  4,  4,
2235
    4,  4,  4,  4,  4,  4,  3,  3,  3,  3,  3,  3,  3,  3,  3,  2,  2,  2,  2,
2236
    2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  1,  1,  1,  1,  1,  1,  1,  1,
2237
    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1
2238
};
2239
static const uint8_t ii_size_scales[BLOCK_SIZES_ALL] = {
2240
    32, 16, 16, 16, 8, 8, 8, 4,
2241
    4,  4,  2,  2,  2, 1, 1, 1,
2242
    8,  8,  4,  4,  2, 2
2243
};
2244
/* clang-format on */
2245
2246
40
static void build_smooth_interintra_mask(uint8_t* mask, int stride, BlockSize plane_bsize, InterIntraMode mode) {
2247
40
    const int bw         = block_size_wide[plane_bsize];
2248
40
    const int bh         = block_size_high[plane_bsize];
2249
40
    const int size_scale = ii_size_scales[plane_bsize];
2250
2251
40
    switch (mode) {
2252
10
    case II_V_PRED:
2253
154
        for (int i = 0; i < bh; ++i) {
2254
144
            memset(mask, ii_weights1d[i * size_scale], bw * sizeof(mask[0]));
2255
144
            mask += stride;
2256
144
        }
2257
10
        break;
2258
2259
10
    case II_H_PRED:
2260
154
        for (int i = 0; i < bh; ++i) {
2261
2.84k
            for (int j = 0; j < bw; ++j) {
2262
2.70k
                mask[j] = ii_weights1d[j * size_scale];
2263
2.70k
            }
2264
144
            mask += stride;
2265
144
        }
2266
10
        break;
2267
2268
10
    case II_SMOOTH_PRED:
2269
154
        for (int i = 0; i < bh; ++i) {
2270
2.84k
            for (int j = 0; j < bw; ++j) {
2271
2.70k
                mask[j] = ii_weights1d[(i < j ? i : j) * size_scale];
2272
2.70k
            }
2273
144
            mask += stride;
2274
144
        }
2275
10
        break;
2276
2277
10
    case II_DC_PRED:
2278
10
    default:
2279
154
        for (int i = 0; i < bh; ++i) {
2280
144
            memset(mask, 32, bw * sizeof(mask[0]));
2281
144
            mask += stride;
2282
144
        }
2283
10
        break;
2284
40
    }
2285
40
}
2286
2287
// ii_masks stores the actual masks. We use smooth_ii_masks to access ii_masks so that we can index the array
2288
// directly with the bsize (BlockSize that would be passed when doing the prediction) without using the extra memory
2289
// to store empty, unused masks for the BLOCK_SIZES that don't allow inter-intra
2290
static uint8_t  ii_masks[BLOCK_32X32 - BLOCK_4X4 + 1][INTERINTRA_MODES][MAX_INTERINTRA_SB_SQUARE];
2291
static uint8_t* smooth_ii_masks[BLOCK_SIZES_ALL][INTERINTRA_MODES];
2292
2293
// Initialize the masks used for inter-intra compound blending. Inter-intra is allowed for 8x8-32x32 blocks, but
2294
// masks must be generated down to 4x4 because of chroma. The stride of each mask is the block width.
2295
1
void init_ii_masks(void) {
2296
1
    memset(smooth_ii_masks, 0 /*NULL*/, sizeof(smooth_ii_masks));
2297
11
    for (BlockSize bsize = BLOCK_4X4; bsize <= BLOCK_32X32; ++bsize) {
2298
10
        const int bw = block_size_wide[bsize];
2299
50
        for (InterIntraMode ii_mode = II_DC_PRED; ii_mode < INTERINTRA_MODES; ii_mode++) {
2300
40
            build_smooth_interintra_mask(ii_masks[bsize - BLOCK_4X4][ii_mode], bw, bsize, ii_mode);
2301
40
            smooth_ii_masks[bsize][ii_mode] = ii_masks[bsize - BLOCK_4X4][ii_mode];
2302
40
        }
2303
10
    }
2304
1
}
2305
2306
// mask stride is block width
2307
0
static uint8_t* get_ii_mask(BlockSize bsize, InterIntraMode ii_mode) {
2308
0
    return smooth_ii_masks[bsize][ii_mode];
2309
0
}
2310
2311
void svt_aom_combine_interintra_highbd(InterIntraMode mode, uint8_t use_wedge_interintra, uint8_t wedge_index,
2312
                                       uint8_t wedge_sign, BlockSize bsize, BlockSize plane_bsize, uint8_t* comppred8,
2313
                                       int compstride, const uint8_t* interpred8, int interstride,
2314
0
                                       const uint8_t* intrapred8, int intrastride, int bd) {
2315
0
    const int bw = block_size_wide[plane_bsize];
2316
0
    const int bh = block_size_high[plane_bsize];
2317
2318
0
    if (use_wedge_interintra) {
2319
0
        if (svt_aom_is_interintra_wedge_used(bsize)) {
2320
0
            const uint8_t* mask = svt_aom_get_contiguous_soft_mask(wedge_index, wedge_sign, bsize);
2321
0
            const int      subh = 2 * mi_size_high[bsize] == bh;
2322
0
            const int      subw = 2 * mi_size_wide[bsize] == bw;
2323
0
            svt_aom_highbd_blend_a64_mask(comppred8,
2324
0
                                          compstride,
2325
0
                                          intrapred8,
2326
0
                                          intrastride,
2327
0
                                          interpred8,
2328
0
                                          interstride,
2329
0
                                          mask,
2330
0
                                          block_size_wide[bsize],
2331
0
                                          bw,
2332
0
                                          bh,
2333
0
                                          subw,
2334
0
                                          subh,
2335
0
                                          bd);
2336
0
        }
2337
0
        return;
2338
0
    }
2339
2340
0
    uint8_t* mask = get_ii_mask(plane_bsize, mode);
2341
0
    svt_aom_highbd_blend_a64_mask(
2342
0
        comppred8, compstride, intrapred8, intrastride, interpred8, interstride, mask, bw, bw, bh, 0, 0, bd);
2343
0
}
2344
2345
static const uint8_t* av1_get_compound_type_mask(const InterInterCompoundData* const comp_data, uint8_t* seg_mask,
2346
0
                                                 BlockSize bsize) {
2347
0
    assert(svt_aom_is_masked_compound_type(comp_data->type));
2348
0
    (void)bsize;
2349
0
    switch (comp_data->type) {
2350
0
    case COMPOUND_WEDGE:
2351
0
        return svt_aom_get_contiguous_soft_mask(comp_data->wedge_index, comp_data->wedge_sign, bsize);
2352
0
    case COMPOUND_DIFFWTD:
2353
0
        return seg_mask;
2354
0
    default:
2355
0
        assert(0);
2356
0
        return NULL;
2357
0
    }
2358
0
}
2359
2360
void svt_aom_build_masked_compound_no_round(uint8_t* dst, int dst_stride, const CONV_BUF_TYPE* src0, int src0_stride,
2361
                                            const CONV_BUF_TYPE* src1, int src1_stride,
2362
                                            const InterInterCompoundData* const comp_data, uint8_t* seg_mask,
2363
                                            BlockSize bsize, int h, int w, ConvolveParams* conv_params,
2364
0
                                            uint8_t bit_depth, bool is_16bit) {
2365
    // Derive subsampling from h and w passed in. May be refactored to
2366
    // pass in subsampling factors directly.
2367
0
    const int      subh = (2 << mi_size_high_log2[bsize]) == h;
2368
0
    const int      subw = (2 << mi_size_wide_log2[bsize]) == w;
2369
0
    const uint8_t* mask = av1_get_compound_type_mask(comp_data, seg_mask, bsize);
2370
2371
0
    if (is_16bit) {
2372
0
        svt_aom_highbd_blend_a64_d16_mask(dst,
2373
0
                                          dst_stride,
2374
0
                                          src0,
2375
0
                                          src0_stride,
2376
0
                                          src1,
2377
0
                                          src1_stride,
2378
0
                                          mask,
2379
0
                                          block_size_wide[bsize],
2380
0
                                          w,
2381
0
                                          h,
2382
0
                                          subw,
2383
0
                                          subh,
2384
0
                                          conv_params,
2385
0
                                          bit_depth);
2386
0
    } else {
2387
0
        svt_aom_lowbd_blend_a64_d16_mask(dst,
2388
0
                                         dst_stride,
2389
0
                                         src0,
2390
0
                                         src0_stride,
2391
0
                                         src1,
2392
0
                                         src1_stride,
2393
0
                                         mask,
2394
0
                                         block_size_wide[bsize],
2395
0
                                         w,
2396
0
                                         h,
2397
0
                                         subw,
2398
0
                                         subh,
2399
0
                                         conv_params);
2400
0
    }
2401
0
}
2402
2403
0
void svt_aom_find_ref_dv(Mv* ref_dv, const TileInfo* const tile, int mib_size, int mi_row, int mi_col) {
2404
0
    (void)mi_col;
2405
0
    if (mi_row - mib_size < tile->mi_row_start) {
2406
0
        ref_dv->y = 0;
2407
0
        ref_dv->x = -MI_SIZE * mib_size - INTRABC_DELAY_PIXELS;
2408
0
    } else {
2409
0
        ref_dv->y = -MI_SIZE * mib_size;
2410
0
        ref_dv->x = 0;
2411
0
    }
2412
0
    ref_dv->y *= 8;
2413
0
    ref_dv->x *= 8;
2414
0
}
2415
#if CONFIG_ENABLE_OBMC
2416
0
int svt_av1_skip_u4x4_pred_in_obmc(BlockSize bsize, int dir, int subsampling_x, int subsampling_y) {
2417
0
    assert(is_motion_variation_allowed_bsize(bsize));
2418
2419
0
    const BlockSize bsize_plane = get_plane_block_size(bsize, subsampling_x, subsampling_y);
2420
0
    switch (bsize_plane) {
2421
#if DISABLE_CHROMA_U8X8_OBMC
2422
    case BLOCK_4X4:
2423
    case BLOCK_8X4:
2424
    case BLOCK_4X8:
2425
        return 1;
2426
        break;
2427
#else
2428
0
    case BLOCK_4X4:
2429
0
    case BLOCK_8X4:
2430
0
    case BLOCK_4X8:
2431
0
        return dir == 0;
2432
0
        break;
2433
0
#endif
2434
0
    default:
2435
0
        return 0;
2436
0
    }
2437
0
}
2438
#endif
2439
2440
0
#define MAX_MASK_VALUE (1 << WEDGE_WEIGHT_BITS)
2441
2442
/**
2443
 * Computes SSE of a compound predictor constructed from 2 fundamental
2444
 * predictors p0 and p1 using blending with mask.
2445
 *
2446
 * r1:  Residuals of p1.
2447
 *      (source - p1)
2448
 * d:   Difference of p1 and p0.
2449
 *      (p1 - p0)
2450
 * m:   The blending mask
2451
 * N:   Number of pixels
2452
 *
2453
 * 'r1', 'd', and 'm' are contiguous.
2454
 *
2455
 * Computes:
2456
 *  Sum((MAX_MASK_VALUE*r1 + mask*d)**2), which is equivalent to:
2457
 *  Sum((mask*r0 + (MAX_MASK_VALUE-mask)*r1)**2),
2458
 *    where r0 is (source - p0), and r1 is (source - p1), which is in turn
2459
 *    is equivalent to:
2460
 *  Sum((source*MAX_MASK_VALUE - (mask*p0 + (MAX_MASK_VALUE-mask)*p1))**2),
2461
 *    which is the SSE of the residuals of the compound predictor scaled up by
2462
 *    MAX_MASK_VALUE**2.
2463
 *
2464
 * Note that we clamp the partial term in the loop to 16 bits signed. This is
2465
 * to facilitate equivalent SIMD implementation. It should have no effect if
2466
 * residuals are within 16 - WEDGE_WEIGHT_BITS (=10) signed, which always
2467
 * holds for 8 bit input, and on real input, it should hold practically always,
2468
 * as residuals are expected to be small.
2469
 */
2470
0
uint64_t svt_av1_wedge_sse_from_residuals_c(const int16_t* r1, const int16_t* d, const uint8_t* m, int N) {
2471
0
    uint64_t csse = 0;
2472
2473
0
    for (int i = 0; i < N; i++) {
2474
0
        int32_t t = MAX_MASK_VALUE * r1[i] + m[i] * d[i];
2475
0
        t         = clamp(t, INT16_MIN, INT16_MAX);
2476
0
        csse += t * t;
2477
0
    }
2478
0
    return ROUND_POWER_OF_TWO(csse, 2 * WEDGE_WEIGHT_BITS);
2479
0
}
2480
2481
void svt_aom_combine_interintra(InterIntraMode mode, int8_t use_wedge_interintra, int wedge_index, int wedge_sign,
2482
                                BlockSize bsize, BlockSize plane_bsize, uint8_t* comppred, int compstride,
2483
0
                                const uint8_t* interpred, int interstride, const uint8_t* intrapred, int intrastride) {
2484
0
    const int bw = block_size_wide[plane_bsize];
2485
0
    const int bh = block_size_high[plane_bsize];
2486
2487
0
    if (use_wedge_interintra) {
2488
0
        if (svt_aom_is_interintra_wedge_used(bsize)) {
2489
0
            const uint8_t* mask = svt_aom_get_contiguous_soft_mask(wedge_index, wedge_sign, bsize);
2490
0
            const int      subw = 2 * mi_size_wide[bsize] == bw;
2491
0
            const int      subh = 2 * mi_size_high[bsize] == bh;
2492
0
            svt_aom_blend_a64_mask(comppred,
2493
0
                                   compstride,
2494
0
                                   intrapred,
2495
0
                                   intrastride,
2496
0
                                   interpred,
2497
0
                                   interstride,
2498
0
                                   mask,
2499
0
                                   block_size_wide[bsize],
2500
0
                                   bw,
2501
0
                                   bh,
2502
0
                                   subw,
2503
0
                                   subh);
2504
0
        }
2505
0
        return;
2506
0
    } else {
2507
0
        uint8_t* mask = get_ii_mask(plane_bsize, mode);
2508
0
        svt_aom_blend_a64_mask(
2509
0
            comppred, compstride, intrapred, intrastride, interpred, interstride, mask, bw, bw, bh, 0, 0);
2510
0
    }
2511
0
}
2512
2513
void svt_aom_highbd_blend_a64_hmask_16bit_c(uint16_t* dst, uint32_t dst_stride, const uint16_t* src0,
2514
                                            uint32_t src0_stride, const uint16_t* src1, uint32_t src1_stride,
2515
0
                                            const uint8_t* mask, int w, int h, int bd) {
2516
0
    (void)bd;
2517
2518
0
    assert(IMPLIES(src0 == dst, src0_stride == dst_stride));
2519
0
    assert(IMPLIES(src1 == dst, src1_stride == dst_stride));
2520
2521
0
    assert(h >= 1);
2522
0
    assert(w >= 1);
2523
0
    assert(IS_POWER_OF_TWO(h));
2524
0
    assert(IS_POWER_OF_TWO(w));
2525
2526
0
    assert(bd == 8 || bd == 10 || bd == 12);
2527
2528
0
    for (int i = 0; i < h; ++i) {
2529
0
        for (int j = 0; j < w; ++j) {
2530
0
            dst[i * dst_stride + j] = AOM_BLEND_A64(mask[j], src0[i * src0_stride + j], src1[i * src1_stride + j]);
2531
0
        }
2532
0
    }
2533
0
}
2534
2535
0
uint64_t svt_aom_sum_squares_i16_c(const int16_t* src, uint32_t n) {
2536
0
    uint64_t ss = 0;
2537
0
    do {
2538
0
        const int16_t v = *src++;
2539
0
        ss += v * v;
2540
0
    } while (--n);
2541
2542
0
    return ss;
2543
0
}
2544
2545
// obmc_mask_N[overlap_position]
2546
static const uint8_t obmc_mask_1[1]                      = {64};
2547
DECLARE_ALIGNED(2, static const uint8_t, obmc_mask_2[2]) = {45, 64};
2548
2549
DECLARE_ALIGNED(4, static const uint8_t, obmc_mask_4[4]) = {39, 50, 59, 64};
2550
2551
static const uint8_t obmc_mask_8[8] = {36, 42, 48, 53, 57, 61, 64, 64};
2552
2553
static const uint8_t obmc_mask_16[16] = {34, 37, 40, 43, 46, 49, 52, 54, 56, 58, 60, 61, 64, 64, 64, 64};
2554
2555
static const uint8_t obmc_mask_32[32] = {33, 35, 36, 38, 40, 41, 43, 44, 45, 47, 48, 50, 51, 52, 53, 55,
2556
                                         56, 57, 58, 59, 60, 60, 61, 62, 64, 64, 64, 64, 64, 64, 64, 64};
2557
2558
0
const uint8_t* svt_av1_get_obmc_mask(int length) {
2559
0
    switch (length) {
2560
0
    case 1:
2561
0
        return obmc_mask_1;
2562
0
    case 2:
2563
0
        return obmc_mask_2;
2564
0
    case 4:
2565
0
        return obmc_mask_4;
2566
0
    case 8:
2567
0
        return obmc_mask_8;
2568
0
    case 16:
2569
0
        return obmc_mask_16;
2570
0
    case 32:
2571
0
        return obmc_mask_32;
2572
0
    default:
2573
0
        assert(0);
2574
0
        return NULL;
2575
0
    }
2576
0
}
2577
2578
0
int16_t svt_aom_mode_context_analyzer(int16_t mode_context, const MvReferenceFrame* const rf) {
2579
0
    static unsigned svt_aom_compound_mode_ctx_map[3][COMP_NEWMV_CTXS] = {
2580
0
        {0, 1, 1, 1, 1},
2581
0
        {1, 2, 3, 4, 4},
2582
0
        {4, 4, 5, 6, 7},
2583
0
    };
2584
2585
0
    if (rf[1] <= INTRA_FRAME) {
2586
0
        return mode_context;
2587
0
    }
2588
2589
0
    const unsigned newmv_ctx = mode_context & NEWMV_CTX_MASK;
2590
0
    const unsigned refmv_ctx = (mode_context >> REFMV_OFFSET) & REFMV_CTX_MASK;
2591
0
    assert((refmv_ctx >> 1) < 3);
2592
0
    const unsigned comp_ctx = svt_aom_compound_mode_ctx_map[refmv_ctx >> 1][AOMMIN(newmv_ctx, COMP_NEWMV_CTXS - 1)];
2593
0
    return comp_ctx;
2594
0
}