Coverage Report

Created: 2026-07-30 06:27

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