Coverage Report

Created: 2026-05-16 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ffmpeg/libavcodec/vvc/mvs.c
Line
Count
Source
1
/*
2
 * VVC motion vector decoder
3
 *
4
 * Copyright (C) 2023 Nuo Mi
5
 * Copyright (C) 2022 Xu Mu
6
 * This file is part of FFmpeg.
7
 *
8
 * FFmpeg is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * FFmpeg is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with FFmpeg; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22
23
#include "ctu.h"
24
#include "data.h"
25
#include "refs.h"
26
#include "mvs.h"
27
28
89.6k
#define IS_SAME_MV(a, b) (AV_RN64A(a) == AV_RN64A(b))
29
30
//check if the two luma locations belong to the same motion estimation region
31
static av_always_inline int is_same_mer(const VVCFrameContext *fc, const int xN, const int yN, const int xP, const int yP)
32
42.4k
{
33
42.4k
    const uint8_t plevel = fc->ps.sps->log2_parallel_merge_level;
34
35
42.4k
    return xN >> plevel == xP >> plevel &&
36
871
           yN >> plevel == yP >> plevel;
37
42.4k
}
38
39
//return true if we have same mvs and ref_idxs
40
static av_always_inline int compare_mv_ref_idx(const MvField *n, const MvField *o)
41
87.2k
{
42
87.2k
    if (!o || n->pred_flag != o->pred_flag)
43
21.8k
        return 0;
44
157k
    for (int i = 0; i < 2; i++) {
45
111k
        PredFlag mask = i + 1;
46
111k
        if (n->pred_flag & mask) {
47
66.5k
            const int same_ref_idx = n->ref_idx[i] == o->ref_idx[i];
48
66.5k
            const int same_mv = IS_SAME_MV(n->mv + i, o->mv + i);
49
66.5k
            if (!same_ref_idx || !same_mv)
50
20.0k
                return 0;
51
66.5k
        }
52
111k
    }
53
45.2k
    return 1;
54
65.3k
}
55
56
// 8.5.2.15 Temporal motion buffer compression process for collocated motion vectors
57
static av_always_inline void mv_compression(Mv *motion)
58
2.64k
{
59
2.64k
    int mv[2] = {motion->x, motion->y};
60
7.92k
    for (int i = 0; i < 2; i++) {
61
5.28k
        const int s = mv[i] >> 17;
62
5.28k
        const int f = av_log2((mv[i] ^ s) | 31) - 4;
63
5.28k
        const int mask  = (-1 * (1 << f)) >> 1;
64
5.28k
        const int round = (1 << f) >> 2;
65
5.28k
        mv[i] = (mv[i] + round) & mask;
66
5.28k
    }
67
2.64k
    motion->x = mv[0];
68
2.64k
    motion->y = mv[1];
69
2.64k
}
70
71
void ff_vvc_mv_scale(Mv *dst, const Mv *src, int td, int tb)
72
6.96k
{
73
6.96k
    int tx, scale_factor;
74
75
6.96k
    td = av_clip_int8(td);
76
6.96k
    tb = av_clip_int8(tb);
77
6.96k
    tx = (0x4000 + (abs(td) >> 1)) / td;
78
6.96k
    scale_factor = av_clip_intp2((tb * tx + 32) >> 6, 12);
79
6.96k
    dst->x = av_clip_intp2((scale_factor * src->x + 127 +
80
6.96k
                           (scale_factor * src->x < 0)) >> 8, 17);
81
6.96k
    dst->y = av_clip_intp2((scale_factor * src->y + 127 +
82
6.96k
                           (scale_factor * src->y < 0)) >> 8, 17);
83
6.96k
}
84
85
//part of 8.5.2.12 Derivation process for collocated motion vectors
86
static int check_mvset(Mv *mvLXCol, Mv *mvCol,
87
                       int colPic, int poc,
88
                       const RefPicList *refPicList, int X, int refIdxLx,
89
                       const RefPicList *refPicList_col, int listCol, int refidxCol)
90
2.65k
{
91
2.65k
    int cur_lt = refPicList[X].refs[refIdxLx].is_lt;
92
2.65k
    int col_lt = refPicList_col[listCol].refs[refidxCol].is_lt;
93
2.65k
    int col_poc_diff, cur_poc_diff;
94
95
2.65k
    if (cur_lt != col_lt) {
96
19
        mvLXCol->x = 0;
97
19
        mvLXCol->y = 0;
98
19
        return 0;
99
19
    }
100
101
2.64k
    col_poc_diff = colPic - refPicList_col[listCol].refs[refidxCol].poc;
102
2.64k
    cur_poc_diff = poc    - refPicList[X].refs[refIdxLx].poc;
103
104
2.64k
    mv_compression(mvCol);
105
2.64k
    if (cur_lt || col_poc_diff == cur_poc_diff) {
106
806
        mvLXCol->x = av_clip_intp2(mvCol->x, 17);
107
806
        mvLXCol->y = av_clip_intp2(mvCol->y, 17);
108
1.83k
    } else {
109
1.83k
        ff_vvc_mv_scale(mvLXCol, mvCol, col_poc_diff, cur_poc_diff);
110
1.83k
    }
111
2.64k
    return 1;
112
2.65k
}
113
114
#define CHECK_MVSET(l)                                          \
115
2.65k
    check_mvset(mvLXCol, temp_col.mv + l,                       \
116
2.65k
                colPic, fc->ps.ph.poc,                          \
117
2.65k
                refPicList, X, refIdxLx,                        \
118
2.65k
                refPicList_col, L ## l, temp_col.ref_idx[l])
119
120
//derive NoBackwardPredFlag
121
int ff_vvc_no_backward_pred_flag(const VVCLocalContext *lc)
122
2.46k
{
123
2.46k
    int check_diffpicount = 0;
124
2.46k
    int i, j;
125
2.46k
    const RefPicList *rpl = lc->sc->rpl;
126
127
7.38k
    for (j = 0; j < 2; j++) {
128
13.3k
        for (i = 0; i < lc->sc->sh.r->num_ref_idx_active[j]; i++) {
129
9.77k
            if (rpl[j].refs[i].poc > lc->fc->ps.ph.poc) {
130
1.39k
                check_diffpicount++;
131
1.39k
                break;
132
1.39k
            }
133
9.77k
        }
134
4.92k
    }
135
2.46k
    return !check_diffpicount;
136
2.46k
}
137
138
//8.5.2.12 Derivation process for collocated motion vectors
139
static int derive_temporal_colocated_mvs(const VVCLocalContext *lc, MvField temp_col,
140
                                         int refIdxLx, Mv *mvLXCol, int X,
141
                                         int colPic, const RefPicList *refPicList_col, int sb_flag)
142
40.2k
{
143
40.2k
    const VVCFrameContext *fc   = lc->fc;
144
40.2k
    const SliceContext *sc      = lc->sc;
145
40.2k
    RefPicList* refPicList      = sc->rpl;
146
147
40.2k
    if (temp_col.pred_flag == PF_INTRA ||
148
2.67k
        temp_col.pred_flag == PF_IBC   ||
149
2.66k
        temp_col.pred_flag == PF_PLT)
150
37.6k
        return 0;
151
152
2.66k
    if (sb_flag){
153
100
        if (X == 0) {
154
50
            if (temp_col.pred_flag & PF_L0)
155
44
                return CHECK_MVSET(0);
156
6
            else if (ff_vvc_no_backward_pred_flag(lc) && (temp_col.pred_flag & PF_L1))
157
2
                return CHECK_MVSET(1);
158
50
        } else {
159
50
            if (temp_col.pred_flag & PF_L1)
160
42
                return CHECK_MVSET(1);
161
8
            else if (ff_vvc_no_backward_pred_flag(lc) && (temp_col.pred_flag & PF_L0))
162
4
                return CHECK_MVSET(0);
163
50
        }
164
2.56k
    } else {
165
2.56k
        if (!(temp_col.pred_flag & PF_L0))
166
5
            return CHECK_MVSET(1);
167
2.56k
        else if (temp_col.pred_flag == PF_L0)
168
113
            return CHECK_MVSET(0);
169
2.44k
        else if (temp_col.pred_flag == PF_BI) {
170
2.44k
            if (ff_vvc_no_backward_pred_flag(lc)) {
171
1.07k
                if (X == 0)
172
544
                    return CHECK_MVSET(0);
173
530
                else
174
530
                    return CHECK_MVSET(1);
175
1.37k
            } else {
176
1.37k
                if (!lc->sc->sh.r->sh_collocated_from_l0_flag)
177
67
                    return CHECK_MVSET(0);
178
1.30k
                else
179
1.30k
                    return CHECK_MVSET(1);
180
1.37k
            }
181
2.44k
        }
182
2.56k
    }
183
8
    return 0;
184
2.66k
}
185
186
#define TAB_MVF(x, y)                                                   \
187
145M
    tab_mvf[((y) >> MIN_PU_LOG2) * min_pu_width + ((x) >> MIN_PU_LOG2)]
188
189
#define TAB_MVF_PU(v)                                                   \
190
    TAB_MVF(x ## v, y ## v)
191
192
#define TAB_CP_MV(lx, x, y)                                              \
193
0
    fc->tab.cp_mv[lx][((((y) >> min_cb_log2_size) * min_cb_width + ((x) >> min_cb_log2_size)) ) * MAX_CONTROL_POINTS]
194
195
196
#define DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag)                          \
197
40.2k
    derive_temporal_colocated_mvs(lc, temp_col,                          \
198
40.2k
                                  refIdxLx, mvLXCol, X, colPic,         \
199
40.2k
                                  ff_vvc_get_ref_list(fc, ref, x, y), sb_flag)
200
201
//8.5.2.11 Derivation process for temporal luma motion vector prediction
202
static int temporal_luma_motion_vector(const VVCLocalContext *lc,
203
    const int refIdxLx, Mv *mvLXCol, const int X, int check_center, int sb_flag)
204
96.1k
{
205
96.1k
    const VVCFrameContext *fc = lc->fc;
206
96.1k
    const VVCSPS *sps         = fc->ps.sps;
207
96.1k
    const VVCPPS *pps         = fc->ps.pps;
208
96.1k
    const CodingUnit *cu      = lc->cu;
209
96.1k
    const int subpic_idx      = lc->sc->sh.r->curr_subpic_idx;
210
96.1k
    int x, y, x_end, y_end, colPic, availableFlagLXCol = 0;
211
96.1k
    int min_pu_width = fc->ps.pps->min_pu_width;
212
96.1k
    VVCFrame *ref = fc->ref->collocated_ref;
213
96.1k
    MvField *tab_mvf;
214
96.1k
    MvField temp_col;
215
216
96.1k
    if (!ref) {
217
48.5k
        memset(mvLXCol, 0, sizeof(*mvLXCol));
218
48.5k
        return 0;
219
48.5k
    }
220
221
47.6k
    if (!fc->ps.ph.r->ph_temporal_mvp_enabled_flag || (cu->cb_width * cu->cb_height <= 32))
222
4.82k
        return 0;
223
224
42.8k
    tab_mvf = ref->tab_dmvr_mvf;
225
42.8k
    colPic  = ref->poc;
226
227
    //bottom right collocated motion vector
228
42.8k
    x = cu->x0 + cu->cb_width;
229
42.8k
    y = cu->y0 + cu->cb_height;
230
231
42.8k
    x_end = pps->subpic_x[subpic_idx] + pps->subpic_width[subpic_idx];
232
42.8k
    y_end = pps->subpic_y[subpic_idx] + pps->subpic_height[subpic_idx];
233
234
42.8k
    if (tab_mvf &&
235
42.8k
        (cu->y0 >> sps->ctb_log2_size_y) == (y >> sps->ctb_log2_size_y) &&
236
42.8k
        x < x_end && y < y_end) {
237
0
        x                 &= ~7;
238
0
        y                 &= ~7;
239
0
        temp_col           = TAB_MVF(x, y);
240
0
        availableFlagLXCol = DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag);
241
0
    }
242
42.8k
    if (check_center) {
243
        // derive center collocated motion vector
244
40.0k
        if (tab_mvf && !availableFlagLXCol) {
245
40.0k
            x                  = cu->x0 + (cu->cb_width >> 1);
246
40.0k
            y                  = cu->y0 + (cu->cb_height >> 1);
247
40.0k
            x                 &= ~7;
248
40.0k
            y                 &= ~7;
249
40.0k
            temp_col           = TAB_MVF(x, y);
250
40.0k
            availableFlagLXCol = DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag);
251
40.0k
        }
252
40.0k
    }
253
42.8k
    return availableFlagLXCol;
254
47.6k
}
255
256
void ff_vvc_set_mvf(const VVCLocalContext *lc, const int x0, const int y0, const int w, const int h, const MvField *mvf)
257
476k
{
258
476k
    const VVCFrameContext *fc   = lc->fc;
259
476k
    MvField *tab_mvf            = fc->tab.mvf;
260
476k
    const int min_pu_width      = fc->ps.pps->min_pu_width;
261
476k
    const int min_pu_size       = 1 << MIN_PU_LOG2;
262
1.13M
    for (int dy = 0; dy < h; dy += min_pu_size) {
263
2.42M
        for (int dx = 0; dx < w; dx += min_pu_size) {
264
1.76M
            const int x = x0 + dx;
265
1.76M
            const int y = y0 + dy;
266
1.76M
            TAB_MVF(x, y) = *mvf;
267
1.76M
        }
268
656k
    }
269
476k
}
270
271
void ff_vvc_set_intra_mvf(const VVCLocalContext *lc, const bool dmvr, const PredFlag pf, const bool ciip_flag)
272
7.60M
{
273
7.60M
    const VVCFrameContext *fc   = lc->fc;
274
7.60M
    const CodingUnit *cu        = lc->cu;
275
7.60M
    MvField *tab_mvf            = dmvr ? fc->ref->tab_dmvr_mvf : fc->tab.mvf;
276
7.60M
    const int min_pu_width      = fc->ps.pps->min_pu_width;
277
7.60M
    const int min_pu_size       = 1 << MIN_PU_LOG2;
278
29.8M
    for (int dy = 0; dy < cu->cb_height; dy += min_pu_size) {
279
166M
        for (int dx = 0; dx < cu->cb_width; dx += min_pu_size) {
280
143M
            const int x = cu->x0 + dx;
281
143M
            const int y = cu->y0 + dy;
282
143M
            MvField *mv = &TAB_MVF(x, y);
283
284
143M
            mv->pred_flag = pf;
285
143M
            mv->ciip_flag = ciip_flag;
286
143M
        }
287
22.2M
    }
288
7.60M
}
289
290
//cbProfFlagLX from 8.5.5.9 Derivation process for motion vector arrays from affine control point motion vectors
291
static int derive_cb_prof_flag_lx(const VVCLocalContext *lc, const PredictionUnit* pu, int lx, int is_fallback)
292
7.60k
{
293
7.60k
    const MotionInfo* mi    = &pu->mi;
294
7.60k
    const Mv* cp_mv         = &mi->mv[lx][0];
295
7.60k
    if (lc->fc->ps.ph.r->ph_prof_disabled_flag || is_fallback)
296
6.68k
        return 0;
297
916
    if (mi->motion_model_idc == MOTION_4_PARAMS_AFFINE) {
298
916
        if (IS_SAME_MV(cp_mv, cp_mv + 1))
299
916
            return 0;
300
916
    }
301
0
    if (mi->motion_model_idc == MOTION_6_PARAMS_AFFINE) {
302
0
        if (IS_SAME_MV(cp_mv, cp_mv + 1) && IS_SAME_MV(cp_mv, cp_mv + 2))
303
0
            return 0;
304
0
    }
305
0
    if (lc->sc->rpl[lx].refs[mi->ref_idx[lx]].is_scaled)
306
0
        return 0;
307
0
    return 1;
308
0
}
309
310
typedef struct SubblockParams {
311
    int d_hor_x;
312
    int d_ver_x;
313
    int d_hor_y;
314
    int d_ver_y;
315
    int mv_scale_hor;
316
    int mv_scale_ver;
317
    int is_fallback;
318
319
    int cb_width;
320
    int cb_height;
321
} SubblockParams;
322
323
static int is_fallback_mode(const SubblockParams *sp, const PredFlag pred_flag)
324
7.60k
{
325
7.60k
    const int a = 4 * (2048 + sp->d_hor_x);
326
7.60k
    const int b = 4 * sp->d_hor_y;
327
7.60k
    const int c = 4 * (2048 + sp->d_ver_y);
328
7.60k
    const int d = 4 * sp->d_ver_x;
329
7.60k
    if (pred_flag == PF_BI) {
330
7.11k
        const int max_w4 = FFMAX(0, FFMAX(a, FFMAX(b, a + b)));
331
7.11k
        const int min_w4 = FFMIN(0, FFMIN(a, FFMIN(b, a + b)));
332
7.11k
        const int max_h4 = FFMAX(0, FFMAX(c, FFMAX(d, c + d)));
333
7.11k
        const int min_h4 = FFMIN(0, FFMIN(c, FFMIN(d, c + d)));
334
7.11k
        const int bx_wx4 = ((max_w4 - min_w4) >> 11) + 9;
335
7.11k
        const int bx_hx4 = ((max_h4 - min_h4) >> 11) + 9;
336
7.11k
        return bx_wx4 * bx_hx4 > 225;
337
7.11k
    } else {
338
485
        const int bx_wxh = (FFABS(a) >> 11) + 9;
339
485
        const int bx_hxh = (FFABS(d) >> 11) + 9;
340
485
        const int bx_wxv = (FFABS(b) >> 11) + 9;
341
485
        const int bx_hxv = (FFABS(c) >> 11) + 9;
342
485
        if (bx_wxh * bx_hxh <= 165 && bx_wxv * bx_hxv <= 165)
343
485
            return 0;
344
485
    }
345
0
    return 1;
346
7.60k
}
347
348
static void init_subblock_params(SubblockParams *sp, const MotionInfo* mi,
349
    const int cb_width, const int cb_height, const int lx)
350
7.60k
{
351
7.60k
    const int log2_cbw  = av_log2(cb_width);
352
7.60k
    const int log2_cbh  = av_log2(cb_height);
353
7.60k
    const Mv* cp_mv     = mi->mv[lx];
354
7.60k
    const int num_cp_mv = mi->motion_model_idc + 1;
355
7.60k
    sp->d_hor_x = (cp_mv[1].x - cp_mv[0].x) * (1 << (MAX_CU_DEPTH - log2_cbw));
356
7.60k
    sp->d_ver_x = (cp_mv[1].y - cp_mv[0].y) * (1 << (MAX_CU_DEPTH - log2_cbw));
357
7.60k
    if (num_cp_mv == 3) {
358
0
        sp->d_hor_y = (cp_mv[2].x - cp_mv[0].x) * (1 << (MAX_CU_DEPTH - log2_cbh));
359
0
        sp->d_ver_y = (cp_mv[2].y - cp_mv[0].y) * (1 << (MAX_CU_DEPTH - log2_cbh));
360
7.60k
    } else {
361
7.60k
        sp->d_hor_y = -sp->d_ver_x;
362
7.60k
        sp->d_ver_y = sp->d_hor_x;
363
7.60k
    }
364
7.60k
    sp->mv_scale_hor = (cp_mv[0].x) * (1 << MAX_CU_DEPTH);
365
7.60k
    sp->mv_scale_ver = (cp_mv[0].y) * (1 << MAX_CU_DEPTH);
366
7.60k
    sp->cb_width  = cb_width;
367
7.60k
    sp->cb_height = cb_height;
368
7.60k
    sp->is_fallback = is_fallback_mode(sp, mi->pred_flag);
369
7.60k
}
370
371
static void derive_subblock_diff_mvs(const VVCLocalContext *lc, PredictionUnit* pu, const SubblockParams* sp, const int lx)
372
7.60k
{
373
7.60k
    pu->cb_prof_flag[lx] = derive_cb_prof_flag_lx(lc, pu, lx, sp->is_fallback);
374
7.60k
    if (pu->cb_prof_flag[lx]) {
375
0
        const int dmv_limit = 1 << 5;
376
0
        const int pos_offset_x = 6 * (sp->d_hor_x + sp->d_hor_y);
377
0
        const int pos_offset_y = 6 * (sp->d_ver_x + sp->d_ver_y);
378
0
        for (int x = 0; x < AFFINE_MIN_BLOCK_SIZE; x++) {
379
0
            for (int y = 0; y < AFFINE_MIN_BLOCK_SIZE; y++) {
380
0
                LOCAL_ALIGNED_8(Mv, diff, [1]);
381
0
                diff->x = x * (sp->d_hor_x * (1 << 2)) + y * (sp->d_hor_y * (1 << 2)) - pos_offset_x;
382
0
                diff->y = x * (sp->d_ver_x * (1 << 2)) + y * (sp->d_ver_y * (1 << 2)) - pos_offset_y;
383
0
                ff_vvc_round_mv(diff, 0, 8);
384
0
                pu->diff_mv_x[lx][AFFINE_MIN_BLOCK_SIZE * y + x] = av_clip(diff->x, -dmv_limit + 1, dmv_limit - 1);
385
0
                pu->diff_mv_y[lx][AFFINE_MIN_BLOCK_SIZE * y + x] = av_clip(diff->y, -dmv_limit + 1, dmv_limit - 1);
386
0
            }
387
0
        }
388
0
    }
389
7.60k
}
390
391
static void store_cp_mv(const VVCLocalContext *lc, const MotionInfo *mi, const int lx)
392
7.60k
{
393
7.60k
    VVCFrameContext *fc = lc->fc;
394
7.60k
    const CodingUnit *cu = lc->cu;
395
7.60k
    const int log2_min_cb_size = fc->ps.sps->min_cb_log2_size_y;
396
7.60k
    const int min_cb_size = fc->ps.sps->min_cb_size_y;
397
7.60k
    const int min_cb_width = fc->ps.pps->min_cb_width;
398
7.60k
    const int num_cp_mv = mi->motion_model_idc + 1;
399
400
22.2k
    for (int dy = 0; dy < cu->cb_height; dy += min_cb_size) {
401
43.4k
        for (int dx = 0; dx < cu->cb_width; dx += min_cb_size) {
402
28.7k
            const int x_cb = (cu->x0 + dx) >> log2_min_cb_size;
403
28.7k
            const int y_cb = (cu->y0 + dy) >> log2_min_cb_size;
404
28.7k
            const int offset = (y_cb * min_cb_width + x_cb) * MAX_CONTROL_POINTS;
405
406
28.7k
            memcpy(&fc->tab.cp_mv[lx][offset], mi->mv[lx], sizeof(Mv) * num_cp_mv);
407
28.7k
        }
408
14.6k
    }
409
7.60k
}
410
411
//8.5.5.9 Derivation process for motion vector arrays from affine control point motion vectors
412
void ff_vvc_store_sb_mvs(const VVCLocalContext *lc, PredictionUnit *pu)
413
4.04k
{
414
4.04k
    const CodingUnit *cu = lc->cu;
415
4.04k
    const MotionInfo *mi = &pu->mi;
416
4.04k
    const int sbw = cu->cb_width / mi->num_sb_x;
417
4.04k
    const int sbh = cu->cb_height / mi->num_sb_y;
418
4.04k
    SubblockParams params[2];
419
4.04k
    MvField mvf = {0};
420
421
4.04k
    mvf.pred_flag = mi->pred_flag;
422
4.04k
    mvf.bcw_idx = mi->bcw_idx;
423
4.04k
    mvf.hpel_if_idx = mi->hpel_if_idx;
424
12.1k
    for (int i = 0; i < 2; i++) {
425
8.08k
        const PredFlag mask = i + 1;
426
8.08k
        if (mi->pred_flag & mask) {
427
7.60k
            store_cp_mv(lc, mi, i);
428
7.60k
            init_subblock_params(params + i, mi, cu->cb_width, cu->cb_height, i);
429
7.60k
            derive_subblock_diff_mvs(lc, pu, params + i, i);
430
7.60k
            mvf.ref_idx[i] = mi->ref_idx[i];
431
7.60k
        }
432
8.08k
    }
433
434
12.1k
    for (int sby = 0; sby < mi->num_sb_y; sby++) {
435
24.2k
        for (int sbx = 0; sbx < mi->num_sb_x; sbx++) {
436
16.1k
            const int x0 = cu->x0 + sbx * sbw;
437
16.1k
            const int y0 = cu->y0 + sby * sbh;
438
48.5k
            for (int i = 0; i < 2; i++) {
439
32.3k
                const PredFlag mask = i + 1;
440
32.3k
                if (mi->pred_flag & mask) {
441
30.4k
                    const SubblockParams* sp = params + i;
442
30.4k
                    const int x_pos_cb = sp->is_fallback ? (cu->cb_width >> 1) : (2 + (sbx << MIN_CU_LOG2));
443
30.4k
                    const int y_pos_cb = sp->is_fallback ? (cu->cb_height >> 1) : (2 + (sby << MIN_CU_LOG2));
444
30.4k
                    Mv *mv = mvf.mv + i;
445
446
30.4k
                    mv->x = sp->mv_scale_hor + sp->d_hor_x * x_pos_cb + sp->d_hor_y * y_pos_cb;
447
30.4k
                    mv->y = sp->mv_scale_ver + sp->d_ver_x * x_pos_cb + sp->d_ver_y * y_pos_cb;
448
30.4k
                    ff_vvc_round_mv(mv, 0, MAX_CU_DEPTH);
449
30.4k
                    ff_vvc_clip_mv(mv);
450
30.4k
                }
451
32.3k
            }
452
16.1k
            ff_vvc_set_mvf(lc, x0, y0, sbw, sbh, &mvf);
453
16.1k
        }
454
8.08k
    }
455
4.04k
}
456
457
void ff_vvc_store_gpm_mvf(const VVCLocalContext *lc, const PredictionUnit *pu)
458
9.23k
{
459
9.23k
    const CodingUnit *cu     = lc->cu;
460
9.23k
    const int angle_idx      = ff_vvc_gpm_angle_idx[pu->gpm_partition_idx];
461
9.23k
    const int distance_idx   = ff_vvc_gpm_distance_idx[pu->gpm_partition_idx];
462
9.23k
    const int displacement_x = ff_vvc_gpm_distance_lut[angle_idx];
463
9.23k
    const int displacement_y = ff_vvc_gpm_distance_lut[(angle_idx + 8) % 32];
464
9.23k
    const int is_flip        = angle_idx >= 13 &&angle_idx <= 27;
465
9.23k
    const int shift_hor      = (angle_idx % 16 == 8 || (angle_idx % 16 && cu->cb_height >= cu->cb_width)) ? 0 : 1;
466
9.23k
    const int sign           = angle_idx < 16 ? 1 : -1;
467
9.23k
    const int block_size     = 4;
468
9.23k
    int offset_x = (-cu->cb_width) >> 1;
469
9.23k
    int offset_y = (-cu->cb_height) >> 1;
470
471
9.23k
    if (!shift_hor)
472
8.59k
        offset_y += sign * ((distance_idx * cu->cb_height) >> 3);
473
632
    else
474
632
        offset_x += sign * ((distance_idx * cu->cb_width) >> 3);
475
476
27.6k
    for (int y = 0; y < cu->cb_height; y += block_size) {
477
55.3k
        for (int x = 0; x < cu->cb_width; x += block_size) {
478
36.9k
            const int motion_idx = (((x + offset_x) * (1 << 1)) + 5) * displacement_x +
479
36.9k
                (((y + offset_y) * (1 << 1)) + 5) * displacement_y;
480
36.9k
            const int s_type = FFABS(motion_idx) < 32 ? 2 : (motion_idx <= 0 ? (1 - is_flip) : is_flip);
481
36.9k
            const int pred_flag = pu->gpm_mv[0].pred_flag | pu->gpm_mv[1].pred_flag;
482
36.9k
            const int x0 = cu->x0 + x;
483
36.9k
            const int y0 = cu->y0 + y;
484
485
36.9k
            if (!s_type)
486
11.0k
                ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, pu->gpm_mv + 0);
487
25.9k
            else if (s_type == 1 || (s_type == 2 && pred_flag != PF_BI))
488
15.9k
                ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, pu->gpm_mv + 1);
489
9.96k
            else {
490
9.96k
                MvField mvf  = pu->gpm_mv[0];
491
9.96k
                const MvField *mv1 = &pu->gpm_mv[1];
492
9.96k
                const int lx =  mv1->pred_flag - PF_L0;
493
9.96k
                mvf.pred_flag = PF_BI;
494
9.96k
                mvf.ref_idx[lx] = mv1->ref_idx[lx];
495
9.96k
                mvf.mv[lx] = mv1->mv[lx];
496
9.96k
                ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, &mvf);
497
9.96k
            }
498
36.9k
        }
499
18.4k
    }
500
9.23k
}
501
502
void ff_vvc_store_mvf(const VVCLocalContext *lc, const MvField *mvf)
503
54.0k
{
504
54.0k
    const CodingUnit *cu = lc->cu;
505
54.0k
    ff_vvc_set_mvf(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height, mvf);
506
54.0k
}
507
508
void ff_vvc_store_mv(const VVCLocalContext *lc, const MotionInfo *mi)
509
369k
{
510
369k
    const CodingUnit *cu = lc->cu;
511
369k
    MvField mvf = {0};
512
513
369k
    mvf.hpel_if_idx = mi->hpel_if_idx;
514
369k
    mvf.bcw_idx = mi->bcw_idx;
515
369k
    mvf.pred_flag = mi->pred_flag;
516
517
1.10M
    for (int i = 0; i < 2; i++) {
518
738k
        const PredFlag mask = i + 1;
519
738k
        if (mvf.pred_flag & mask) {
520
371k
            mvf.mv[i] = mi->mv[i][0];
521
371k
            mvf.ref_idx[i] = mi->ref_idx[i];
522
371k
        }
523
738k
    }
524
369k
    ff_vvc_set_mvf(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height, &mvf);
525
369k
}
526
527
typedef enum NeighbourIdx {
528
    A0,
529
    A1,
530
    A2,
531
    B0,
532
    B1,
533
    B2,
534
    B3,
535
    NUM_NBS,
536
    NB_IDX_NONE = NUM_NBS,
537
} NeighbourIdx;
538
539
typedef struct Neighbour {
540
    int x;
541
    int y;
542
543
    int checked;
544
    int available;
545
} Neighbour;
546
547
typedef struct NeighbourContext {
548
    Neighbour neighbours[NUM_NBS];
549
    const VVCLocalContext *lc;
550
} NeighbourContext;
551
552
static int is_available(const VVCFrameContext *fc, const int x0, const int y0)
553
131k
{
554
131k
    const VVCSPS *sps      = fc->ps.sps;
555
131k
    const int x            = x0 >> sps->min_cb_log2_size_y;
556
131k
    const int y            = y0 >> sps->min_cb_log2_size_y;
557
131k
    const int min_cb_width = fc->ps.pps->min_cb_width;
558
559
131k
    return SAMPLE_CTB(fc->tab.cb_width[0], x, y) != 0;
560
131k
}
561
562
static int is_a0_available(const VVCLocalContext *lc, const CodingUnit *cu)
563
238k
{
564
238k
    const VVCFrameContext *fc   = lc->fc;
565
238k
    const VVCSPS *sps           = fc->ps.sps;
566
238k
    const int x0b               = av_zero_extend(cu->x0, sps->ctb_log2_size_y);
567
238k
    int cand_bottom_left;
568
569
238k
    if (!x0b && !lc->ctb_left_flag) {
570
205k
        cand_bottom_left = 0;
571
205k
    } else {
572
33.6k
        const int max_y = FFMIN(fc->ps.pps->height, ((cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y);
573
33.6k
        if (cu->y0 + cu->cb_height >= max_y)
574
20.4k
            cand_bottom_left = 0;
575
13.2k
        else
576
13.2k
            cand_bottom_left = is_available(fc, cu->x0 - 1, cu->y0 + cu->cb_height);
577
33.6k
    }
578
238k
    return cand_bottom_left;
579
238k
}
580
581
static void init_neighbour_context(NeighbourContext *ctx, const VVCLocalContext *lc)
582
238k
{
583
238k
    const CodingUnit *cu            = lc->cu;
584
238k
    const NeighbourAvailable *na    = &lc->na;
585
238k
    const int x0                    = cu->x0;
586
238k
    const int y0                    = cu->y0;
587
238k
    const int cb_width              = cu->cb_width;
588
238k
    const int cb_height             = cu->cb_height;
589
238k
    const int a0_available          = is_a0_available(lc, cu);
590
591
238k
    Neighbour neighbours[NUM_NBS] = {
592
238k
        { x0 - 1,               y0 + cb_height,         !a0_available           }, //A0
593
238k
        { x0 - 1,               y0 + cb_height - 1,     !na->cand_left          }, //A1
594
238k
        { x0 - 1,               y0,                     !na->cand_left          }, //A2
595
238k
        { x0 + cb_width,        y0 - 1,                 !na->cand_up_right      }, //B0
596
238k
        { x0 + cb_width - 1,    y0 - 1,                 !na->cand_up            }, //B1
597
238k
        { x0 - 1,               y0 - 1,                 !na->cand_up_left       }, //B2
598
238k
        { x0,                   y0 - 1,                 !na->cand_up            }, //B3
599
238k
    };
600
601
238k
    memcpy(ctx->neighbours, neighbours, sizeof(neighbours));
602
238k
    ctx->lc = lc;
603
238k
}
604
605
static av_always_inline PredMode pred_flag_to_mode(PredFlag pred)
606
115k
{
607
115k
    static const PredMode lut[] = {
608
115k
        MODE_INTRA, // PF_INTRA
609
115k
        MODE_INTER, // PF_L0
610
115k
        MODE_INTER, // PF_L1
611
115k
        MODE_INTER, // PF_BI
612
115k
        0,          // invalid
613
115k
        MODE_IBC,   // PF_IBC
614
115k
        0,          // invalid
615
115k
        0,          // invalid
616
115k
        MODE_PLT,   // PF_PLT
617
115k
    };
618
619
115k
    return lut[pred];
620
115k
}
621
622
static int check_available(Neighbour *n, const VVCLocalContext *lc, const int check_mer)
623
787k
{
624
787k
    const VVCFrameContext *fc   = lc->fc;
625
787k
    const VVCSPS *sps           = fc->ps.sps;
626
787k
    const CodingUnit *cu        = lc->cu;
627
787k
    const MvField *tab_mvf      = fc->tab.mvf;
628
787k
    const int min_pu_width      = fc->ps.pps->min_pu_width;
629
630
787k
    if (!n->checked) {
631
117k
        n->checked = 1;
632
117k
        n->available = !sps->r->sps_entropy_coding_sync_enabled_flag || ((n->x >> sps->ctb_log2_size_y) <= (cu->x0 >> sps->ctb_log2_size_y));
633
117k
        n->available = n->available && is_available(fc, n->x, n->y) && cu->pred_mode == pred_flag_to_mode(TAB_MVF(n->x, n->y).pred_flag);
634
117k
        if (check_mer)
635
45.6k
            n->available = n->available && !is_same_mer(fc, n->x, n->y, cu->x0, cu->y0);
636
117k
    }
637
787k
    return n->available;
638
787k
}
639
640
static const MvField *mv_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand)
641
42.0k
{
642
42.0k
    const VVCFrameContext *fc   = lc->fc;
643
42.0k
    const int min_pu_width      = fc->ps.pps->min_pu_width;
644
42.0k
    const MvField* tab_mvf      = fc->tab.mvf;
645
42.0k
    const MvField *mvf          = &TAB_MVF(x_cand, y_cand);
646
647
42.0k
    return mvf;
648
42.0k
}
649
650
static const MvField* mv_merge_from_nb(NeighbourContext *ctx, const NeighbourIdx nb)
651
283k
{
652
283k
    const VVCLocalContext *lc   = ctx->lc;
653
283k
    Neighbour *n                = &ctx->neighbours[nb];
654
655
283k
    if (check_available(n, lc, 1))
656
42.0k
        return mv_merge_candidate(lc, n->x, n->y);
657
241k
    return 0;
658
283k
}
659
283k
#define MV_MERGE_FROM_NB(nb) mv_merge_from_nb(&nctx, nb)
660
661
//8.5.2.3 Derivation process for spatial merging candidates
662
static int mv_merge_spatial_candidates(const VVCLocalContext *lc, const int merge_idx,
663
    const MvField **nb_list, MvField *cand_list, int *nb_merge_cand)
664
63.2k
{
665
63.2k
    const MvField *cand;
666
63.2k
    int num_cands = 0;
667
63.2k
    NeighbourContext nctx;
668
669
63.2k
    static NeighbourIdx nbs[][2] = {
670
63.2k
        {B1, NB_IDX_NONE },
671
63.2k
        {A1, B1 },
672
63.2k
        {B0, B1 },
673
63.2k
        {A0, A1 },
674
63.2k
    };
675
676
63.2k
    init_neighbour_context(&nctx, lc);
677
283k
    for (int i = 0; i < FF_ARRAY_ELEMS(nbs); i++) {
678
229k
        NeighbourIdx nb    = nbs[i][0];
679
229k
        NeighbourIdx old   = nbs[i][1];
680
229k
        cand = nb_list[nb] = MV_MERGE_FROM_NB(nb);
681
229k
        if (cand && !compare_mv_ref_idx(cand, nb_list[old])) {
682
20.8k
            cand_list[num_cands] = *cand;
683
20.8k
            if (merge_idx == num_cands)
684
8.84k
                return 1;
685
12.0k
            num_cands++;
686
12.0k
        }
687
229k
    }
688
54.4k
    if (num_cands != 4) {
689
54.3k
        cand = MV_MERGE_FROM_NB(B2);
690
54.3k
        if (cand && !compare_mv_ref_idx(cand, nb_list[A1])
691
408
            && !compare_mv_ref_idx(cand, nb_list[B1])) {
692
255
            cand_list[num_cands] = *cand;
693
255
            if (merge_idx == num_cands)
694
129
                return 1;
695
126
            num_cands++;
696
126
        }
697
54.3k
    }
698
54.2k
    *nb_merge_cand = num_cands;
699
54.2k
    return 0;
700
54.4k
}
701
702
static int mv_merge_temporal_candidate(const VVCLocalContext *lc, MvField *cand)
703
54.2k
{
704
54.2k
    const VVCFrameContext *fc   = lc->fc;
705
54.2k
    const CodingUnit *cu        = lc->cu;
706
707
54.2k
    memset(cand, 0, sizeof(*cand));
708
54.2k
    if (fc->ps.ph.r->ph_temporal_mvp_enabled_flag && (cu->cb_width * cu->cb_height > 32)) {
709
26.3k
        int available_l0 = temporal_luma_motion_vector(lc, 0, cand->mv + 0, 0, 1, 0);
710
26.3k
        int available_l1 = IS_B(lc->sc->sh.r) ?
711
26.2k
            temporal_luma_motion_vector(lc, 0, cand->mv + 1, 1, 1, 0) : 0;
712
26.3k
        cand->pred_flag = available_l0 + (available_l1 << 1);
713
26.3k
    }
714
54.2k
    return cand->pred_flag;
715
54.2k
}
716
717
//8.5.2.6 Derivation process for history-based merging candidates
718
static int mv_merge_history_candidates(const VVCLocalContext *lc, const int merge_idx,
719
    const MvField **nb_list, MvField *cand_list, int *num_cands)
720
53.9k
{
721
53.9k
    const VVCSPS *sps       = lc->fc->ps.sps;
722
53.9k
    const EntryPoint* ep    = lc->ep;
723
65.0k
    for (int i = 1; i <= ep->num_hmvp && (*num_cands < sps->max_num_merge_cand - 1); i++) {
724
11.8k
        const MvField *h = &ep->hmvp[ep->num_hmvp - i];
725
11.8k
        const int same_motion = i <= 2 && (compare_mv_ref_idx(h, nb_list[A1]) || compare_mv_ref_idx(h, nb_list[B1]));
726
11.8k
        if (!same_motion) {
727
1.45k
            cand_list[*num_cands] = *h;
728
1.45k
            if (merge_idx == *num_cands)
729
744
                return 1;
730
714
            (*num_cands)++;
731
714
        }
732
11.8k
    }
733
53.2k
    return 0;
734
53.9k
}
735
736
//8.5.2.4 Derivation process for pairwise average merging candidate
737
static int mv_merge_pairwise_candidate(MvField *cand_list, const int num_cands, const int is_b)
738
53.2k
{
739
53.2k
    if (num_cands > 1) {
740
117
        const int num_ref_rists = is_b ? 2 : 1;
741
117
        const MvField* p0       = cand_list + 0;
742
117
        const MvField* p1       = cand_list + 1;
743
117
        MvField* cand           = cand_list + num_cands;
744
745
117
        cand->pred_flag = 0;
746
234
        for (int i = 0; i < num_ref_rists; i++) {
747
117
            PredFlag mask = i + 1;
748
117
            if (p0->pred_flag & mask) {
749
117
                cand->pred_flag |= mask;
750
117
                cand->ref_idx[i] = p0->ref_idx[i];
751
117
                if (p1->pred_flag & mask) {
752
117
                    Mv *mv = cand->mv + i;
753
117
                    mv->x = p0->mv[i].x + p1->mv[i].x;
754
117
                    mv->y = p0->mv[i].y + p1->mv[i].y;
755
117
                    ff_vvc_round_mv(mv, 0, 1);
756
117
                } else {
757
0
                    cand->mv[i] = p0->mv[i];
758
0
                }
759
117
            } else if (p1->pred_flag & mask) {
760
0
                cand->pred_flag |= mask;
761
0
                cand->mv[i] = p1->mv[i];
762
0
                cand->ref_idx[i] = p1->ref_idx[i];
763
0
            }
764
117
        }
765
117
        if (cand->pred_flag) {
766
117
            cand->hpel_if_idx = p0->hpel_if_idx == p1->hpel_if_idx ? p0->hpel_if_idx : 0;
767
117
            cand->bcw_idx = 0;
768
117
            cand->ciip_flag = 0;
769
117
            return 1;
770
117
        }
771
117
    }
772
53.1k
    return 0;
773
53.2k
}
774
775
//8.5.2.5 Derivation process for zero motion vector merging candidates
776
static void mv_merge_zero_motion_candidate(const VVCLocalContext *lc, const int merge_idx,
777
    MvField *cand_list, int num_cands)
778
53.1k
{
779
53.1k
    const VVCSPS *sps             = lc->fc->ps.sps;
780
53.1k
    const H266RawSliceHeader *rsh = lc->sc->sh.r;
781
53.1k
    const int num_ref_idx         = IS_P(rsh) ?
782
44.9k
        rsh->num_ref_idx_active[L0] : FFMIN(rsh->num_ref_idx_active[L0], rsh->num_ref_idx_active[L1]);
783
53.1k
    int zero_idx                  = 0;
784
785
104k
    while (num_cands < sps->max_num_merge_cand) {
786
104k
        MvField *cand = cand_list + num_cands;
787
788
104k
        cand->pred_flag    = PF_L0 + (IS_B(rsh) << 1);
789
104k
        AV_ZERO64(cand->mv + 0);
790
104k
        AV_ZERO64(cand->mv + 1);
791
104k
        cand->ref_idx[0]   = zero_idx < num_ref_idx ? zero_idx : 0;
792
104k
        cand->ref_idx[1]   = zero_idx < num_ref_idx ? zero_idx : 0;
793
104k
        cand->bcw_idx      = 0;
794
104k
        cand->hpel_if_idx  = 0;
795
104k
        if (merge_idx == num_cands)
796
53.1k
            return;
797
51.4k
        num_cands++;
798
51.4k
        zero_idx++;
799
51.4k
    }
800
53.1k
}
801
802
static void mv_merge_mode(const VVCLocalContext *lc,  const int merge_idx, MvField *cand_list)
803
63.2k
{
804
63.2k
    int num_cands    = 0;
805
63.2k
    const MvField *nb_list[NUM_NBS + 1] = { NULL };
806
807
63.2k
    if (mv_merge_spatial_candidates(lc, merge_idx, nb_list, cand_list, &num_cands))
808
8.97k
        return;
809
810
54.2k
    if (mv_merge_temporal_candidate(lc, &cand_list[num_cands])) {
811
1.20k
        if (merge_idx == num_cands)
812
307
            return;
813
898
        num_cands++;
814
898
    }
815
816
53.9k
    if (mv_merge_history_candidates(lc, merge_idx, nb_list, cand_list, &num_cands))
817
744
        return;
818
819
53.2k
    if (mv_merge_pairwise_candidate(cand_list, num_cands, IS_B(lc->sc->sh.r))) {
820
117
        if (merge_idx == num_cands)
821
105
            return;
822
12
        num_cands++;
823
12
    }
824
825
53.1k
    mv_merge_zero_motion_candidate(lc, merge_idx, cand_list, num_cands);
826
53.1k
}
827
828
//8.5.2.2 Derivation process for luma motion vectors for merge mode
829
void ff_vvc_luma_mv_merge_mode(VVCLocalContext *lc, const int merge_idx, const int ciip_flag, MvField *mv)
830
54.0k
{
831
54.0k
    const CodingUnit *cu = lc->cu;
832
54.0k
    MvField cand_list[MRG_MAX_NUM_CANDS];
833
834
54.0k
    ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
835
54.0k
    mv_merge_mode(lc, merge_idx, cand_list);
836
54.0k
    *mv = cand_list[merge_idx];
837
    //ciip flag in not inhritable
838
54.0k
    mv->ciip_flag = ciip_flag;
839
54.0k
}
840
841
//8.5.4.2 Derivation process for luma motion vectors for geometric partitioning merge mode
842
void ff_vvc_luma_mv_merge_gpm(VVCLocalContext *lc, const int merge_gpm_idx[2], MvField *mv)
843
9.23k
{
844
9.23k
    const CodingUnit *cu = lc->cu;
845
9.23k
    MvField cand_list[MRG_MAX_NUM_CANDS];
846
847
9.23k
    const int idx[] = { merge_gpm_idx[0], merge_gpm_idx[1] + (merge_gpm_idx[1] >= merge_gpm_idx[0]) };
848
849
9.23k
    ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
850
9.23k
    mv_merge_mode(lc, FFMAX(idx[0], idx[1]), cand_list);
851
9.23k
    memset(mv, 0, 2 * sizeof(*mv));
852
27.6k
    for (int i = 0; i < 2; i++) {
853
18.4k
        int lx   = idx[i] & 1;
854
18.4k
        int mask = lx + PF_L0;
855
18.4k
        MvField *cand = cand_list + idx[i];
856
18.4k
        if (!(cand->pred_flag & mask)) {
857
0
            lx   = !lx;
858
0
            mask = lx + PF_L0;
859
0
        }
860
18.4k
        mv[i].pred_flag   = mask;
861
18.4k
        mv[i].ref_idx[lx] = cand->ref_idx[lx];
862
18.4k
        mv[i].mv[lx]      = cand->mv[lx];
863
18.4k
    }
864
865
9.23k
}
866
867
//8.5.5.5 Derivation process for luma affine control point motion vectors from a neighbouring block
868
static void affine_cps_from_nb(const VVCLocalContext *lc,
869
    const int x_nb, int y_nb, const int nbw, const int nbh, const int lx,
870
    Mv *cps, int num_cps)
871
0
{
872
0
    const VVCFrameContext *fc   = lc->fc;
873
0
    const CodingUnit *cu        = lc->cu;
874
0
    const int x0                = cu->x0;
875
0
    const int y0                = cu->y0;
876
0
    const int cb_width          = cu->cb_width;
877
0
    const int cb_height         = cu->cb_height;
878
0
    const MvField* tab_mvf      = fc->tab.mvf;
879
0
    const int min_cb_log2_size  = fc->ps.sps->min_cb_log2_size_y;
880
0
    const int min_cb_width      = fc->ps.pps->min_cb_width;
881
882
0
    const int log2_nbw          = ff_log2(nbw);
883
0
    const int log2_nbh          = ff_log2(nbh);
884
0
    const int is_ctb_boundary   = !((y_nb + nbh) % fc->ps.sps->ctb_size_y) && (y_nb + nbh == y0);
885
0
    const Mv *l, *r;
886
0
    int mv_scale_hor, mv_scale_ver, d_hor_x, d_ver_x, d_hor_y, d_ver_y, motion_model_idc_nb;
887
0
    if (is_ctb_boundary) {
888
0
        const int min_pu_width = fc->ps.pps->min_pu_width;
889
0
        l = &TAB_MVF(x_nb, y_nb + nbh - 1).mv[lx];
890
0
        r = &TAB_MVF(x_nb + nbw - 1, y_nb + nbh - 1).mv[lx];
891
0
    } else {
892
0
        const int x = x_nb >> min_cb_log2_size;
893
0
        const int y = y_nb >> min_cb_log2_size;
894
0
        motion_model_idc_nb  = SAMPLE_CTB(fc->tab.mmi, x, y);
895
896
0
        l = &TAB_CP_MV(lx, x_nb, y_nb);
897
0
        r = &TAB_CP_MV(lx, x_nb + nbw - 1, y_nb) + 1;
898
0
    }
899
0
    mv_scale_hor = l->x * (1 << 7);
900
0
    mv_scale_ver = l->y * (1 << 7);
901
0
    d_hor_x = (r->x - l->x) * (1 << (7 - log2_nbw));
902
0
    d_ver_x = (r->y - l->y) * (1 << (7 - log2_nbw));
903
0
    if (!is_ctb_boundary && motion_model_idc_nb == MOTION_6_PARAMS_AFFINE) {
904
0
        const Mv* lb = &TAB_CP_MV(lx, x_nb, y_nb + nbh - 1) + 2;
905
0
        d_hor_y = (lb->x - l->x) * (1 << (7 - log2_nbh));
906
0
        d_ver_y = (lb->y - l->y) * (1 << (7 - log2_nbh));
907
0
    } else {
908
0
        d_hor_y = -d_ver_x;
909
0
        d_ver_y = d_hor_x;
910
0
    }
911
912
0
    if (is_ctb_boundary) {
913
0
        y_nb = y0;
914
0
    }
915
0
    cps[0].x = mv_scale_hor + d_hor_x * (x0 - x_nb)  + d_hor_y * (y0 - y_nb);
916
0
    cps[0].y = mv_scale_ver + d_ver_x * (x0 - x_nb)  + d_ver_y * (y0 - y_nb);
917
0
    cps[1].x = mv_scale_hor + d_hor_x * (x0 + cb_width - x_nb)  + d_hor_y * (y0 - y_nb);
918
0
    cps[1].y = mv_scale_ver + d_ver_x * (x0 + cb_width - x_nb)  + d_ver_y * (y0 - y_nb);
919
0
    if (num_cps == 3) {
920
0
        cps[2].x = mv_scale_hor + d_hor_x * (x0 - x_nb)  + d_hor_y * (y0 + cb_height - y_nb);
921
0
        cps[2].y = mv_scale_ver + d_ver_x * (x0 - x_nb)  + d_ver_y * (y0 + cb_height - y_nb);
922
0
    }
923
0
    for (int i = 0; i < num_cps; i++) {
924
0
        ff_vvc_round_mv(cps + i, 0, 7);
925
0
        ff_vvc_clip_mv(cps + i);
926
0
    }
927
0
}
928
929
//derive affine neighbour's position, width and height,
930
static int affine_neighbour_cb(const VVCFrameContext *fc, const int x_nb, const int y_nb, int *x_cb, int *y_cb, int *cbw, int *cbh)
931
0
{
932
0
    const int log2_min_cb_size  = fc->ps.sps->min_cb_log2_size_y;
933
0
    const int min_cb_width      = fc->ps.pps->min_cb_width;
934
0
    const int x                 = x_nb >> log2_min_cb_size;
935
0
    const int y                 = y_nb >> log2_min_cb_size;
936
0
    const int motion_model_idc  = SAMPLE_CTB(fc->tab.mmi, x, y);
937
0
    if (motion_model_idc) {
938
0
        *x_cb = SAMPLE_CTB(fc->tab.cb_pos_x[0],  x, y);
939
0
        *y_cb = SAMPLE_CTB(fc->tab.cb_pos_y[0],  x, y);
940
0
        *cbw  = SAMPLE_CTB(fc->tab.cb_width[0],  x, y);
941
0
        *cbh  = SAMPLE_CTB(fc->tab.cb_height[0], x, y);
942
0
    }
943
0
    return motion_model_idc;
944
0
}
945
946
//part of 8.5.5.2 Derivation process for motion vectors and reference indices in subblock merge mode
947
static int affine_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, MotionInfo* mi)
948
0
{
949
0
    const VVCFrameContext *fc = lc->fc;
950
0
    int x, y, w, h, motion_model_idc;
951
952
0
    motion_model_idc = affine_neighbour_cb(fc, x_cand, y_cand, &x, &y, &w, &h);
953
0
    if (motion_model_idc) {
954
0
        const int min_pu_width = fc->ps.pps->min_pu_width;
955
0
        const MvField* tab_mvf = fc->tab.mvf;
956
0
        const MvField *mvf = &TAB_MVF(x, y);
957
958
0
        mi->bcw_idx   = mvf->bcw_idx;
959
0
        mi->pred_flag = mvf->pred_flag;
960
0
        for (int i = 0; i < 2; i++) {
961
0
            PredFlag mask = i + 1;
962
0
            if (mi->pred_flag & mask) {
963
0
                affine_cps_from_nb(lc, x, y, w, h, i, &mi->mv[i][0], motion_model_idc + 1);
964
0
            }
965
0
            mi->ref_idx[i] = mvf->ref_idx[i];
966
0
        }
967
0
        mi->motion_model_idc = motion_model_idc;
968
0
    }
969
0
    return motion_model_idc;
970
0
}
971
972
static int affine_merge_from_nbs(NeighbourContext *ctx, const NeighbourIdx *nbs, const int num_nbs, MotionInfo* cand)
973
7.68k
{
974
7.68k
    const VVCLocalContext *lc = ctx->lc;
975
26.8k
    for (int i = 0; i < num_nbs; i++) {
976
19.2k
        Neighbour *n = &ctx->neighbours[nbs[i]];
977
19.2k
        if (check_available(n, lc, 1) && affine_merge_candidate(lc, n->x, n->y, cand))
978
0
            return 1;
979
19.2k
    }
980
7.68k
    return 0;
981
7.68k
}
982
7.68k
#define AFFINE_MERGE_FROM_NBS(nbs) affine_merge_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), mi)
983
984
985
static const MvField* derive_corner_mvf(NeighbourContext *ctx, const NeighbourIdx *neighbour, const int num_neighbour)
986
11.7k
{
987
11.7k
    const VVCFrameContext *fc   = ctx->lc->fc;
988
11.7k
    const MvField *tab_mvf      = fc->tab.mvf;
989
11.7k
    const int min_pu_width      = fc->ps.pps->min_pu_width;
990
38.8k
    for (int i = 0; i < num_neighbour; i++) {
991
27.1k
        Neighbour *n = &ctx->neighbours[neighbour[i]];
992
27.1k
        if (check_available(n, ctx->lc, 1)) {
993
0
            return &TAB_MVF(n->x, n->y);
994
0
        }
995
27.1k
    }
996
11.7k
    return NULL;
997
11.7k
}
998
999
11.5k
#define DERIVE_CORNER_MV(nbs) derive_corner_mvf(nctx, nbs, FF_ARRAY_ELEMS(nbs))
1000
1001
// check if the mv's and refidx are the same between A and B
1002
static av_always_inline int compare_pf_ref_idx(const MvField *A, const struct MvField *B, const struct MvField *C, const int lx)
1003
0
{
1004
1005
0
    const PredFlag mask = (lx + 1) & A->pred_flag;
1006
0
    if (!(B->pred_flag & mask))
1007
0
        return 0;
1008
0
    if (A->ref_idx[lx] != B->ref_idx[lx])
1009
0
        return 0;
1010
0
    if (C) {
1011
0
        if (!(C->pred_flag & mask))
1012
0
            return 0;
1013
0
        if (A->ref_idx[lx] != C->ref_idx[lx])
1014
0
            return 0;
1015
0
    }
1016
0
    return 1;
1017
0
}
1018
1019
static av_always_inline void sb_clip_location(const VVCLocalContext *lc,
1020
    const int x_ctb, const int y_ctb, const Mv* temp_mv, int *x, int *y)
1021
131
{
1022
131
    const VVCFrameContext *fc = lc->fc;
1023
131
    const VVCPPS *pps         = fc->ps.pps;
1024
131
    const int ctb_log2_size   = fc->ps.sps->ctb_log2_size_y;
1025
131
    const int subpic_idx      = lc->sc->sh.r->curr_subpic_idx;
1026
131
    const int x_end           = pps->subpic_x[subpic_idx] + pps->subpic_width[subpic_idx];
1027
131
    const int y_end           = pps->subpic_y[subpic_idx] + pps->subpic_height[subpic_idx];
1028
1029
131
    *x = av_clip(*x + temp_mv->x, x_ctb, FFMIN(x_end - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7;
1030
131
    *y = av_clip(*y + temp_mv->y, y_ctb, FFMIN(y_end - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7;
1031
131
}
1032
1033
static void sb_temproal_luma_motion(const VVCLocalContext *lc,
1034
    const int x_ctb, const int y_ctb, const Mv *temp_mv,
1035
    int x, int y, uint8_t *pred_flag, Mv *mv)
1036
131
{
1037
131
    MvField temp_col;
1038
131
    Mv* mvLXCol;
1039
131
    const int refIdxLx          = 0;
1040
131
    const VVCFrameContext *fc   = lc->fc;
1041
131
    const VVCSH *sh             = &lc->sc->sh;
1042
131
    const int min_pu_width      = fc->ps.pps->min_pu_width;
1043
131
    VVCFrame *ref               = fc->ref->collocated_ref;
1044
131
    MvField *tab_mvf            = ref->tab_dmvr_mvf;
1045
131
    int colPic                  = ref->poc;
1046
131
    int X                       = 0;
1047
1048
131
    sb_clip_location(lc, x_ctb, y_ctb, temp_mv, &x, &y);
1049
1050
131
    temp_col    = TAB_MVF(x, y);
1051
131
    mvLXCol     = mv + 0;
1052
131
    *pred_flag = DERIVE_TEMPORAL_COLOCATED_MVS(1);
1053
131
    if (IS_B(sh->r)) {
1054
130
        X = 1;
1055
130
        mvLXCol = mv + 1;
1056
130
        *pred_flag |= (DERIVE_TEMPORAL_COLOCATED_MVS(1)) << 1;
1057
130
    }
1058
131
}
1059
1060
//8.5.5.4 Derivation process for subblock-based temporal merging base motion data
1061
static int sb_temporal_luma_motion_data(const VVCLocalContext *lc, const MvField *a1,
1062
    const int x_ctb, const int y_ctb, MvField *ctr_mvf, Mv *temp_mv)
1063
236
{
1064
236
    const VVCFrameContext *fc   = lc->fc;
1065
236
    const RefPicList *rpl       = lc->sc->rpl;
1066
236
    const CodingUnit *cu        = lc->cu;
1067
236
    const int x                 = cu->x0  + cu->cb_width / 2;
1068
236
    const int y                 = cu->y0  + cu->cb_height / 2;
1069
236
    const VVCFrame *ref         = fc->ref->collocated_ref;
1070
1071
236
    int colPic;
1072
1073
236
    memset(temp_mv, 0, sizeof(*temp_mv));
1074
1075
236
    if (!ref) {
1076
130
        memset(ctr_mvf, 0, sizeof(*ctr_mvf));
1077
130
        return 0;
1078
130
    }
1079
1080
106
    colPic  = ref->poc;
1081
1082
106
    if (a1) {
1083
0
        if ((a1->pred_flag & PF_L0) && colPic == rpl[L0].refs[a1->ref_idx[L0]].poc)
1084
0
            *temp_mv = a1->mv[0];
1085
0
        else if ((a1->pred_flag & PF_L1) && colPic == rpl[L1].refs[a1->ref_idx[L1]].poc)
1086
0
            *temp_mv = a1->mv[1];
1087
0
        ff_vvc_round_mv(temp_mv, 0, 4);
1088
0
    }
1089
106
    sb_temproal_luma_motion(lc, x_ctb, y_ctb, temp_mv, x, y, &ctr_mvf->pred_flag , ctr_mvf->mv);
1090
1091
106
    return ctr_mvf->pred_flag;
1092
236
}
1093
1094
1095
//8.5.5.3 Derivation process for subblock-based temporal merging candidates
1096
static int sb_temporal_merge_candidate(const VVCLocalContext* lc, NeighbourContext *nctx, PredictionUnit *pu)
1097
4.06k
{
1098
4.06k
    const VVCFrameContext *fc   = lc->fc;
1099
4.06k
    const CodingUnit *cu        = lc->cu;
1100
4.06k
    const VVCSPS *sps           = fc->ps.sps;
1101
4.06k
    const VVCPH *ph             = &fc->ps.ph;
1102
4.06k
    MotionInfo *mi              = &pu->mi;
1103
4.06k
    const int ctb_log2_size     = sps->ctb_log2_size_y;
1104
4.06k
    const int x0                = cu->x0;
1105
4.06k
    const int y0                = cu->y0;
1106
4.06k
    const NeighbourIdx n        = A1;
1107
4.06k
    const MvField *a1;
1108
4.06k
    MvField ctr_mvf;
1109
4.06k
    LOCAL_ALIGNED_8(Mv, temp_mv, [1]);
1110
4.06k
    const int x_ctb = (x0 >> ctb_log2_size) << ctb_log2_size;
1111
4.06k
    const int y_ctb = (y0 >> ctb_log2_size) << ctb_log2_size;
1112
1113
1114
4.06k
    if (!ph->r->ph_temporal_mvp_enabled_flag ||
1115
3.98k
        !sps->r->sps_sbtmvp_enabled_flag ||
1116
236
        (cu->cb_width < 8 && cu->cb_height < 8))
1117
3.83k
        return 0;
1118
1119
236
    mi->num_sb_x = cu->cb_width >> 3;
1120
236
    mi->num_sb_y = cu->cb_height >> 3;
1121
1122
236
    a1 = derive_corner_mvf(nctx, &n, 1);
1123
236
    if (sb_temporal_luma_motion_data(lc, a1, x_ctb, y_ctb, &ctr_mvf, temp_mv)) {
1124
25
        const int sbw = cu->cb_width / mi->num_sb_x;
1125
25
        const int sbh = cu->cb_height / mi->num_sb_y;
1126
25
        MvField mvf = {0};
1127
50
        for (int sby = 0; sby < mi->num_sb_y; sby++) {
1128
50
            for (int sbx = 0; sbx < mi->num_sb_x; sbx++) {
1129
25
                int x = x0 + sbx * sbw;
1130
25
                int y = y0 + sby * sbh;
1131
25
                sb_temproal_luma_motion(lc, x_ctb, y_ctb, temp_mv, x + sbw / 2, y +  sbh / 2, &mvf.pred_flag, mvf.mv);
1132
25
                if (!mvf.pred_flag) {
1133
0
                    mvf.pred_flag = ctr_mvf.pred_flag;
1134
0
                    memcpy(mvf.mv, ctr_mvf.mv, sizeof(mvf.mv));
1135
0
                }
1136
25
                ff_vvc_set_mvf(lc, x, y, sbw, sbh, &mvf);
1137
25
            }
1138
25
        }
1139
25
        return 1;
1140
25
    }
1141
211
    return 0;
1142
236
}
1143
1144
static int affine_merge_const1(const MvField *c0, const MvField *c1, const MvField *c2, MotionInfo *mi)
1145
2.75k
{
1146
2.75k
    if (c0 && c1 && c2) {
1147
0
        mi->pred_flag = 0;
1148
0
        for (int i = 0; i < 2; i++) {
1149
0
            PredFlag mask = i + 1;
1150
0
            if (compare_pf_ref_idx(c0, c1, c2, i)) {
1151
0
                mi->pred_flag |= mask;
1152
0
                mi->ref_idx[i] = c0->ref_idx[i];
1153
0
                mi->mv[i][0] = c0->mv[i];
1154
0
                mi->mv[i][1] = c1->mv[i];
1155
0
                mi->mv[i][2] = c2->mv[i];
1156
0
            }
1157
0
        }
1158
0
        if (mi->pred_flag) {
1159
0
            if (mi->pred_flag == PF_BI)
1160
0
                mi->bcw_idx = c0->bcw_idx;
1161
0
            mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1162
0
            return 1;
1163
0
        }
1164
0
    }
1165
2.75k
    return 0;
1166
2.75k
}
1167
1168
static int affine_merge_const2(const MvField *c0, const MvField *c1, const MvField *c3, MotionInfo *mi)
1169
2.75k
{
1170
2.75k
    if (c0 && c1 && c3) {
1171
0
        mi->pred_flag = 0;
1172
0
        for (int i = 0; i < 2; i++) {
1173
0
            PredFlag mask = i + 1;
1174
0
            if (compare_pf_ref_idx(c0, c1, c3, i)) {
1175
0
                mi->pred_flag |= mask;
1176
0
                mi->ref_idx[i] = c0->ref_idx[i];
1177
0
                mi->mv[i][0] = c0->mv[i];
1178
0
                mi->mv[i][1] = c1->mv[i];
1179
0
                mi->mv[i][2].x = c3->mv[i].x + c0->mv[i].x - c1->mv[i].x;
1180
0
                mi->mv[i][2].y = c3->mv[i].y + c0->mv[i].y - c1->mv[i].y;
1181
0
                ff_vvc_clip_mv(&mi->mv[i][2]);
1182
0
            }
1183
0
        }
1184
0
        if (mi->pred_flag) {
1185
0
            mi->bcw_idx = mi->pred_flag == PF_BI ? c0->bcw_idx : 0;
1186
0
            mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1187
0
            return 1;
1188
0
        }
1189
0
    }
1190
2.75k
    return 0;
1191
2.75k
}
1192
1193
static int affine_merge_const3(const MvField *c0, const MvField *c2, const MvField *c3, MotionInfo *mi)
1194
2.75k
{
1195
2.75k
    if (c0 && c2 && c3) {
1196
0
        mi->pred_flag = 0;
1197
0
        for (int i = 0; i < 2; i++) {
1198
0
            PredFlag mask = i + 1;
1199
0
            if (compare_pf_ref_idx(c0, c2, c3, i)) {
1200
0
                mi->pred_flag |= mask;
1201
0
                mi->ref_idx[i] = c0->ref_idx[i];
1202
0
                mi->mv[i][0] = c0->mv[i];
1203
0
                mi->mv[i][1].x = c3->mv[i].x + c0->mv[i].x - c2->mv[i].x;
1204
0
                mi->mv[i][1].y = c3->mv[i].y + c0->mv[i].y - c2->mv[i].y;
1205
0
                ff_vvc_clip_mv(&mi->mv[i][1]);
1206
0
                mi->mv[i][2] = c2->mv[i];
1207
0
            }
1208
0
        }
1209
0
        if (mi->pred_flag) {
1210
0
            mi->bcw_idx = mi->pred_flag == PF_BI ? c0->bcw_idx : 0;
1211
0
            mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1212
0
            return 1;
1213
0
        }
1214
0
    }
1215
2.75k
    return 0;
1216
2.75k
}
1217
1218
static int affine_merge_const4(const MvField *c1, const MvField *c2, const MvField *c3, MotionInfo *mi)
1219
2.75k
{
1220
2.75k
    if (c1 && c2 && c3) {
1221
0
        mi->pred_flag = 0;
1222
0
        for (int i = 0; i < 2; i++) {
1223
0
            PredFlag mask = i + 1;
1224
0
            if (compare_pf_ref_idx(c1, c2, c3, i)) {
1225
0
                mi->pred_flag |= mask;
1226
0
                mi->ref_idx[i] = c1->ref_idx[i];
1227
0
                mi->mv[i][0].x = c1->mv[i].x + c2->mv[i].x - c3->mv[i].x;
1228
0
                mi->mv[i][0].y = c1->mv[i].y + c2->mv[i].y - c3->mv[i].y;
1229
0
                ff_vvc_clip_mv(&mi->mv[i][0]);
1230
0
                mi->mv[i][1] = c1->mv[i];
1231
0
                mi->mv[i][2] = c2->mv[i];
1232
0
            }
1233
0
        }
1234
0
        if (mi->pred_flag) {
1235
0
            mi->bcw_idx = mi->pred_flag == PF_BI ? c1->bcw_idx : 0;
1236
0
            mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1237
0
            return 1;
1238
0
        }
1239
0
    }
1240
2.75k
    return 0;
1241
2.75k
}
1242
1243
static int affine_merge_const5(const MvField *c0, const MvField *c1, MotionInfo *mi)
1244
3.84k
{
1245
3.84k
    if (c0 && c1) {
1246
0
        mi->pred_flag = 0;
1247
0
        for (int i = 0; i < 2; i++) {
1248
0
            PredFlag mask = i + 1;
1249
0
            if (compare_pf_ref_idx(c0, c1, NULL, i)) {
1250
0
                mi->pred_flag |= mask;
1251
0
                mi->ref_idx[i] = c0->ref_idx[i];
1252
0
                mi->mv[i][0] = c0->mv[i];
1253
0
                mi->mv[i][1] = c1->mv[i];
1254
0
            }
1255
0
        }
1256
0
        if (mi->pred_flag) {
1257
0
            if (mi->pred_flag == PF_BI)
1258
0
                mi->bcw_idx = c0->bcw_idx;
1259
0
            mi->motion_model_idc = MOTION_4_PARAMS_AFFINE;
1260
0
            return 1;
1261
0
        }
1262
0
    }
1263
3.84k
    return 0;
1264
3.84k
}
1265
1266
static int affine_merge_const6(const MvField* c0, const MvField* c2, const int cb_width, const int cb_height, MotionInfo *mi)
1267
3.84k
{
1268
3.84k
    if (c0 && c2) {
1269
0
        const int shift = 7 + av_log2(cb_width) - av_log2(cb_height);
1270
0
        mi->pred_flag = 0;
1271
0
        for (int i = 0; i < 2; i++) {
1272
0
            PredFlag mask = i + 1;
1273
0
            if (compare_pf_ref_idx(c0, c2, NULL, i)) {
1274
0
                mi->pred_flag |= mask;
1275
0
                mi->ref_idx[i] = c0->ref_idx[i];
1276
0
                mi->mv[i][0] = c0->mv[i];
1277
0
                mi->mv[i][1].x = (c0->mv[i].x * (1 << 7)) + ((c2->mv[i].y - c0->mv[i].y) * (1 << shift));
1278
0
                mi->mv[i][1].y = (c0->mv[i].y * (1 << 7)) - ((c2->mv[i].x - c0->mv[i].x) * (1 << shift));
1279
0
                ff_vvc_round_mv(&mi->mv[i][1], 0, 7);
1280
0
                ff_vvc_clip_mv(&mi->mv[i][1]);
1281
0
            }
1282
0
        }
1283
0
        if (mi->pred_flag) {
1284
0
            if (mi->pred_flag == PF_BI)
1285
0
                mi->bcw_idx = c0->bcw_idx;
1286
0
            mi->motion_model_idc = MOTION_4_PARAMS_AFFINE;
1287
0
            return 1;
1288
0
        }
1289
0
    }
1290
3.84k
    return 0;
1291
3.84k
}
1292
1293
static void affine_merge_zero_motion(const VVCLocalContext *lc, MotionInfo *mi)
1294
4.04k
{
1295
4.04k
    const CodingUnit *cu = lc->cu;
1296
1297
4.04k
    memset(mi, 0, sizeof(*mi));
1298
4.04k
    mi->pred_flag    = PF_L0 + (IS_B(lc->sc->sh.r) << 1);
1299
4.04k
    mi->motion_model_idc = MOTION_4_PARAMS_AFFINE;
1300
4.04k
    mi->num_sb_x = cu->cb_width >> MIN_PU_LOG2;
1301
4.04k
    mi->num_sb_y = cu->cb_height >> MIN_PU_LOG2;
1302
4.04k
}
1303
1304
//8.5.5.6 Derivation process for constructed affine control point motion vector merging candidates
1305
static int affine_merge_const_candidates(const VVCLocalContext *lc, MotionInfo *mi,
1306
    NeighbourContext *nctx, const int merge_subblock_idx, int num_cands)
1307
3.84k
{
1308
3.84k
    const VVCFrameContext *fc   = lc->fc;
1309
3.84k
    const CodingUnit *cu        = lc->cu;
1310
3.84k
    const NeighbourIdx tl[]     = { B2, B3, A2 };
1311
3.84k
    const NeighbourIdx tr[]     = { B1, B0};
1312
3.84k
    const NeighbourIdx bl[]     = { A1, A0};
1313
3.84k
    const MvField *c0, *c1, *c2;
1314
1315
3.84k
    c0 = DERIVE_CORNER_MV(tl);
1316
3.84k
    c1 = DERIVE_CORNER_MV(tr);
1317
3.84k
    c2 = DERIVE_CORNER_MV(bl);
1318
1319
3.84k
    if (fc->ps.sps->r->sps_6param_affine_enabled_flag) {
1320
2.75k
        MvField corner3, *c3 = NULL;
1321
        //Const1
1322
2.75k
        if (affine_merge_const1(c0, c1, c2, mi)) {
1323
0
            if (merge_subblock_idx == num_cands)
1324
0
                return 1;
1325
0
            num_cands++;
1326
0
        }
1327
1328
2.75k
        memset(&corner3, 0, sizeof(corner3));
1329
2.75k
        if (fc->ps.ph.r->ph_temporal_mvp_enabled_flag){
1330
2.67k
            const int available_l0 = temporal_luma_motion_vector(lc, 0, corner3.mv + 0, 0, 0, 0);
1331
2.67k
            const int available_l1 = (lc->sc->sh.r->sh_slice_type == VVC_SLICE_TYPE_B) ?
1332
2.23k
                temporal_luma_motion_vector(lc, 0, corner3.mv + 1, 1, 0, 0) : 0;
1333
1334
2.67k
            corner3.pred_flag = available_l0 + (available_l1 << 1);
1335
2.67k
            if (corner3.pred_flag)
1336
0
                c3 = &corner3;
1337
2.67k
        }
1338
1339
        //Const2
1340
2.75k
        if (affine_merge_const2(c0, c1, c3, mi)) {
1341
0
            if (merge_subblock_idx == num_cands)
1342
0
                return 1;
1343
0
            num_cands++;
1344
0
        }
1345
1346
        //Const3
1347
2.75k
        if (affine_merge_const3(c0, c2, c3, mi)) {
1348
0
           if (merge_subblock_idx == num_cands)
1349
0
               return 1;
1350
0
           num_cands++;
1351
0
        }
1352
1353
        //Const4
1354
2.75k
        if (affine_merge_const4(c1, c2, c3, mi)) {
1355
0
           if (merge_subblock_idx == num_cands)
1356
0
               return 1;
1357
0
           num_cands++;
1358
0
        }
1359
2.75k
    }
1360
1361
    //Const5
1362
3.84k
    if (affine_merge_const5(c0, c1, mi)) {
1363
0
        if (merge_subblock_idx == num_cands)
1364
0
            return 1;
1365
0
        num_cands++;
1366
0
    }
1367
1368
3.84k
    if (affine_merge_const6(c0, c2, cu->cb_width, cu->cb_height, mi)) {
1369
0
        if (merge_subblock_idx == num_cands)
1370
0
            return 1;
1371
0
    }
1372
3.84k
    return 0;
1373
3.84k
}
1374
1375
//8.5.5.2 Derivation process for motion vectors and reference indices in subblock merge mode
1376
//return 1 if candidate is SbCol
1377
static int sb_mv_merge_mode(const VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
1378
4.06k
{
1379
4.06k
    const VVCSPS *sps       = lc->fc->ps.sps;
1380
4.06k
    const CodingUnit *cu    = lc->cu;
1381
4.06k
    MotionInfo *mi          = &pu->mi;
1382
4.06k
    int num_cands           = 0;
1383
4.06k
    NeighbourContext nctx;
1384
1385
4.06k
    init_neighbour_context(&nctx, lc);
1386
1387
    //SbCol
1388
4.06k
    if (sb_temporal_merge_candidate(lc, &nctx, pu)) {
1389
25
        if (merge_subblock_idx == num_cands)
1390
25
            return 1;
1391
0
        num_cands++;
1392
0
    }
1393
1394
4.04k
    pu->inter_affine_flag = 1;
1395
4.04k
    mi->num_sb_x  = cu->cb_width >> MIN_PU_LOG2;
1396
4.04k
    mi->num_sb_y  = cu->cb_height >> MIN_PU_LOG2;
1397
1398
4.04k
    if (sps->r->sps_affine_enabled_flag) {
1399
3.84k
        const NeighbourIdx ak[] = { A0, A1 };
1400
3.84k
        const NeighbourIdx bk[] = { B0, B1, B2 };
1401
        //A
1402
3.84k
        if (AFFINE_MERGE_FROM_NBS(ak)) {
1403
0
            if (merge_subblock_idx == num_cands)
1404
0
                return 0;
1405
0
            num_cands++;
1406
0
        }
1407
1408
        //B
1409
3.84k
        if (AFFINE_MERGE_FROM_NBS(bk)) {
1410
0
            if (merge_subblock_idx == num_cands)
1411
0
                return 0;
1412
0
            num_cands++;
1413
0
        }
1414
1415
        //Const1 to Const6
1416
3.84k
        if (affine_merge_const_candidates(lc, mi, &nctx, merge_subblock_idx, num_cands))
1417
0
            return 0;
1418
3.84k
    }
1419
    //Zero
1420
4.04k
    affine_merge_zero_motion(lc, mi);
1421
4.04k
    return 0;
1422
4.04k
}
1423
1424
void ff_vvc_sb_mv_merge_mode(VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
1425
4.06k
{
1426
4.06k
    const CodingUnit *cu = lc->cu;
1427
4.06k
    ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1428
4.06k
    if (!sb_mv_merge_mode(lc, merge_subblock_idx, pu)) {
1429
4.04k
        ff_vvc_store_sb_mvs(lc, pu);
1430
4.04k
    }
1431
4.06k
}
1432
1433
static int mvp_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand,
1434
    const int lx, const int8_t *ref_idx, Mv *mv)
1435
3.81k
{
1436
3.81k
    const VVCFrameContext *fc       = lc->fc;
1437
3.81k
    const RefPicList *rpl           = lc->sc->rpl;
1438
3.81k
    const int min_pu_width          = fc->ps.pps->min_pu_width;
1439
3.81k
    const MvField* tab_mvf          = fc->tab.mvf;
1440
3.81k
    const MvField *mvf              = &TAB_MVF(x_cand, y_cand);
1441
3.81k
    const PredFlag maskx = lx + 1;
1442
3.81k
    const int poc = rpl[lx].refs[ref_idx[lx]].poc;
1443
3.81k
    int available = 0;
1444
1445
3.81k
    if ((mvf->pred_flag & maskx) && rpl[lx].refs[mvf->ref_idx[lx]].poc == poc) {
1446
3.59k
        available = 1;
1447
3.59k
        *mv = mvf->mv[lx];
1448
3.59k
    } else {
1449
216
        const int ly = !lx;
1450
216
        const PredFlag masky = ly + 1;
1451
216
        if ((mvf->pred_flag & masky) && rpl[ly].refs[mvf->ref_idx[ly]].poc == poc) {
1452
105
            available = 1;
1453
105
            *mv = mvf->mv[ly];
1454
105
        }
1455
216
    }
1456
1457
3.81k
    return available;
1458
3.81k
}
1459
1460
static int affine_mvp_candidate(const VVCLocalContext *lc,
1461
    const int x_cand, const int y_cand, const int lx, const int8_t *ref_idx,
1462
    Mv *cps, const int num_cp)
1463
0
{
1464
0
    const VVCFrameContext *fc = lc->fc;
1465
0
    int x_nb, y_nb, nbw, nbh, motion_model_idc, available = 0;
1466
1467
0
    motion_model_idc = affine_neighbour_cb(fc, x_cand, y_cand, &x_nb, &y_nb, &nbw, &nbh);
1468
0
    if (motion_model_idc) {
1469
0
        const int min_pu_width = fc->ps.pps->min_pu_width;
1470
0
        const MvField* tab_mvf = fc->tab.mvf;
1471
0
        const MvField *mvf = &TAB_MVF(x_nb, y_nb);
1472
0
        RefPicList* rpl = lc->sc->rpl;
1473
0
        const PredFlag maskx = lx + 1;
1474
0
        const int poc = rpl[lx].refs[ref_idx[lx]].poc;
1475
1476
0
        if ((mvf->pred_flag & maskx) && rpl[lx].refs[mvf->ref_idx[lx]].poc == poc) {
1477
0
            available = 1;
1478
0
            affine_cps_from_nb(lc, x_nb, y_nb, nbw, nbh, lx, cps, num_cp);
1479
0
        } else {
1480
0
            const int ly = !lx;
1481
0
            const PredFlag masky = ly + 1;
1482
0
            if ((mvf->pred_flag & masky) && rpl[ly].refs[mvf->ref_idx[ly]].poc == poc) {
1483
0
                available = 1;
1484
0
                affine_cps_from_nb(lc, x_nb, y_nb, nbw, nbh, ly, cps, num_cp);
1485
0
            }
1486
0
        }
1487
1488
0
    }
1489
0
    return available;
1490
0
}
1491
1492
static int mvp_from_nbs(NeighbourContext *ctx,
1493
    const NeighbourIdx *nbs, const int num_nbs, const int lx, const int8_t *ref_idx, const int amvr_shift,
1494
    Mv *cps, const int num_cps)
1495
81.4k
{
1496
81.4k
    const VVCLocalContext *lc   = ctx->lc;
1497
81.4k
    int available               = 0;
1498
1499
278k
    for (int i = 0; i < num_nbs; i++) {
1500
200k
        Neighbour *n = &ctx->neighbours[nbs[i]];
1501
200k
        if (check_available(n, lc, 0)) {
1502
3.81k
            if (num_cps > 1)
1503
0
                available = affine_mvp_candidate(lc, n->x, n->y, lx, ref_idx, cps, num_cps);
1504
3.81k
            else
1505
3.81k
                available = mvp_candidate(lc, n->x, n->y, lx, ref_idx, cps);
1506
3.81k
            if (available) {
1507
7.40k
                for (int c = 0; c < num_cps; c++)
1508
3.70k
                    ff_vvc_round_mv(cps + c, amvr_shift, amvr_shift);
1509
3.70k
                return 1;
1510
3.70k
            }
1511
3.81k
        }
1512
200k
    }
1513
77.7k
    return 0;
1514
81.4k
}
1515
1516
//get mvp from neighbours
1517
#define AFFINE_MVP_FROM_NBS(nbs)                                                         \
1518
0
    mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, cps, num_cp)  \
1519
1520
#define MVP_FROM_NBS(nbs)                                                                \
1521
81.4k
    mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, mv, 1)        \
1522
1523
static int mvp_spatial_candidates(const VVCLocalContext *lc,
1524
    const int mvp_lx_flag, const int lx, const int8_t* ref_idx, const int amvr_shift,
1525
    Mv* mv, int *nb_merge_cand)
1526
40.9k
{
1527
40.9k
    const NeighbourIdx ak[] = { A0, A1 };
1528
40.9k
    const NeighbourIdx bk[] = { B0, B1, B2 };
1529
40.9k
    NeighbourContext nctx;
1530
40.9k
    int available_a, num_cands = 0;
1531
40.9k
    LOCAL_ALIGNED_8(Mv, mv_a, [1]);
1532
1533
40.9k
    init_neighbour_context(&nctx, lc);
1534
1535
40.9k
    available_a = MVP_FROM_NBS(ak);
1536
40.9k
    if (available_a) {
1537
843
        if (mvp_lx_flag == num_cands)
1538
488
            return 1;
1539
355
        num_cands++;
1540
355
        *mv_a = *mv;
1541
355
    }
1542
40.4k
    if (MVP_FROM_NBS(bk)) {
1543
2.86k
        if (!available_a || !IS_SAME_MV(mv_a, mv)) {
1544
2.84k
            if (mvp_lx_flag == num_cands)
1545
1.87k
                return 1;
1546
971
            num_cands++;
1547
971
        }
1548
2.86k
    }
1549
38.6k
    *nb_merge_cand = num_cands;
1550
38.6k
    return 0;
1551
40.4k
}
1552
1553
static int mvp_temporal_candidates(const VVCLocalContext* lc,
1554
    const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift,
1555
    Mv* mv, int *num_cands)
1556
38.6k
{
1557
38.6k
    if (temporal_luma_motion_vector(lc, ref_idx[lx], mv, lx, 1, 0)) {
1558
140
        if (mvp_lx_flag == *num_cands) {
1559
122
            ff_vvc_round_mv(mv, amvr_shift, amvr_shift);
1560
122
            return 1;
1561
122
        }
1562
18
        (*num_cands)++;
1563
18
    }
1564
38.5k
    return 0;
1565
1566
38.6k
}
1567
1568
static int mvp_history_candidates(const VVCLocalContext *lc,
1569
    const int mvp_lx_flag, const int lx, const int8_t ref_idx, const int amvr_shift,
1570
    Mv *mv, int num_cands)
1571
38.5k
{
1572
38.5k
    const EntryPoint* ep            = lc->ep;
1573
38.5k
    const RefPicList* rpl           = lc->sc->rpl;
1574
38.5k
    const int poc                   = rpl[lx].refs[ref_idx].poc;
1575
1576
38.5k
    if (ep->num_hmvp == 0)
1577
37.6k
        return 0;
1578
878
    for (int i = 1; i <= FFMIN(4, ep->num_hmvp); i++) {
1579
805
        const MvField* h = &ep->hmvp[i - 1];
1580
1.04k
        for (int j = 0; j < 2; j++) {
1581
973
            const int ly = (j ? !lx : lx);
1582
973
            PredFlag mask = PF_L0 + ly;
1583
973
            if ((h->pred_flag & mask) && poc == rpl[ly].refs[h->ref_idx[ly]].poc) {
1584
732
                if (mvp_lx_flag == num_cands) {
1585
732
                    *mv = h->mv[ly];
1586
732
                    ff_vvc_round_mv(mv, amvr_shift, amvr_shift);
1587
732
                    return 1;
1588
732
                }
1589
0
                num_cands++;
1590
0
            }
1591
973
        }
1592
805
    }
1593
73
    return 0;
1594
805
}
1595
1596
//8.5.2.8 Derivation process for luma motion vector prediction
1597
static void mvp(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx,
1598
    const int8_t *ref_idx, const int amvr_shift, Mv *mv)
1599
40.9k
{
1600
40.9k
    int num_cands;
1601
1602
40.9k
    if (mvp_spatial_candidates(lc, mvp_lx_flag, lx, ref_idx, amvr_shift, mv, &num_cands))
1603
2.35k
        return;
1604
1605
38.6k
    if (mvp_temporal_candidates(lc, mvp_lx_flag, lx, ref_idx, amvr_shift, mv, &num_cands))
1606
122
        return;
1607
1608
38.5k
    if (mvp_history_candidates(lc, mvp_lx_flag, lx, ref_idx[lx], amvr_shift, mv, num_cands))
1609
732
        return;
1610
1611
37.7k
    memset(mv, 0, sizeof(*mv));
1612
37.7k
}
1613
1614
void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift,  MotionInfo *mi)
1615
38.6k
{
1616
38.6k
    const CodingUnit *cu    = lc->cu;
1617
38.6k
    mi->num_sb_x            = 1;
1618
38.6k
    mi->num_sb_y            = 1;
1619
1620
38.6k
    ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1621
38.6k
    if (mi->pred_flag != PF_L1)
1622
36.4k
        mvp(lc, mvp_lx_flag[L0], L0, mi->ref_idx, amvr_shift, &mi->mv[L0][0]);
1623
38.6k
    if (mi->pred_flag != PF_L0)
1624
4.49k
        mvp(lc, mvp_lx_flag[L1], L1, mi->ref_idx, amvr_shift, &mi->mv[L1][0]);
1625
38.6k
}
1626
1627
static int ibc_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *const cand_list, int *nb_merge_cand)
1628
348k
{
1629
348k
    const CodingUnit *cu      = lc->cu;
1630
348k
    const VVCFrameContext *fc = lc->fc;
1631
348k
    const int min_pu_width    = fc->ps.pps->min_pu_width;
1632
348k
    const MvField *tab_mvf    = fc->tab.mvf;
1633
348k
    const int is_gt4by4       = (cu->cb_width * cu->cb_height) > 16;
1634
348k
    int num_cands             = 0;
1635
1636
348k
    NeighbourContext nctx;
1637
348k
    Neighbour *a1 = &nctx.neighbours[A1];
1638
348k
    Neighbour *b1 = &nctx.neighbours[B1];
1639
1640
348k
    if (!is_gt4by4) {
1641
217k
        *nb_merge_cand = 0;
1642
217k
        return 0;
1643
217k
    }
1644
1645
130k
    init_neighbour_context(&nctx, lc);
1646
1647
130k
    if (check_available(a1, lc, 0)) {
1648
5.58k
        cand_list[num_cands++] = TAB_MVF(a1->x, a1->y).mv[L0];
1649
5.58k
        if (num_cands > merge_idx)
1650
4.64k
            return 1;
1651
5.58k
    }
1652
125k
    if (check_available(b1, lc, 0)) {
1653
1.33k
        const MvField *mvf = &TAB_MVF(b1->x, b1->y);
1654
1.33k
        if (!num_cands || !IS_SAME_MV(&cand_list[0], mvf->mv)) {
1655
1.27k
            cand_list[num_cands++] = mvf->mv[L0];
1656
1.27k
            if (num_cands > merge_idx)
1657
758
                return 1;
1658
1.27k
        }
1659
1.33k
    }
1660
1661
125k
    *nb_merge_cand = num_cands;
1662
125k
    return 0;
1663
125k
}
1664
1665
static int ibc_history_candidates(const VVCLocalContext *lc,
1666
    const int merge_idx, Mv *cand_list, int *nb_merge_cand)
1667
342k
{
1668
342k
    const CodingUnit *cu = lc->cu;
1669
342k
    const EntryPoint *ep = lc->ep;
1670
342k
    const int is_gt4by4  = (cu->cb_width * cu->cb_height) > 16;
1671
342k
    int num_cands        = *nb_merge_cand;
1672
1673
344k
    for (int i = 1; i <= ep->num_hmvp_ibc; i++) {
1674
2.77k
        int same_motion = 0;
1675
2.77k
        const MvField *mvf = &ep->hmvp_ibc[ep->num_hmvp_ibc - i];
1676
3.24k
        for (int j = 0; j < *nb_merge_cand; j++) {
1677
1.20k
            same_motion = is_gt4by4 && i == 1 && IS_SAME_MV(&mvf->mv[L0], &cand_list[j]);
1678
1.20k
            if (same_motion)
1679
726
                break;
1680
1.20k
        }
1681
2.77k
        if (!same_motion) {
1682
2.04k
            cand_list[num_cands++] = mvf->mv[L0];
1683
2.04k
            if (num_cands > merge_idx)
1684
1.17k
                return 1;
1685
2.04k
        }
1686
2.77k
    }
1687
1688
341k
    *nb_merge_cand = num_cands;
1689
341k
    return 0;
1690
342k
}
1691
1692
438k
#define MV_BITS 18
1693
438k
#define IBC_SHIFT(v) ((v) >= (1 << (MV_BITS - 1)) ? ((v) - (1 << MV_BITS)) : (v))
1694
1695
static inline void ibc_add_mvp(Mv *mv, Mv *mvp, const int amvr_shift)
1696
219k
{
1697
219k
    ff_vvc_round_mv(mv, amvr_shift, 0);
1698
219k
    ff_vvc_round_mv(mvp, amvr_shift, amvr_shift);
1699
219k
    mv->x = IBC_SHIFT(mv->x + mvp->x);
1700
219k
    mv->y = IBC_SHIFT(mv->y + mvp->y);
1701
219k
}
1702
1703
static void ibc_merge_candidates(VVCLocalContext *lc, const int merge_idx, Mv *mv)
1704
348k
{
1705
348k
    const CodingUnit *cu = lc->cu;
1706
348k
    LOCAL_ALIGNED_8(Mv, cand_list, [MRG_MAX_NUM_CANDS]);
1707
348k
    int nb_cands;
1708
1709
348k
    ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1710
348k
    if (ibc_spatial_candidates(lc, merge_idx, cand_list, &nb_cands) ||
1711
342k
        ibc_history_candidates(lc, merge_idx, cand_list, &nb_cands)) {
1712
6.58k
        *mv = cand_list[merge_idx];
1713
6.58k
        return;
1714
6.58k
    }
1715
1716
    //zero mv
1717
341k
    memset(mv, 0, sizeof(*mv));
1718
341k
}
1719
1720
static int ibc_check_mv(VVCLocalContext *lc, Mv *mv)
1721
348k
{
1722
348k
    const VVCFrameContext *fc = lc->fc;
1723
348k
    const VVCSPS *sps         = lc->fc->ps.sps;
1724
348k
    const CodingUnit *cu      = lc->cu;
1725
348k
    const Mv *bv              = &cu->pu.mi.mv[L0][0];
1726
1727
348k
    if (sps->ctb_size_y < ((cu->y0 + (bv->y >> 4)) & (sps->ctb_size_y - 1)) + cu->cb_height) {
1728
17.8k
        av_log(fc->log_ctx, AV_LOG_ERROR, "IBC region spans multiple CTBs.\n");
1729
17.8k
        return AVERROR_INVALIDDATA;
1730
17.8k
    }
1731
1732
330k
    return 0;
1733
348k
}
1734
1735
int ff_vvc_mvp_ibc(VVCLocalContext *lc, const int mvp_l0_flag, const int amvr_shift, Mv *mv)
1736
219k
{
1737
219k
    LOCAL_ALIGNED_8(Mv, mvp, [1]);
1738
1739
219k
    ibc_merge_candidates(lc, mvp_l0_flag, mvp);
1740
219k
    ibc_add_mvp(mv, mvp, amvr_shift);
1741
219k
    return ibc_check_mv(lc, mv);
1742
219k
}
1743
1744
int ff_vvc_luma_mv_merge_ibc(VVCLocalContext *lc, const int merge_idx, Mv *mv)
1745
128k
{
1746
128k
    ibc_merge_candidates(lc, merge_idx, mv);
1747
128k
    return ibc_check_mv(lc, mv);
1748
128k
}
1749
1750
static int affine_mvp_constructed_cp(NeighbourContext *ctx,
1751
    const NeighbourIdx *neighbour, const int num_neighbour,
1752
    const int lx, const int8_t ref_idx, const int amvr_shift, Mv *cp)
1753
0
{
1754
0
    const VVCLocalContext *lc       = ctx->lc;
1755
0
    const VVCFrameContext *fc       = lc->fc;
1756
0
    const MvField *tab_mvf          = fc->tab.mvf;
1757
0
    const int min_pu_width          = fc->ps.pps->min_pu_width;
1758
0
    const RefPicList* rpl           = lc->sc->rpl;
1759
0
    int available                   = 0;
1760
1761
0
    for (int i = 0; i < num_neighbour; i++) {
1762
0
        Neighbour *n = &ctx->neighbours[neighbour[i]];
1763
0
        if (check_available(n, ctx->lc, 0)) {
1764
0
            const PredFlag maskx = lx + 1;
1765
0
            const MvField* mvf = &TAB_MVF(n->x, n->y);
1766
0
            const int poc = rpl[lx].refs[ref_idx].poc;
1767
0
            if ((mvf->pred_flag & maskx) && rpl[lx].refs[mvf->ref_idx[lx]].poc == poc) {
1768
0
                available = 1;
1769
0
                *cp = mvf->mv[lx];
1770
0
            } else {
1771
0
                const int ly = !lx;
1772
0
                const PredFlag masky = ly + 1;
1773
0
                if ((mvf->pred_flag & masky) && rpl[ly].refs[mvf->ref_idx[ly]].poc == poc) {
1774
0
                    available = 1;
1775
0
                    *cp = mvf->mv[ly];
1776
0
                }
1777
0
            }
1778
0
            if (available) {
1779
0
                ff_vvc_round_mv(cp, amvr_shift, amvr_shift);
1780
0
                return 1;
1781
0
            }
1782
0
        }
1783
0
    }
1784
0
    return 0;
1785
0
}
1786
1787
#define AFFINE_MVP_CONSTRUCTED_CP(cands, cp)                                    \
1788
0
    affine_mvp_constructed_cp(nctx, cands, FF_ARRAY_ELEMS(cands), lx, ref_idx,  \
1789
0
        amvr_shift, cp)
1790
1791
//8.5.5.8 Derivation process for constructed affine control point motion vector prediction candidates
1792
static int affine_mvp_const1(NeighbourContext* nctx,
1793
    const int lx, const int8_t ref_idx, const int amvr_shift,
1794
    Mv *cps, int *available)
1795
0
{
1796
0
    const NeighbourIdx tl[] = { B2, B3, A2 };
1797
0
    const NeighbourIdx tr[] = { B1, B0 };
1798
0
    const NeighbourIdx bl[] = { A1, A0 };
1799
1800
0
    available[0] = AFFINE_MVP_CONSTRUCTED_CP(tl, cps + 0);
1801
0
    available[1] = AFFINE_MVP_CONSTRUCTED_CP(tr, cps + 1);
1802
0
    available[2] = AFFINE_MVP_CONSTRUCTED_CP(bl, cps + 2);
1803
0
    return available[0] && available[1];
1804
0
}
1805
1806
//8.5.5.7 item 7
1807
static void affine_mvp_const2(const int idx, Mv *cps, const int num_cp)
1808
0
{
1809
0
    const Mv mv = cps[idx];
1810
0
    for (int j = 0; j < num_cp; j++)
1811
0
        cps[j] = mv;
1812
0
}
1813
1814
//8.5.5.7 Derivation process for luma affine control point motion vector predictors
1815
static void affine_mvp(const VVCLocalContext *lc,
1816
    const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift,
1817
    MotionModelIdc motion_model_idc, Mv *cps)
1818
0
{
1819
0
    const NeighbourIdx ak[] = { A0, A1 };
1820
0
    const NeighbourIdx bk[] = { B0, B1, B2 };
1821
0
    const int num_cp = motion_model_idc + 1;
1822
0
    NeighbourContext nctx;
1823
0
    int available[MAX_CONTROL_POINTS];
1824
0
    int num_cands    = 0;
1825
1826
0
    init_neighbour_context(&nctx, lc);
1827
    //Ak
1828
0
    if (AFFINE_MVP_FROM_NBS(ak)) {
1829
0
        if (mvp_lx_flag == num_cands)
1830
0
            return;
1831
0
        num_cands++;
1832
0
    }
1833
    //Bk
1834
0
    if (AFFINE_MVP_FROM_NBS(bk)) {
1835
0
        if (mvp_lx_flag == num_cands)
1836
0
            return;
1837
0
        num_cands++;
1838
0
    }
1839
1840
    //Const1
1841
0
    if (affine_mvp_const1(&nctx, lx, ref_idx[lx], amvr_shift, cps, available)) {
1842
0
        if (available[2] || motion_model_idc == MOTION_4_PARAMS_AFFINE) {
1843
0
            if (mvp_lx_flag == num_cands)
1844
0
                return;
1845
0
            num_cands++;
1846
0
        }
1847
0
    }
1848
1849
    //Const2
1850
0
    for (int i = 2; i >= 0; i--) {
1851
0
        if (available[i]) {
1852
0
            if (mvp_lx_flag == num_cands) {
1853
0
                affine_mvp_const2(i, cps, num_cp);
1854
0
                return;
1855
0
            }
1856
0
            num_cands++;
1857
0
        }
1858
0
    }
1859
0
    if (temporal_luma_motion_vector(lc, ref_idx[lx], cps, lx, 1, 0)) {
1860
0
        if (mvp_lx_flag == num_cands) {
1861
0
            ff_vvc_round_mv(cps, amvr_shift, amvr_shift);
1862
0
            for (int i = 1; i < num_cp; i++)
1863
0
                cps[i] = cps[0];
1864
0
            return;
1865
0
        }
1866
0
        num_cands++;
1867
0
    }
1868
1869
    //Zero Mv
1870
0
    memset(cps, 0, num_cp * sizeof(Mv));
1871
0
}
1872
1873
void ff_vvc_affine_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift,  MotionInfo *mi)
1874
0
{
1875
0
    const CodingUnit *cu = lc->cu;
1876
1877
0
    mi->num_sb_x = cu->cb_width >> MIN_PU_LOG2;
1878
0
    mi->num_sb_y = cu->cb_height >> MIN_PU_LOG2;
1879
1880
0
    ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1881
0
    if (mi->pred_flag != PF_L1)
1882
0
        affine_mvp(lc, mvp_lx_flag[L0], L0, mi->ref_idx, amvr_shift, mi->motion_model_idc, &mi->mv[L0][0]);
1883
0
    if (mi->pred_flag != PF_L0)
1884
0
        affine_mvp(lc, mvp_lx_flag[L1], L1, mi->ref_idx, amvr_shift, mi->motion_model_idc, &mi->mv[L1][0]);
1885
0
}
1886
1887
//8.5.2.14 Rounding process for motion vectors
1888
void ff_vvc_round_mv(Mv *mv, const int lshift, const int rshift)
1889
473k
{
1890
473k
    if (rshift) {
1891
254k
        const int offset = 1 << (rshift - 1);
1892
254k
        mv->x = ((mv->x + offset - (mv->x >= 0)) >> rshift) * (1 << lshift);
1893
254k
        mv->y = ((mv->y + offset - (mv->y >= 0)) >> rshift) * (1 << lshift);
1894
254k
    } else {
1895
219k
        mv->x = mv->x * (1 << lshift);
1896
219k
        mv->y = mv->y * (1 << lshift);
1897
219k
    }
1898
473k
}
1899
1900
void ff_vvc_clip_mv(Mv *mv)
1901
30.4k
{
1902
30.4k
    mv->x = av_clip(mv->x, -(1 << 17), (1 << 17) - 1);
1903
30.4k
    mv->y = av_clip(mv->y, -(1 << 17), (1 << 17) - 1);
1904
30.4k
}
1905
1906
//8.5.2.1 Derivation process for motion vector components and reference indices
1907
static av_always_inline int is_greater_mer(const VVCFrameContext *fc, const int x0, const int y0, const int x0_br, const int y0_br)
1908
92.7k
{
1909
92.7k
    const uint8_t plevel = fc->ps.sps->log2_parallel_merge_level;
1910
1911
92.7k
    return x0_br >> plevel > x0 >> plevel &&
1912
83.5k
           y0_br >> plevel > y0 >> plevel;
1913
92.7k
}
1914
1915
static void update_hmvp(MvField *hmvp, int *num_hmvp, const MvField *mvf,
1916
    int (*compare)(const MvField *n, const MvField *o))
1917
204k
{
1918
204k
    int i;
1919
239k
    for (i = 0; i < *num_hmvp; i++) {
1920
51.0k
        if (compare(mvf, hmvp + i)) {
1921
16.6k
            (*num_hmvp)--;
1922
16.6k
            break;
1923
16.6k
        }
1924
51.0k
    }
1925
204k
    if (i == MAX_NUM_HMVP_CANDS) {
1926
2.68k
        (*num_hmvp)--;
1927
2.68k
        i = 0;
1928
2.68k
    }
1929
1930
204k
    memmove(hmvp + i, hmvp + i + 1, (*num_hmvp - i) * sizeof(MvField));
1931
204k
    hmvp[(*num_hmvp)++] = *mvf;
1932
204k
}
1933
1934
static int compare_l0_mv(const MvField *n, const MvField *o)
1935
19.7k
{
1936
19.7k
    return IS_SAME_MV(&n->mv[L0], &o->mv[L0]);
1937
19.7k
}
1938
1939
//8.6.2.4 Derivation process for IBC history-based block vector candidates
1940
//8.5.2.16 Updating process for the history-based motion vector predictor candidate list
1941
void ff_vvc_update_hmvp(VVCLocalContext *lc, const MotionInfo *mi)
1942
423k
{
1943
423k
    const VVCFrameContext *fc   = lc->fc;
1944
423k
    const CodingUnit *cu        = lc->cu;
1945
423k
    const int min_pu_width      = fc->ps.pps->min_pu_width;
1946
423k
    const MvField *tab_mvf      = fc->tab.mvf;
1947
423k
    EntryPoint *ep              = lc->ep;
1948
1949
423k
    if (cu->pred_mode == MODE_IBC) {
1950
330k
        if (cu->cb_width * cu->cb_height <= 16)
1951
208k
            return;
1952
121k
        update_hmvp(ep->hmvp_ibc, &ep->num_hmvp_ibc, &TAB_MVF(cu->x0, cu->y0), compare_l0_mv);
1953
121k
    } else {
1954
92.7k
        if (!is_greater_mer(fc, cu->x0, cu->y0, cu->x0 + cu->cb_width, cu->y0 + cu->cb_height))
1955
9.26k
            return;
1956
83.4k
        update_hmvp(ep->hmvp, &ep->num_hmvp, &TAB_MVF(cu->x0, cu->y0), compare_mv_ref_idx);
1957
83.4k
    }
1958
423k
}
1959
1960
MvField* ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0)
1961
57.8k
{
1962
57.8k
    const int min_pu_width  = fc->ps.pps->min_pu_width;
1963
57.8k
    MvField* tab_mvf        = fc->tab.mvf;
1964
1965
57.8k
    return &TAB_MVF(x0, y0);
1966
57.8k
}