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