FFmpeg
vvc_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 "vvc_ctu.h"
24 #include "vvc_data.h"
25 #include "vvc_refs.h"
26 #include "vvc_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
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 {
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
40 static 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
57 static av_always_inline void mv_compression(Mv *motion)
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 
71 void 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
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 {
91  int cur_lt = refPicList[X].isLongTerm[refIdxLx];
92  int col_lt = refPicList_col[listCol].isLongTerm[refidxCol];
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].list[refidxCol];
102  cur_poc_diff = poc - refPicList[X].list[refIdxLx];
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 < rpl[j].nb_refs; i++) {
129  if (rpl[j].list[i] > 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  return 0;
149 
150  if (sb_flag){
151  if (X == 0) {
152  if (temp_col.pred_flag & PF_L0)
153  return CHECK_MVSET(0);
154  else if (ff_vvc_no_backward_pred_flag(lc) && (temp_col.pred_flag & PF_L1))
155  return CHECK_MVSET(1);
156  } else {
157  if (temp_col.pred_flag & PF_L1)
158  return CHECK_MVSET(1);
159  else if (ff_vvc_no_backward_pred_flag(lc) && (temp_col.pred_flag & PF_L0))
160  return CHECK_MVSET(0);
161  }
162  } else {
163  if (!(temp_col.pred_flag & PF_L0))
164  return CHECK_MVSET(1);
165  else if (temp_col.pred_flag == PF_L0)
166  return CHECK_MVSET(0);
167  else if (temp_col.pred_flag == PF_BI) {
169  if (X == 0)
170  return CHECK_MVSET(0);
171  else
172  return CHECK_MVSET(1);
173  } else {
174  if (!lc->sc->sh.r->sh_collocated_from_l0_flag)
175  return CHECK_MVSET(0);
176  else
177  return CHECK_MVSET(1);
178  }
179  }
180  }
181  return 0;
182 }
183 
184 #define TAB_MVF(x, y) \
185  tab_mvf[((y) >> MIN_PU_LOG2) * min_pu_width + ((x) >> MIN_PU_LOG2)]
186 
187 #define TAB_MVF_PU(v) \
188  TAB_MVF(x ## v, y ## v)
189 
190 #define TAB_CP_MV(lx, x, y) \
191  fc->tab.cp_mv[lx][((((y) >> min_cb_log2_size) * min_cb_width + ((x) >> min_cb_log2_size)) ) * MAX_CONTROL_POINTS]
192 
193 
194 #define DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag) \
195  derive_temporal_colocated_mvs(lc, temp_col, \
196  refIdxLx, mvLXCol, X, colPic, \
197  ff_vvc_get_ref_list(fc, ref, x, y), sb_flag)
198 
199 //8.5.2.11 Derivation process for temporal luma motion vector prediction
201  const int refIdxLx, Mv *mvLXCol, const int X, int check_center, int sb_flag)
202 {
203  const VVCFrameContext *fc = lc->fc;
204  const VVCSPS *sps = fc->ps.sps;
205  const CodingUnit *cu = lc->cu;
206  int x, y, colPic, availableFlagLXCol = 0;
207  int min_pu_width = fc->ps.pps->min_pu_width;
208  VVCFrame *ref = fc->ref->collocated_ref;
209  MvField *tab_mvf;
210  MvField temp_col;
211 
212  if (!ref) {
213  memset(mvLXCol, 0, sizeof(*mvLXCol));
214  return 0;
215  }
216 
217  if (!fc->ps.ph.r->ph_temporal_mvp_enabled_flag || (cu->cb_width * cu->cb_height <= 32))
218  return 0;
219 
220  tab_mvf = ref->tab_dmvr_mvf;
221  colPic = ref->poc;
222 
223  //bottom right collocated motion vector
224  x = cu->x0 + cu->cb_width;
225  y = cu->y0 + cu->cb_height;
226 
227  if (tab_mvf &&
228  (cu->y0 >> sps->ctb_log2_size_y) == (y >> sps->ctb_log2_size_y) &&
229  y < fc->ps.pps->height &&
230  x < fc->ps.pps->width) {
231  x &= ~7;
232  y &= ~7;
233  temp_col = TAB_MVF(x, y);
234  availableFlagLXCol = DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag);
235  }
236  if (check_center) {
237  // derive center collocated motion vector
238  if (tab_mvf && !availableFlagLXCol) {
239  x = cu->x0 + (cu->cb_width >> 1);
240  y = cu->y0 + (cu->cb_height >> 1);
241  x &= ~7;
242  y &= ~7;
243  temp_col = TAB_MVF(x, y);
244  availableFlagLXCol = DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag);
245  }
246  }
247  return availableFlagLXCol;
248 }
249 
250 void ff_vvc_set_mvf(const VVCLocalContext *lc, const int x0, const int y0, const int w, const int h, const MvField *mvf)
251 {
252  const VVCFrameContext *fc = lc->fc;
253  MvField *tab_mvf = fc->tab.mvf;
254  const int min_pu_width = fc->ps.pps->min_pu_width;
255  const int min_pu_size = 1 << MIN_PU_LOG2;
256  for (int dy = 0; dy < h; dy += min_pu_size) {
257  for (int dx = 0; dx < w; dx += min_pu_size) {
258  const int x = x0 + dx;
259  const int y = y0 + dy;
260  TAB_MVF(x, y) = *mvf;
261  }
262  }
263 }
264 
265 void ff_vvc_set_intra_mvf(const VVCLocalContext *lc, const int dmvr)
266 {
267  const VVCFrameContext *fc = lc->fc;
268  const CodingUnit *cu = lc->cu;
269  MvField *tab_mvf = dmvr ? fc->ref->tab_dmvr_mvf : fc->tab.mvf;
270  const int min_pu_width = fc->ps.pps->min_pu_width;
271  const int min_pu_size = 1 << MIN_PU_LOG2;
272  for (int dy = 0; dy < cu->cb_height; dy += min_pu_size) {
273  for (int dx = 0; dx < cu->cb_width; dx += min_pu_size) {
274  const int x = cu->x0 + dx;
275  const int y = cu->y0 + dy;
276  TAB_MVF(x, y).pred_flag = PF_INTRA;
277  }
278  }
279 }
280 
281 //cbProfFlagLX from 8.5.5.9 Derivation process for motion vector arrays from affine control point motion vectors
282 static int derive_cb_prof_flag_lx(const VVCLocalContext *lc, const PredictionUnit* pu, int lx, int is_fallback)
283 {
284  const MotionInfo* mi = &pu->mi;
285  const Mv* cp_mv = &mi->mv[lx][0];
286  if (lc->fc->ps.ph.r->ph_prof_disabled_flag || is_fallback)
287  return 0;
288  if (mi->motion_model_idc == MOTION_4_PARAMS_AFFINE) {
289  if (IS_SAME_MV(cp_mv, cp_mv + 1))
290  return 0;
291  }
292  if (mi->motion_model_idc == MOTION_6_PARAMS_AFFINE) {
293  if (IS_SAME_MV(cp_mv, cp_mv + 1) && IS_SAME_MV(cp_mv, cp_mv + 2))
294  return 0;
295  }
296  //fixme: RprConstraintsActiveFlag
297  return 1;
298 }
299 
300 typedef struct SubblockParams {
301  int d_hor_x;
302  int d_ver_x;
303  int d_hor_y;
304  int d_ver_y;
308 
309  int cb_width;
312 
313 static int is_fallback_mode(const SubblockParams *sp, const PredFlag pred_flag)
314 {
315  const int a = 4 * (2048 + sp->d_hor_x);
316  const int b = 4 * sp->d_hor_y;
317  const int c = 4 * (2048 + sp->d_ver_y);
318  const int d = 4 * sp->d_ver_x;
319  if (pred_flag == PF_BI) {
320  const int max_w4 = FFMAX(0, FFMAX(a, FFMAX(b, a + b)));
321  const int min_w4 = FFMIN(0, FFMIN(a, FFMIN(b, a + b)));
322  const int max_h4 = FFMAX(0, FFMAX(c, FFMAX(d, c + d)));
323  const int min_h4 = FFMIN(0, FFMIN(c, FFMIN(d, c + d)));
324  const int bx_wx4 = ((max_w4 - min_w4) >> 11) + 9;
325  const int bx_hx4 = ((max_h4 - min_h4) >> 11) + 9;
326  return bx_wx4 * bx_hx4 > 225;
327  } else {
328  const int bx_wxh = (FFABS(a) >> 11) + 9;
329  const int bx_hxh = (FFABS(d) >> 11) + 9;
330  const int bx_wxv = (FFABS(b) >> 11) + 9;
331  const int bx_hxv = (FFABS(c) >> 11) + 9;
332  if (bx_wxh * bx_hxh <= 165 && bx_wxv * bx_hxv <= 165)
333  return 0;
334  }
335  return 1;
336 }
337 
339  const int cb_width, const int cb_height, const int lx)
340 {
341  const int log2_cbw = av_log2(cb_width);
342  const int log2_cbh = av_log2(cb_height);
343  const Mv* cp_mv = mi->mv[lx];
344  const int num_cp_mv = mi->motion_model_idc + 1;
345  sp->d_hor_x = (cp_mv[1].x - cp_mv[0].x) * (1 << (MAX_CU_DEPTH - log2_cbw));
346  sp->d_ver_x = (cp_mv[1].y - cp_mv[0].y) * (1 << (MAX_CU_DEPTH - log2_cbw));
347  if (num_cp_mv == 3) {
348  sp->d_hor_y = (cp_mv[2].x - cp_mv[0].x) * (1 << (MAX_CU_DEPTH - log2_cbh));
349  sp->d_ver_y = (cp_mv[2].y - cp_mv[0].y) * (1 << (MAX_CU_DEPTH - log2_cbh));
350  } else {
351  sp->d_hor_y = -sp->d_ver_x;
352  sp->d_ver_y = sp->d_hor_x;
353  }
354  sp->mv_scale_hor = (cp_mv[0].x) * (1 << MAX_CU_DEPTH);
355  sp->mv_scale_ver = (cp_mv[0].y) * (1 << MAX_CU_DEPTH);
356  sp->cb_width = cb_width;
357  sp->cb_height = cb_height;
358  sp->is_fallback = is_fallback_mode(sp, mi->pred_flag);
359 }
360 
361 static void derive_subblock_diff_mvs(const VVCLocalContext *lc, PredictionUnit* pu, const SubblockParams* sp, const int lx)
362 {
363  pu->cb_prof_flag[lx] = derive_cb_prof_flag_lx(lc, pu, lx, sp->is_fallback);
364  if (pu->cb_prof_flag[lx]) {
365  const int dmv_limit = 1 << 5;
366  const int pos_offset_x = 6 * (sp->d_hor_x + sp->d_hor_y);
367  const int pos_offset_y = 6 * (sp->d_ver_x + sp->d_ver_y);
368  for (int x = 0; x < AFFINE_MIN_BLOCK_SIZE; x++) {
369  for (int y = 0; y < AFFINE_MIN_BLOCK_SIZE; y++) {
370  LOCAL_ALIGNED_8(Mv, diff, [1]);
371  diff->x = x * (sp->d_hor_x * (1 << 2)) + y * (sp->d_hor_y * (1 << 2)) - pos_offset_x;
372  diff->y = x * (sp->d_ver_x * (1 << 2)) + y * (sp->d_ver_y * (1 << 2)) - pos_offset_y;
373  ff_vvc_round_mv(diff, 0, 8);
374  pu->diff_mv_x[lx][AFFINE_MIN_BLOCK_SIZE * y + x] = av_clip(diff->x, -dmv_limit + 1, dmv_limit - 1);
375  pu->diff_mv_y[lx][AFFINE_MIN_BLOCK_SIZE * y + x] = av_clip(diff->y, -dmv_limit + 1, dmv_limit - 1);
376  }
377  }
378  }
379 }
380 
381 static void store_cp_mv(const VVCLocalContext *lc, const MotionInfo *mi, const int lx)
382 {
383  VVCFrameContext *fc = lc->fc;
384  const CodingUnit *cu = lc->cu;
385  const int log2_min_cb_size = fc->ps.sps->min_cb_log2_size_y;
386  const int min_cb_size = fc->ps.sps->min_cb_size_y;
387  const int min_cb_width = fc->ps.pps->min_cb_width;
388  const int num_cp_mv = mi->motion_model_idc + 1;
389 
390  for (int dy = 0; dy < cu->cb_height; dy += min_cb_size) {
391  for (int dx = 0; dx < cu->cb_width; dx += min_cb_size) {
392  const int x_cb = (cu->x0 + dx) >> log2_min_cb_size;
393  const int y_cb = (cu->y0 + dy) >> log2_min_cb_size;
394  const int offset = (y_cb * min_cb_width + x_cb) * MAX_CONTROL_POINTS;
395 
396  memcpy(&fc->tab.cp_mv[lx][offset], mi->mv[lx], sizeof(Mv) * num_cp_mv);
397  SAMPLE_CTB(fc->tab.mmi, x_cb, y_cb) = mi->motion_model_idc;
398  }
399  }
400 }
401 
402 //8.5.5.9 Derivation process for motion vector arrays from affine control point motion vectors
404 {
405  const CodingUnit *cu = lc->cu;
406  const MotionInfo *mi = &pu->mi;
407  const int sbw = cu->cb_width / mi->num_sb_x;
408  const int sbh = cu->cb_height / mi->num_sb_y;
409  SubblockParams params[2];
410  MvField mvf;
411 
412  mvf.pred_flag = mi->pred_flag;
413  mvf.bcw_idx = mi->bcw_idx;
414  mvf.hpel_if_idx = mi->hpel_if_idx;
415  mvf.ciip_flag = 0;
416  for (int i = 0; i < 2; i++) {
417  const PredFlag mask = i + 1;
418  if (mi->pred_flag & mask) {
419  store_cp_mv(lc, mi, i);
420  init_subblock_params(params + i, mi, cu->cb_width, cu->cb_height, i);
421  derive_subblock_diff_mvs(lc, pu, params + i, i);
422  mvf.ref_idx[i] = mi->ref_idx[i];
423  }
424  }
425 
426  for (int sby = 0; sby < mi->num_sb_y; sby++) {
427  for (int sbx = 0; sbx < mi->num_sb_x; sbx++) {
428  const int x0 = cu->x0 + sbx * sbw;
429  const int y0 = cu->y0 + sby * sbh;
430  for (int i = 0; i < 2; i++) {
431  const PredFlag mask = i + 1;
432  if (mi->pred_flag & mask) {
433  const SubblockParams* sp = params + i;
434  const int x_pos_cb = sp->is_fallback ? (cu->cb_width >> 1) : (2 + (sbx << MIN_CU_LOG2));
435  const int y_pos_cb = sp->is_fallback ? (cu->cb_height >> 1) : (2 + (sby << MIN_CU_LOG2));
436  Mv *mv = mvf.mv + i;
437 
438  mv->x = sp->mv_scale_hor + sp->d_hor_x * x_pos_cb + sp->d_hor_y * y_pos_cb;
439  mv->y = sp->mv_scale_ver + sp->d_ver_x * x_pos_cb + sp->d_ver_y * y_pos_cb;
442  }
443  }
444  ff_vvc_set_mvf(lc, x0, y0, sbw, sbh, &mvf);
445  }
446  }
447 }
448 
450 {
451  const CodingUnit *cu = lc->cu;
452  const int angle_idx = ff_vvc_gpm_angle_idx[pu->gpm_partition_idx];
453  const int distance_idx = ff_vvc_gpm_distance_idx[pu->gpm_partition_idx];
454  const int displacement_x = ff_vvc_gpm_distance_lut[angle_idx];
455  const int displacement_y = ff_vvc_gpm_distance_lut[(angle_idx + 8) % 32];
456  const int is_flip = angle_idx >= 13 &&angle_idx <= 27;
457  const int shift_hor = (angle_idx % 16 == 8 || (angle_idx % 16 && cu->cb_height >= cu->cb_width)) ? 0 : 1;
458  const int sign = angle_idx < 16 ? 1 : -1;
459  const int block_size = 4;
460  int offset_x = (-cu->cb_width) >> 1;
461  int offset_y = (-cu->cb_height) >> 1;
462 
463  if (!shift_hor)
464  offset_y += sign * ((distance_idx * cu->cb_height) >> 3);
465  else
466  offset_x += sign * ((distance_idx * cu->cb_width) >> 3);
467 
468  for (int y = 0; y < cu->cb_height; y += block_size) {
469  for (int x = 0; x < cu->cb_width; x += block_size) {
470  const int motion_idx = (((x + offset_x) * (1 << 1)) + 5) * displacement_x +
471  (((y + offset_y) * (1 << 1)) + 5) * displacement_y;
472  const int s_type = FFABS(motion_idx) < 32 ? 2 : (motion_idx <= 0 ? (1 - is_flip) : is_flip);
473  const int pred_flag = pu->gpm_mv[0].pred_flag | pu->gpm_mv[1].pred_flag;
474  const int x0 = cu->x0 + x;
475  const int y0 = cu->y0 + y;
476 
477  if (!s_type)
478  ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, pu->gpm_mv + 0);
479  else if (s_type == 1 || (s_type == 2 && pred_flag != PF_BI))
480  ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, pu->gpm_mv + 1);
481  else {
482  MvField mvf = pu->gpm_mv[0];
483  const MvField *mv1 = &pu->gpm_mv[1];
484  const int lx = mv1->pred_flag - PF_L0;
485  mvf.pred_flag = PF_BI;
486  mvf.ref_idx[lx] = mv1->ref_idx[lx];
487  mvf.mv[lx] = mv1->mv[lx];
488  ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, &mvf);
489  }
490  }
491  }
492 }
493 
494 void ff_vvc_store_mvf(const VVCLocalContext *lc, const MvField *mvf)
495 {
496  const CodingUnit *cu = lc->cu;
497  ff_vvc_set_mvf(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height, mvf);
498 }
499 
501 {
502  const CodingUnit *cu = lc->cu;
503  MvField mvf;
504 
505  mvf.hpel_if_idx = mi->hpel_if_idx;
506  mvf.bcw_idx = mi->bcw_idx;
507  mvf.pred_flag = mi->pred_flag;
508  mvf.ciip_flag = 0;
509 
510  for (int i = 0; i < 2; i++) {
511  const PredFlag mask = i + 1;
512  if (mvf.pred_flag & mask) {
513  mvf.mv[i] = mi->mv[i][0];
514  mvf.ref_idx[i] = mi->ref_idx[i];
515  }
516  }
517  ff_vvc_set_mvf(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height, &mvf);
518 }
519 
520 typedef enum NeighbourIdx {
521  A0,
522  A1,
523  A2,
524  B0,
525  B1,
526  B2,
527  B3,
530 } NeighbourIdx;
531 
532 typedef struct Neighbour {
533  int x;
534  int y;
535 
536  int checked;
538 } Neighbour;
539 
540 typedef struct NeighbourContext {
544 
545 static int is_a0_available(const VVCLocalContext *lc, const CodingUnit *cu)
546 {
547  const VVCFrameContext *fc = lc->fc;
548  const VVCSPS *sps = fc->ps.sps;
549  const int x0b = av_mod_uintp2(cu->x0, sps->ctb_log2_size_y);
550  int cand_bottom_left;
551 
552  if (!x0b && !lc->ctb_left_flag) {
553  cand_bottom_left = 0;
554  } else {
555  const int log2_min_cb_size = sps->min_cb_log2_size_y;
556  const int min_cb_width = fc->ps.pps->min_cb_width;
557  const int x = (cu->x0 - 1) >> log2_min_cb_size;
558  const int y = (cu->y0 + cu->cb_height) >> log2_min_cb_size;
559  const int max_y = FFMIN(fc->ps.pps->height, ((cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y);
560  if (cu->y0 + cu->cb_height >= max_y)
561  cand_bottom_left = 0;
562  else
563  cand_bottom_left = SAMPLE_CTB(fc->tab.cb_width[0], x, y) != 0;
564  }
565  return cand_bottom_left;
566 }
567 
569 {
570  const CodingUnit *cu = lc->cu;
571  const NeighbourAvailable *na = &lc->na;
572  const int x0 = cu->x0;
573  const int y0 = cu->y0;
574  const int cb_width = cu->cb_width;
575  const int cb_height = cu->cb_height;
576  const int a0_available = is_a0_available(lc, cu);
577 
578  Neighbour neighbours[NUM_NBS] = {
579  { x0 - 1, y0 + cb_height, !a0_available }, //A0
580  { x0 - 1, y0 + cb_height - 1, !na->cand_left }, //A1
581  { x0 - 1, y0, !na->cand_left }, //A2
582  { x0 + cb_width, y0 - 1, !na->cand_up_right }, //B0
583  { x0 + cb_width - 1, y0 - 1, !na->cand_up }, //B1
584  { x0 - 1, y0 - 1, !na->cand_up_left }, //B2
585  { x0, y0 - 1, !na->cand_up }, //B3
586  };
587 
588  memcpy(ctx->neighbours, neighbours, sizeof(neighbours));
589  ctx->lc = lc;
590 }
591 
593 {
594  return pred == PF_IBC ? MODE_IBC : (pred == PF_INTRA ? MODE_INTRA : MODE_INTER);
595 }
596 
597 static int check_available(Neighbour *n, const VVCLocalContext *lc, const int check_mer)
598 {
599  const VVCFrameContext *fc = lc->fc;
600  const VVCSPS *sps = fc->ps.sps;
601  const CodingUnit *cu = lc->cu;
602  const MvField *tab_mvf = fc->tab.mvf;
603  const int min_pu_width = fc->ps.pps->min_pu_width;
604 
605  if (!n->checked) {
606  n->checked = 1;
607  n->available = !sps->r->sps_entropy_coding_sync_enabled_flag || ((n->x >> sps->ctb_log2_size_y) <= (cu->x0 >> sps->ctb_log2_size_y));
608  n->available &= cu->pred_mode == pred_flag_to_mode(TAB_MVF(n->x, n->y).pred_flag);
609  if (check_mer)
610  n->available &= !is_same_mer(fc, n->x, n->y, cu->x0, cu->y0);
611  }
612  return n->available;
613 }
614 
615 static const MvField *mv_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand)
616 {
617  const VVCFrameContext *fc = lc->fc;
618  const int min_pu_width = fc->ps.pps->min_pu_width;
619  const MvField* tab_mvf = fc->tab.mvf;
620  const MvField *mvf = &TAB_MVF(x_cand, y_cand);
621 
622  return mvf;
623 }
624 
626 {
627  const VVCLocalContext *lc = ctx->lc;
628  Neighbour *n = &ctx->neighbours[nb];
629 
630  if (check_available(n, lc, 1))
631  return mv_merge_candidate(lc, n->x, n->y);
632  return 0;
633 }
634 #define MV_MERGE_FROM_NB(nb) mv_merge_from_nb(&nctx, nb)
635 
636 //8.5.2.3 Derivation process for spatial merging candidates
637 static int mv_merge_spatial_candidates(const VVCLocalContext *lc, const int merge_idx,
638  const MvField **nb_list, MvField *cand_list, int *nb_merge_cand)
639 {
640  const MvField *cand;
641  int num_cands = 0;
642  NeighbourContext nctx;
643 
644  static NeighbourIdx nbs[][2] = {
645  {B1, NB_IDX_NONE },
646  {A1, B1 },
647  {B0, B1 },
648  {A0, A1 },
649  };
650 
651  init_neighbour_context(&nctx, lc);
652  for (int i = 0; i < FF_ARRAY_ELEMS(nbs); i++) {
653  NeighbourIdx nb = nbs[i][0];
654  NeighbourIdx old = nbs[i][1];
655  cand = nb_list[nb] = MV_MERGE_FROM_NB(nb);
656  if (cand && !compare_mv_ref_idx(cand, nb_list[old])) {
657  cand_list[num_cands] = *cand;
658  if (merge_idx == num_cands)
659  return 1;
660  num_cands++;
661  }
662  }
663  if (num_cands != 4) {
664  cand = MV_MERGE_FROM_NB(B2);
665  if (cand && !compare_mv_ref_idx(cand, nb_list[A1])
666  && !compare_mv_ref_idx(cand, nb_list[B1])) {
667  cand_list[num_cands] = *cand;
668  if (merge_idx == num_cands)
669  return 1;
670  num_cands++;
671  }
672  }
673  *nb_merge_cand = num_cands;
674  return 0;
675 }
676 
678 {
679  const VVCFrameContext *fc = lc->fc;
680  const CodingUnit *cu = lc->cu;
681 
682  memset(cand, 0, sizeof(*cand));
683  if (fc->ps.ph.r->ph_temporal_mvp_enabled_flag && (cu->cb_width * cu->cb_height > 32)) {
684  int available_l0 = temporal_luma_motion_vector(lc, 0, cand->mv + 0, 0, 1, 0);
685  int available_l1 = IS_B(lc->sc->sh.r) ?
686  temporal_luma_motion_vector(lc, 0, cand->mv + 1, 1, 1, 0) : 0;
687  cand->pred_flag = available_l0 + (available_l1 << 1);
688  }
689  return cand->pred_flag;
690 }
691 
692 //8.5.2.6 Derivation process for history-based merging candidates
693 static int mv_merge_history_candidates(const VVCLocalContext *lc, const int merge_idx,
694  const MvField **nb_list, MvField *cand_list, int *num_cands)
695 {
696  const VVCSPS *sps = lc->fc->ps.sps;
697  const EntryPoint* ep = lc->ep;
698  for (int i = 1; i <= ep->num_hmvp && (*num_cands < sps->max_num_merge_cand - 1); i++) {
699  const MvField *h = &ep->hmvp[ep->num_hmvp - i];
700  const int same_motion = i <= 2 && (compare_mv_ref_idx(h, nb_list[A1]) || compare_mv_ref_idx(h, nb_list[B1]));
701  if (!same_motion) {
702  cand_list[*num_cands] = *h;
703  if (merge_idx == *num_cands)
704  return 1;
705  (*num_cands)++;
706  }
707  }
708  return 0;
709 }
710 
711 //8.5.2.4 Derivation process for pairwise average merging candidate
712 static int mv_merge_pairwise_candidate(MvField *cand_list, const int num_cands, const int is_b)
713 {
714  if (num_cands > 1) {
715  const int num_ref_rists = is_b ? 2 : 1;
716  const MvField* p0 = cand_list + 0;
717  const MvField* p1 = cand_list + 1;
718  MvField* cand = cand_list + num_cands;
719 
720  cand->pred_flag = 0;
721  for (int i = 0; i < num_ref_rists; i++) {
722  PredFlag mask = i + 1;
723  if (p0->pred_flag & mask) {
724  cand->pred_flag |= mask;
725  cand->ref_idx[i] = p0->ref_idx[i];
726  if (p1->pred_flag & mask) {
727  Mv *mv = cand->mv + i;
728  mv->x = p0->mv[i].x + p1->mv[i].x;
729  mv->y = p0->mv[i].y + p1->mv[i].y;
730  ff_vvc_round_mv(mv, 0, 1);
731  } else {
732  cand->mv[i] = p0->mv[i];
733  }
734  } else if (p1->pred_flag & mask) {
735  cand->pred_flag |= mask;
736  cand->mv[i] = p1->mv[i];
737  cand->ref_idx[i] = p1->ref_idx[i];
738  }
739  }
740  if (cand->pred_flag) {
741  cand->hpel_if_idx = p0->hpel_if_idx == p1->hpel_if_idx ? p0->hpel_if_idx : 0;
742  cand->bcw_idx = 0;
743  cand->ciip_flag = 0;
744  return 1;
745  }
746  }
747  return 0;
748 }
749 
750 //8.5.2.5 Derivation process for zero motion vector merging candidates
751 static void mv_merge_zero_motion_candidate(const VVCLocalContext *lc, const int merge_idx,
752  MvField *cand_list, int num_cands)
753 {
754  const VVCSPS *sps = lc->fc->ps.sps;
755  const H266RawSliceHeader *rsh = lc->sc->sh.r;
756  const int num_ref_idx = IS_P(rsh) ?
758  int zero_idx = 0;
759 
760  while (num_cands < sps->max_num_merge_cand) {
761  MvField *cand = cand_list + num_cands;
762 
763  cand->pred_flag = PF_L0 + (IS_B(rsh) << 1);
764  AV_ZERO64(cand->mv + 0);
765  AV_ZERO64(cand->mv + 1);
766  cand->ref_idx[0] = zero_idx < num_ref_idx ? zero_idx : 0;
767  cand->ref_idx[1] = zero_idx < num_ref_idx ? zero_idx : 0;
768  cand->bcw_idx = 0;
769  cand->hpel_if_idx = 0;
770  if (merge_idx == num_cands)
771  return;
772  num_cands++;
773  zero_idx++;
774  }
775 }
776 
777 static void mv_merge_mode(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list)
778 {
779  int num_cands = 0;
780  const MvField *nb_list[NUM_NBS + 1] = { NULL };
781 
782  if (mv_merge_spatial_candidates(lc, merge_idx, nb_list, cand_list, &num_cands))
783  return;
784 
785  if (mv_merge_temporal_candidate(lc, &cand_list[num_cands])) {
786  if (merge_idx == num_cands)
787  return;
788  num_cands++;
789  }
790 
791  if (mv_merge_history_candidates(lc, merge_idx, nb_list, cand_list, &num_cands))
792  return;
793 
794  if (mv_merge_pairwise_candidate(cand_list, num_cands, IS_B(lc->sc->sh.r))) {
795  if (merge_idx == num_cands)
796  return;
797  num_cands++;
798  }
799 
800  mv_merge_zero_motion_candidate(lc, merge_idx, cand_list, num_cands);
801 }
802 
803 //8.5.2.2 Derivation process for luma motion vectors for merge mode
804 void ff_vvc_luma_mv_merge_mode(VVCLocalContext *lc, const int merge_idx, const int ciip_flag, MvField *mv)
805 {
806  const CodingUnit *cu = lc->cu;
807  MvField cand_list[MRG_MAX_NUM_CANDS];
808 
809  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
810  mv_merge_mode(lc, merge_idx, cand_list);
811  *mv = cand_list[merge_idx];
812  //ciip flag in not inhritable
813  mv->ciip_flag = ciip_flag;
814 }
815 
816 //8.5.4.2 Derivation process for luma motion vectors for geometric partitioning merge mode
817 void ff_vvc_luma_mv_merge_gpm(VVCLocalContext *lc, const int merge_gpm_idx[2], MvField *mv)
818 {
819  const CodingUnit *cu = lc->cu;
820  MvField cand_list[MRG_MAX_NUM_CANDS];
821 
822  const int idx[] = { merge_gpm_idx[0], merge_gpm_idx[1] + (merge_gpm_idx[1] >= merge_gpm_idx[0]) };
823 
824  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
825  mv_merge_mode(lc, FFMAX(idx[0], idx[1]), cand_list);
826  memset(mv, 0, 2 * sizeof(*mv));
827  for (int i = 0; i < 2; i++) {
828  int lx = idx[i] & 1;
829  int mask = lx + PF_L0;
830  MvField *cand = cand_list + idx[i];
831  if (!(cand->pred_flag & mask)) {
832  lx = !lx;
833  mask = lx + PF_L0;
834  }
835  mv[i].pred_flag = mask;
836  mv[i].ref_idx[lx] = cand->ref_idx[lx];
837  mv[i].mv[lx] = cand->mv[lx];
838  }
839 
840 }
841 
842 //8.5.5.5 Derivation process for luma affine control point motion vectors from a neighbouring block
843 static void affine_cps_from_nb(const VVCLocalContext *lc,
844  const int x_nb, int y_nb, const int nbw, const int nbh, const int lx,
845  Mv *cps, int num_cps)
846 {
847  const VVCFrameContext *fc = lc->fc;
848  const CodingUnit *cu = lc->cu;
849  const int x0 = cu->x0;
850  const int y0 = cu->y0;
851  const int cb_width = cu->cb_width;
852  const int cb_height = cu->cb_height;
853  const MvField* tab_mvf = fc->tab.mvf;
854  const int min_cb_log2_size = fc->ps.sps->min_cb_log2_size_y;
855  const int min_cb_width = fc->ps.pps->min_cb_width;
856 
857  const int log2_nbw = ff_log2(nbw);
858  const int log2_nbh = ff_log2(nbh);
859  const int is_ctb_boundary = !((y_nb + nbh) % fc->ps.sps->ctb_size_y) && (y_nb + nbh == y0);
860  const Mv *l, *r;
861  int mv_scale_hor, mv_scale_ver, d_hor_x, d_ver_x, d_hor_y, d_ver_y, motion_model_idc_nb;
862  if (is_ctb_boundary) {
863  const int min_pu_width = fc->ps.pps->min_pu_width;
864  l = &TAB_MVF(x_nb, y_nb + nbh - 1).mv[lx];
865  r = &TAB_MVF(x_nb + nbw - 1, y_nb + nbh - 1).mv[lx];
866  } else {
867  const int x = x_nb >> min_cb_log2_size;
868  const int y = y_nb >> min_cb_log2_size;
869  motion_model_idc_nb = SAMPLE_CTB(fc->tab.mmi, x, y);
870 
871  l = &TAB_CP_MV(lx, x_nb, y_nb);
872  r = &TAB_CP_MV(lx, x_nb + nbw - 1, y_nb) + 1;
873  }
874  mv_scale_hor = l->x * (1 << 7);
875  mv_scale_ver = l->y * (1 << 7);
876  d_hor_x = (r->x - l->x) * (1 << (7 - log2_nbw));
877  d_ver_x = (r->y - l->y) * (1 << (7 - log2_nbw));
878  if (!is_ctb_boundary && motion_model_idc_nb == MOTION_6_PARAMS_AFFINE) {
879  const Mv* lb = &TAB_CP_MV(lx, x_nb, y_nb + nbh - 1) + 2;
880  d_hor_y = (lb->x - l->x) * (1 << (7 - log2_nbh));
881  d_ver_y = (lb->y - l->y) * (1 << (7 - log2_nbh));
882  } else {
883  d_hor_y = -d_ver_x;
884  d_ver_y = d_hor_x;
885  }
886 
887  if (is_ctb_boundary) {
888  y_nb = y0;
889  }
890  cps[0].x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 - y_nb);
891  cps[0].y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 - y_nb);
892  cps[1].x = mv_scale_hor + d_hor_x * (x0 + cb_width - x_nb) + d_hor_y * (y0 - y_nb);
893  cps[1].y = mv_scale_ver + d_ver_x * (x0 + cb_width - x_nb) + d_ver_y * (y0 - y_nb);
894  if (num_cps == 3) {
895  cps[2].x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 + cb_height - y_nb);
896  cps[2].y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 + cb_height - y_nb);
897  }
898  for (int i = 0; i < num_cps; i++) {
899  ff_vvc_round_mv(cps + i, 0, 7);
900  ff_vvc_clip_mv(cps + i);
901  }
902 }
903 
904 //derive affine neighbour's postion, width and height,
905 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)
906 {
907  const int log2_min_cb_size = fc->ps.sps->min_cb_log2_size_y;
908  const int min_cb_width = fc->ps.pps->min_cb_width;
909  const int x = x_nb >> log2_min_cb_size;
910  const int y = y_nb >> log2_min_cb_size;
911  const int motion_model_idc = SAMPLE_CTB(fc->tab.mmi, x, y);
912  if (motion_model_idc) {
913  *x_cb = SAMPLE_CTB(fc->tab.cb_pos_x[0], x, y);
914  *y_cb = SAMPLE_CTB(fc->tab.cb_pos_y[0], x, y);
915  *cbw = SAMPLE_CTB(fc->tab.cb_width[0], x, y);
916  *cbh = SAMPLE_CTB(fc->tab.cb_height[0], x, y);
917  }
918  return motion_model_idc;
919 }
920 
921 //part of 8.5.5.2 Derivation process for motion vectors and reference indices in subblock merge mode
922 static int affine_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, MotionInfo* mi)
923 {
924  const VVCFrameContext *fc = lc->fc;
925  int x, y, w, h, motion_model_idc;
926 
927  motion_model_idc = affine_neighbour_cb(fc, x_cand, y_cand, &x, &y, &w, &h);
928  if (motion_model_idc) {
929  const int min_pu_width = fc->ps.pps->min_pu_width;
930  const MvField* tab_mvf = fc->tab.mvf;
931  const MvField *mvf = &TAB_MVF(x, y);
932 
933  mi->bcw_idx = mvf->bcw_idx;
934  mi->pred_flag = mvf->pred_flag;
935  for (int i = 0; i < 2; i++) {
936  PredFlag mask = i + 1;
937  if (mi->pred_flag & mask) {
938  affine_cps_from_nb(lc, x, y, w, h, i, &mi->mv[i][0], motion_model_idc + 1);
939  }
940  mi->ref_idx[i] = mvf->ref_idx[i];
941  }
942  mi->motion_model_idc = motion_model_idc;
943  }
944  return motion_model_idc;
945 }
946 
947 static int affine_merge_from_nbs(NeighbourContext *ctx, const NeighbourIdx *nbs, const int num_nbs, MotionInfo* cand)
948 {
949  const VVCLocalContext *lc = ctx->lc;
950  for (int i = 0; i < num_nbs; i++) {
951  Neighbour *n = &ctx->neighbours[nbs[i]];
952  if (check_available(n, lc, 1) && affine_merge_candidate(lc, n->x, n->y, cand))
953  return 1;
954  }
955  return 0;
956 }
957 #define AFFINE_MERGE_FROM_NBS(nbs) affine_merge_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), mi)
958 
959 
960 static const MvField* derive_corner_mvf(NeighbourContext *ctx, const NeighbourIdx *neighbour, const int num_neighbour)
961 {
962  const VVCFrameContext *fc = ctx->lc->fc;
963  const MvField *tab_mvf = fc->tab.mvf;
964  const int min_pu_width = fc->ps.pps->min_pu_width;
965  for (int i = 0; i < num_neighbour; i++) {
966  Neighbour *n = &ctx->neighbours[neighbour[i]];
967  if (check_available(n, ctx->lc, 1)) {
968  return &TAB_MVF(n->x, n->y);
969  }
970  }
971  return NULL;
972 }
973 
974 #define DERIVE_CORNER_MV(nbs) derive_corner_mvf(nctx, nbs, FF_ARRAY_ELEMS(nbs))
975 
976 // check if the mv's and refidx are the same between A and B
977 static av_always_inline int compare_pf_ref_idx(const MvField *A, const struct MvField *B, const struct MvField *C, const int lx)
978 {
979 
980  const PredFlag mask = (lx + 1) & A->pred_flag;
981  if (!(B->pred_flag & mask))
982  return 0;
983  if (A->ref_idx[lx] != B->ref_idx[lx])
984  return 0;
985  if (C) {
986  if (!(C->pred_flag & mask))
987  return 0;
988  if (A->ref_idx[lx] != C->ref_idx[lx])
989  return 0;
990  }
991  return 1;
992 }
993 
995  const int x_ctb, const int y_ctb, const Mv* temp_mv, int *x, int *y)
996 {
997  const VVCPPS *pps = fc->ps.pps;
998  const int ctb_log2_size = fc->ps.sps->ctb_log2_size_y;
999  *y = av_clip(*y + temp_mv->y, y_ctb, FFMIN(pps->height - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7;
1000  *x = av_clip(*x + temp_mv->x, x_ctb, FFMIN(pps->width - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7;
1001 }
1002 
1004  const int x_ctb, const int y_ctb, const Mv *temp_mv,
1005  int x, int y, uint8_t *pred_flag, Mv *mv)
1006 {
1007  MvField temp_col;
1008  Mv* mvLXCol;
1009  const int refIdxLx = 0;
1010  const VVCFrameContext *fc = lc->fc;
1011  const VVCSH *sh = &lc->sc->sh;
1012  const int min_pu_width = fc->ps.pps->min_pu_width;
1013  VVCFrame *ref = fc->ref->collocated_ref;
1014  MvField *tab_mvf = ref->tab_dmvr_mvf;
1015  int colPic = ref->poc;
1016  int X = 0;
1017 
1018  sb_clip_location(fc, x_ctb, y_ctb, temp_mv, &x, &y);
1019 
1020  temp_col = TAB_MVF(x, y);
1021  mvLXCol = mv + 0;
1022  *pred_flag = DERIVE_TEMPORAL_COLOCATED_MVS(1);
1023  if (IS_B(sh->r)) {
1024  X = 1;
1025  mvLXCol = mv + 1;
1026  *pred_flag |= (DERIVE_TEMPORAL_COLOCATED_MVS(1)) << 1;
1027  }
1028 }
1029 
1030 //8.5.5.4 Derivation process for subblock-based temporal merging base motion data
1032  const int x_ctb, const int y_ctb, MvField *ctr_mvf, Mv *temp_mv)
1033 {
1034  const VVCFrameContext *fc = lc->fc;
1035  const RefPicList *rpl = lc->sc->rpl;
1036  const CodingUnit *cu = lc->cu;
1037  const int x = cu->x0 + cu->cb_width / 2;
1038  const int y = cu->y0 + cu->cb_height / 2;
1039  const VVCFrame *ref = fc->ref->collocated_ref;
1040 
1041  int colPic;
1042 
1043  memset(temp_mv, 0, sizeof(*temp_mv));
1044 
1045  if (!ref) {
1046  memset(ctr_mvf, 0, sizeof(*ctr_mvf));
1047  return 0;
1048  }
1049 
1050  colPic = ref->poc;
1051 
1052  if (a1) {
1053  if ((a1->pred_flag & PF_L0) && colPic == rpl[0].list[a1->ref_idx[0]])
1054  *temp_mv = a1->mv[0];
1055  else if ((a1->pred_flag & PF_L1) && colPic == rpl[1].list[a1->ref_idx[1]])
1056  *temp_mv = a1->mv[1];
1057  ff_vvc_round_mv(temp_mv, 0, 4);
1058  }
1059  sb_temproal_luma_motion(lc, x_ctb, y_ctb, temp_mv, x, y, &ctr_mvf->pred_flag , ctr_mvf->mv);
1060 
1061  return ctr_mvf->pred_flag;
1062 }
1063 
1064 
1065 //8.5.5.3 Derivation process for subblock-based temporal merging candidates
1067 {
1068  const VVCFrameContext *fc = lc->fc;
1069  const CodingUnit *cu = lc->cu;
1070  const VVCSPS *sps = fc->ps.sps;
1071  const VVCPH *ph = &fc->ps.ph;
1072  MotionInfo *mi = &pu->mi;
1073  const int ctb_log2_size = sps->ctb_log2_size_y;
1074  const int x0 = cu->x0;
1075  const int y0 = cu->y0;
1076  const NeighbourIdx n = A1;
1077  const MvField *a1;
1078  MvField ctr_mvf;
1079  LOCAL_ALIGNED_8(Mv, temp_mv, [1]);
1080  const int x_ctb = (x0 >> ctb_log2_size) << ctb_log2_size;
1081  const int y_ctb = (y0 >> ctb_log2_size) << ctb_log2_size;
1082 
1083 
1084  if (!ph->r->ph_temporal_mvp_enabled_flag ||
1085  !sps->r->sps_sbtmvp_enabled_flag ||
1086  (cu->cb_width < 8 && cu->cb_height < 8))
1087  return 0;
1088 
1089  mi->num_sb_x = cu->cb_width >> 3;
1090  mi->num_sb_y = cu->cb_height >> 3;
1091 
1092  a1 = derive_corner_mvf(nctx, &n, 1);
1093  if (sb_temporal_luma_motion_data(lc, a1, x_ctb, y_ctb, &ctr_mvf, temp_mv)) {
1094  const int sbw = cu->cb_width / mi->num_sb_x;
1095  const int sbh = cu->cb_height / mi->num_sb_y;
1096  MvField mvf = {0};
1097  for (int sby = 0; sby < mi->num_sb_y; sby++) {
1098  for (int sbx = 0; sbx < mi->num_sb_x; sbx++) {
1099  int x = x0 + sbx * sbw;
1100  int y = y0 + sby * sbh;
1101  sb_temproal_luma_motion(lc, x_ctb, y_ctb, temp_mv, x + sbw / 2, y + sbh / 2, &mvf.pred_flag, mvf.mv);
1102  if (!mvf.pred_flag) {
1103  mvf.pred_flag = ctr_mvf.pred_flag;
1104  memcpy(mvf.mv, ctr_mvf.mv, sizeof(mvf.mv));
1105  }
1106  ff_vvc_set_mvf(lc, x, y, sbw, sbh, &mvf);
1107  }
1108  }
1109  return 1;
1110  }
1111  return 0;
1112 }
1113 
1114 static int affine_merge_const1(const MvField *c0, const MvField *c1, const MvField *c2, MotionInfo *mi)
1115 {
1116  if (c0 && c1 && c2) {
1117  mi->pred_flag = 0;
1118  for (int i = 0; i < 2; i++) {
1119  PredFlag mask = i + 1;
1120  if (compare_pf_ref_idx(c0, c1, c2, i)) {
1121  mi->pred_flag |= mask;
1122  mi->ref_idx[i] = c0->ref_idx[i];
1123  mi->mv[i][0] = c0->mv[i];
1124  mi->mv[i][1] = c1->mv[i];
1125  mi->mv[i][2] = c2->mv[i];
1126  }
1127  }
1128  if (mi->pred_flag) {
1129  if (mi->pred_flag == PF_BI)
1130  mi->bcw_idx = c0->bcw_idx;
1131  mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1132  return 1;
1133  }
1134  }
1135  return 0;
1136 }
1137 
1138 static int affine_merge_const2(const MvField *c0, const MvField *c1, const MvField *c3, MotionInfo *mi)
1139 {
1140  if (c0 && c1 && c3) {
1141  mi->pred_flag = 0;
1142  for (int i = 0; i < 2; i++) {
1143  PredFlag mask = i + 1;
1144  if (compare_pf_ref_idx(c0, c1, c3, i)) {
1145  mi->pred_flag |= mask;
1146  mi->ref_idx[i] = c0->ref_idx[i];
1147  mi->mv[i][0] = c0->mv[i];
1148  mi->mv[i][1] = c1->mv[i];
1149  mi->mv[i][2].x = c3->mv[i].x + c0->mv[i].x - c1->mv[i].x;
1150  mi->mv[i][2].y = c3->mv[i].y + c0->mv[i].y - c1->mv[i].y;
1151  ff_vvc_clip_mv(&mi->mv[i][2]);
1152  }
1153  }
1154  if (mi->pred_flag) {
1155  mi->bcw_idx = mi->pred_flag == PF_BI ? c0->bcw_idx : 0;
1156  mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1157  return 1;
1158  }
1159  }
1160  return 0;
1161 }
1162 
1163 static int affine_merge_const3(const MvField *c0, const MvField *c2, const MvField *c3, MotionInfo *mi)
1164 {
1165  if (c0 && c2 && c3) {
1166  mi->pred_flag = 0;
1167  for (int i = 0; i < 2; i++) {
1168  PredFlag mask = i + 1;
1169  if (compare_pf_ref_idx(c0, c2, c3, i)) {
1170  mi->pred_flag |= mask;
1171  mi->ref_idx[i] = c0->ref_idx[i];
1172  mi->mv[i][0] = c0->mv[i];
1173  mi->mv[i][1].x = c3->mv[i].x + c0->mv[i].x - c2->mv[i].x;
1174  mi->mv[i][1].y = c3->mv[i].y + c0->mv[i].y - c2->mv[i].y;
1175  ff_vvc_clip_mv(&mi->mv[i][1]);
1176  mi->mv[i][2] = c2->mv[i];
1177  }
1178  }
1179  if (mi->pred_flag) {
1180  mi->bcw_idx = mi->pred_flag == PF_BI ? c0->bcw_idx : 0;
1181  mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1182  return 1;
1183  }
1184  }
1185  return 0;
1186 }
1187 
1188 static int affine_merge_const4(const MvField *c1, const MvField *c2, const MvField *c3, MotionInfo *mi)
1189 {
1190  if (c1 && c2 && c3) {
1191  mi->pred_flag = 0;
1192  for (int i = 0; i < 2; i++) {
1193  PredFlag mask = i + 1;
1194  if (compare_pf_ref_idx(c1, c2, c3, i)) {
1195  mi->pred_flag |= mask;
1196  mi->ref_idx[i] = c1->ref_idx[i];
1197  mi->mv[i][0].x = c1->mv[i].x + c2->mv[i].x - c3->mv[i].x;
1198  mi->mv[i][0].y = c1->mv[i].y + c2->mv[i].y - c3->mv[i].y;
1199  ff_vvc_clip_mv(&mi->mv[i][0]);
1200  mi->mv[i][1] = c1->mv[i];
1201  mi->mv[i][2] = c2->mv[i];
1202  }
1203  }
1204  if (mi->pred_flag) {
1205  mi->bcw_idx = mi->pred_flag == PF_BI ? c1->bcw_idx : 0;
1206  mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1207  return 1;
1208  }
1209  }
1210  return 0;
1211 }
1212 
1213 static int affine_merge_const5(const MvField *c0, const MvField *c1, MotionInfo *mi)
1214 {
1215  if (c0 && c1) {
1216  mi->pred_flag = 0;
1217  for (int i = 0; i < 2; i++) {
1218  PredFlag mask = i + 1;
1219  if (compare_pf_ref_idx(c0, c1, NULL, i)) {
1220  mi->pred_flag |= mask;
1221  mi->ref_idx[i] = c0->ref_idx[i];
1222  mi->mv[i][0] = c0->mv[i];
1223  mi->mv[i][1] = c1->mv[i];
1224  }
1225  }
1226  if (mi->pred_flag) {
1227  if (mi->pred_flag == PF_BI)
1228  mi->bcw_idx = c0->bcw_idx;
1229  mi->motion_model_idc = MOTION_4_PARAMS_AFFINE;
1230  return 1;
1231  }
1232  }
1233  return 0;
1234 }
1235 
1236 static int affine_merge_const6(const MvField* c0, const MvField* c2, const int cb_width, const int cb_height, MotionInfo *mi)
1237 {
1238  if (c0 && c2) {
1239  const int shift = 7 + av_log2(cb_width) - av_log2(cb_height);
1240  mi->pred_flag = 0;
1241  for (int i = 0; i < 2; i++) {
1242  PredFlag mask = i + 1;
1243  if (compare_pf_ref_idx(c0, c2, NULL, i)) {
1244  mi->pred_flag |= mask;
1245  mi->ref_idx[i] = c0->ref_idx[i];
1246  mi->mv[i][0] = c0->mv[i];
1247  mi->mv[i][1].x = (c0->mv[i].x * (1 << 7)) + ((c2->mv[i].y - c0->mv[i].y) * (1 << shift));
1248  mi->mv[i][1].y = (c0->mv[i].y * (1 << 7)) - ((c2->mv[i].x - c0->mv[i].x) * (1 << shift));
1249  ff_vvc_round_mv(&mi->mv[i][1], 0, 7);
1250  ff_vvc_clip_mv(&mi->mv[i][1]);
1251  }
1252  }
1253  if (mi->pred_flag) {
1254  if (mi->pred_flag == PF_BI)
1255  mi->bcw_idx = c0->bcw_idx;
1256  mi->motion_model_idc = MOTION_4_PARAMS_AFFINE;
1257  return 1;
1258  }
1259  }
1260  return 0;
1261 }
1262 
1264 {
1265  const CodingUnit *cu = lc->cu;
1266 
1267  memset(mi, 0, sizeof(*mi));
1268  mi->pred_flag = PF_L0 + (IS_B(lc->sc->sh.r) << 1);
1269  mi->motion_model_idc = MOTION_4_PARAMS_AFFINE;
1270  mi->num_sb_x = cu->cb_width >> MIN_PU_LOG2;
1271  mi->num_sb_y = cu->cb_height >> MIN_PU_LOG2;
1272 }
1273 
1274 //8.5.5.6 Derivation process for constructed affine control point motion vector merging candidates
1276  NeighbourContext *nctx, const int merge_subblock_idx, int num_cands)
1277 {
1278  const VVCFrameContext *fc = lc->fc;
1279  const CodingUnit *cu = lc->cu;
1280  const NeighbourIdx tl[] = { B2, B3, A2 };
1281  const NeighbourIdx tr[] = { B1, B0};
1282  const NeighbourIdx bl[] = { A1, A0};
1283  const MvField *c0, *c1, *c2;
1284 
1285  c0 = DERIVE_CORNER_MV(tl);
1286  c1 = DERIVE_CORNER_MV(tr);
1287  c2 = DERIVE_CORNER_MV(bl);
1288 
1289  if (fc->ps.sps->r->sps_6param_affine_enabled_flag) {
1290  MvField corner3, *c3 = NULL;
1291  //Const1
1292  if (affine_merge_const1(c0, c1, c2, mi)) {
1293  if (merge_subblock_idx == num_cands)
1294  return 1;
1295  num_cands++;
1296  }
1297 
1298  memset(&corner3, 0, sizeof(corner3));
1299  if (fc->ps.ph.r->ph_temporal_mvp_enabled_flag){
1300  const int available_l0 = temporal_luma_motion_vector(lc, 0, corner3.mv + 0, 0, 0, 0);
1301  const int available_l1 = (lc->sc->sh.r->sh_slice_type == VVC_SLICE_TYPE_B) ?
1302  temporal_luma_motion_vector(lc, 0, corner3.mv + 1, 1, 0, 0) : 0;
1303 
1304  corner3.pred_flag = available_l0 + (available_l1 << 1);
1305  if (corner3.pred_flag)
1306  c3 = &corner3;
1307  }
1308 
1309  //Const2
1310  if (affine_merge_const2(c0, c1, c3, mi)) {
1311  if (merge_subblock_idx == num_cands)
1312  return 1;
1313  num_cands++;
1314  }
1315 
1316  //Const3
1317  if (affine_merge_const3(c0, c2, c3, mi)) {
1318  if (merge_subblock_idx == num_cands)
1319  return 1;
1320  num_cands++;
1321  }
1322 
1323  //Const4
1324  if (affine_merge_const4(c1, c2, c3, mi)) {
1325  if (merge_subblock_idx == num_cands)
1326  return 1;
1327  num_cands++;
1328  }
1329  }
1330 
1331  //Const5
1332  if (affine_merge_const5(c0, c1, mi)) {
1333  if (merge_subblock_idx == num_cands)
1334  return 1;
1335  num_cands++;
1336  }
1337 
1338  if (affine_merge_const6(c0, c2, cu->cb_width, cu->cb_height, mi)) {
1339  if (merge_subblock_idx == num_cands)
1340  return 1;
1341  }
1342  return 0;
1343 }
1344 
1345 //8.5.5.2 Derivation process for motion vectors and reference indices in subblock merge mode
1346 //return 1 if candidate is SbCol
1347 static int sb_mv_merge_mode(const VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
1348 {
1349  const VVCSPS *sps = lc->fc->ps.sps;
1350  const CodingUnit *cu = lc->cu;
1351  MotionInfo *mi = &pu->mi;
1352  int num_cands = 0;
1353  NeighbourContext nctx;
1354 
1355  init_neighbour_context(&nctx, lc);
1356 
1357  //SbCol
1358  if (sb_temporal_merge_candidate(lc, &nctx, pu)) {
1359  if (merge_subblock_idx == num_cands)
1360  return 1;
1361  num_cands++;
1362  }
1363 
1364  pu->inter_affine_flag = 1;
1365  mi->num_sb_x = cu->cb_width >> MIN_PU_LOG2;
1366  mi->num_sb_y = cu->cb_height >> MIN_PU_LOG2;
1367 
1368  if (sps->r->sps_affine_enabled_flag) {
1369  const NeighbourIdx ak[] = { A0, A1 };
1370  const NeighbourIdx bk[] = { B0, B1, B2 };
1371  //A
1372  if (AFFINE_MERGE_FROM_NBS(ak)) {
1373  if (merge_subblock_idx == num_cands)
1374  return 0;
1375  num_cands++;
1376  }
1377 
1378  //B
1379  if (AFFINE_MERGE_FROM_NBS(bk)) {
1380  if (merge_subblock_idx == num_cands)
1381  return 0;
1382  num_cands++;
1383  }
1384 
1385  //Const1 to Const6
1386  if (affine_merge_const_candidates(lc, mi, &nctx, merge_subblock_idx, num_cands))
1387  return 0;
1388  }
1389  //Zero
1391  return 0;
1392 }
1393 
1394 void ff_vvc_sb_mv_merge_mode(VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
1395 {
1396  const CodingUnit *cu = lc->cu;
1397  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1398  if (!sb_mv_merge_mode(lc, merge_subblock_idx, pu)) {
1399  ff_vvc_store_sb_mvs(lc, pu);
1400  }
1401 }
1402 
1403 static int mvp_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand,
1404  const int lx, const int8_t *ref_idx, Mv *mv)
1405 {
1406  const VVCFrameContext *fc = lc->fc;
1407  const RefPicList *rpl = lc->sc->rpl;
1408  const int min_pu_width = fc->ps.pps->min_pu_width;
1409  const MvField* tab_mvf = fc->tab.mvf;
1410  const MvField *mvf = &TAB_MVF(x_cand, y_cand);
1411  const PredFlag maskx = lx + 1;
1412  const int poc = rpl[lx].list[ref_idx[lx]];
1413  int available = 0;
1414 
1415  if ((mvf->pred_flag & maskx) && rpl[lx].list[mvf->ref_idx[lx]] == poc) {
1416  available = 1;
1417  *mv = mvf->mv[lx];
1418  } else {
1419  const int ly = !lx;
1420  const PredFlag masky = ly + 1;
1421  if ((mvf->pred_flag & masky) && rpl[ly].list[mvf->ref_idx[ly]] == poc) {
1422  available = 1;
1423  *mv = mvf->mv[ly];
1424  }
1425  }
1426 
1427  return available;
1428 }
1429 
1431  const int x_cand, const int y_cand, const int lx, const int8_t *ref_idx,
1432  Mv *cps, const int num_cp)
1433 {
1434  const VVCFrameContext *fc = lc->fc;
1435  int x_nb, y_nb, nbw, nbh, motion_model_idc, available = 0;
1436 
1437  motion_model_idc = affine_neighbour_cb(fc, x_cand, y_cand, &x_nb, &y_nb, &nbw, &nbh);
1438  if (motion_model_idc) {
1439  const int min_pu_width = fc->ps.pps->min_pu_width;
1440  const MvField* tab_mvf = fc->tab.mvf;
1441  const MvField *mvf = &TAB_MVF(x_nb, y_nb);
1442  RefPicList* rpl = lc->sc->rpl;
1443  const PredFlag maskx = lx + 1;
1444  const int poc = rpl[lx].list[ref_idx[lx]];
1445 
1446  if ((mvf->pred_flag & maskx) && rpl[lx].list[mvf->ref_idx[lx]] == poc) {
1447  available = 1;
1448  affine_cps_from_nb(lc, x_nb, y_nb, nbw, nbh, lx, cps, num_cp);
1449  } else {
1450  const int ly = !lx;
1451  const PredFlag masky = ly + 1;
1452  if ((mvf->pred_flag & masky) && rpl[ly].list[mvf->ref_idx[ly]] == poc) {
1453  available = 1;
1454  affine_cps_from_nb(lc, x_nb, y_nb, nbw, nbh, ly, cps, num_cp);
1455  }
1456  }
1457 
1458  }
1459  return available;
1460 }
1461 
1463  const NeighbourIdx *nbs, const int num_nbs, const int lx, const int8_t *ref_idx, const int amvr_shift,
1464  Mv *cps, const int num_cps)
1465 {
1466  const VVCLocalContext *lc = ctx->lc;
1467  int available = 0;
1468 
1469  for (int i = 0; i < num_nbs; i++) {
1470  Neighbour *n = &ctx->neighbours[nbs[i]];
1471  if (check_available(n, lc, 0)) {
1472  if (num_cps > 1)
1473  available = affine_mvp_candidate(lc, n->x, n->y, lx, ref_idx, cps, num_cps);
1474  else
1475  available = mvp_candidate(lc, n->x, n->y, lx, ref_idx, cps);
1476  if (available) {
1477  for (int c = 0; c < num_cps; c++)
1478  ff_vvc_round_mv(cps + c, amvr_shift, amvr_shift);
1479  return 1;
1480  }
1481  }
1482  }
1483  return 0;
1484 }
1485 
1486 //get mvp from neighbours
1487 #define AFFINE_MVP_FROM_NBS(nbs) \
1488  mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, cps, num_cp) \
1489 
1490 #define MVP_FROM_NBS(nbs) \
1491  mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, mv, 1) \
1492 
1494  const int mvp_lx_flag, const int lx, const int8_t* ref_idx, const int amvr_shift,
1495  Mv* mv, int *nb_merge_cand)
1496 {
1497  const NeighbourIdx ak[] = { A0, A1 };
1498  const NeighbourIdx bk[] = { B0, B1, B2 };
1499  NeighbourContext nctx;
1500  int available_a, num_cands = 0;
1501  LOCAL_ALIGNED_8(Mv, mv_a, [1]);
1502 
1503  init_neighbour_context(&nctx, lc);
1504 
1505  available_a = MVP_FROM_NBS(ak);
1506  if (available_a) {
1507  if (mvp_lx_flag == num_cands)
1508  return 1;
1509  num_cands++;
1510  *mv_a = *mv;
1511  }
1512  if (MVP_FROM_NBS(bk)) {
1513  if (!available_a || !IS_SAME_MV(mv_a, mv)) {
1514  if (mvp_lx_flag == num_cands)
1515  return 1;
1516  num_cands++;
1517  }
1518  }
1519  *nb_merge_cand = num_cands;
1520  return 0;
1521 }
1522 
1524  const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift,
1525  Mv* mv, int *num_cands)
1526 {
1527  if (temporal_luma_motion_vector(lc, ref_idx[lx], mv, lx, 1, 0)) {
1528  if (mvp_lx_flag == *num_cands) {
1529  ff_vvc_round_mv(mv, amvr_shift, amvr_shift);
1530  return 1;
1531  }
1532  (*num_cands)++;
1533  }
1534  return 0;
1535 
1536 }
1537 
1539  const int mvp_lx_flag, const int lx, const int8_t ref_idx, const int amvr_shift,
1540  Mv *mv, int num_cands)
1541 {
1542  const EntryPoint* ep = lc->ep;
1543  const RefPicList* rpl = lc->sc->rpl;
1544  const int poc = rpl[lx].list[ref_idx];
1545 
1546  if (ep->num_hmvp == 0)
1547  return 0;
1548  for (int i = 1; i <= FFMIN(4, ep->num_hmvp); i++) {
1549  const MvField* h = &ep->hmvp[i - 1];
1550  for (int j = 0; j < 2; j++) {
1551  const int ly = (j ? !lx : lx);
1552  PredFlag mask = PF_L0 + ly;
1553  if ((h->pred_flag & mask) && poc == rpl[ly].list[h->ref_idx[ly]]) {
1554  if (mvp_lx_flag == num_cands) {
1555  *mv = h->mv[ly];
1556  ff_vvc_round_mv(mv, amvr_shift, amvr_shift);
1557  return 1;
1558  }
1559  num_cands++;
1560  }
1561  }
1562  }
1563  return 0;
1564 }
1565 
1566 //8.5.2.8 Derivation process for luma motion vector prediction
1567 static void mvp(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx,
1568  const int8_t *ref_idx, const int amvr_shift, Mv *mv)
1569 {
1570  int num_cands;
1571 
1572  if (mvp_spatial_candidates(lc, mvp_lx_flag, lx, ref_idx, amvr_shift, mv, &num_cands))
1573  return;
1574 
1575  if (mvp_temporal_candidates(lc, mvp_lx_flag, lx, ref_idx, amvr_shift, mv, &num_cands))
1576  return;
1577 
1578  if (mvp_history_candidates(lc, mvp_lx_flag, lx, ref_idx[lx], amvr_shift, mv, num_cands))
1579  return;
1580 
1581  memset(mv, 0, sizeof(*mv));
1582 }
1583 
1584 void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
1585 {
1586  const CodingUnit *cu = lc->cu;
1587  mi->num_sb_x = 1;
1588  mi->num_sb_y = 1;
1589 
1590  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1591  if (mi->pred_flag != PF_L1)
1592  mvp(lc, mvp_lx_flag[L0], L0, mi->ref_idx, amvr_shift, &mi->mv[L0][0]);
1593  if (mi->pred_flag != PF_L0)
1594  mvp(lc, mvp_lx_flag[L1], L1, mi->ref_idx, amvr_shift, &mi->mv[L1][0]);
1595 }
1596 
1597 static int ibc_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *const cand_list, int *nb_merge_cand)
1598 {
1599  const CodingUnit *cu = lc->cu;
1600  const VVCFrameContext *fc = lc->fc;
1601  const int min_pu_width = fc->ps.pps->min_pu_width;
1602  const MvField *tab_mvf = fc->tab.mvf;
1603  const int is_gt4by4 = (cu->cb_width * cu->cb_height) > 16;
1604  int num_cands = 0;
1605 
1606  NeighbourContext nctx;
1607  Neighbour *a1 = &nctx.neighbours[A1];
1608  Neighbour *b1 = &nctx.neighbours[B1];
1609 
1610  if (!is_gt4by4) {
1611  *nb_merge_cand = 0;
1612  return 0;
1613  }
1614 
1615  init_neighbour_context(&nctx, lc);
1616 
1617  if (check_available(a1, lc, 1)) {
1618  cand_list[num_cands++] = TAB_MVF(a1->x, a1->y).mv[L0];
1619  if (num_cands > merge_idx)
1620  return 1;
1621  }
1622  if (check_available(b1, lc, 1)) {
1623  const MvField *mvf = &TAB_MVF(b1->x, b1->y);
1624  if (!num_cands || !IS_SAME_MV(&cand_list[0], mvf->mv)) {
1625  cand_list[num_cands++] = mvf->mv[L0];
1626  if (num_cands > merge_idx)
1627  return 1;
1628  }
1629  }
1630 
1631  *nb_merge_cand = num_cands;
1632  return 0;
1633 }
1634 
1636  const int merge_idx, Mv *cand_list, int *nb_merge_cand)
1637 {
1638  const CodingUnit *cu = lc->cu;
1639  const EntryPoint *ep = lc->ep;
1640  const int is_gt4by4 = (cu->cb_width * cu->cb_height) > 16;
1641  int num_cands = *nb_merge_cand;
1642 
1643  for (int i = 1; i <= ep->num_hmvp_ibc; i++) {
1644  int same_motion = 0;
1645  const MvField *mvf = &ep->hmvp_ibc[ep->num_hmvp_ibc - i];
1646  for (int j = 0; j < *nb_merge_cand; j++) {
1647  same_motion = is_gt4by4 && i == 1 && IS_SAME_MV(&mvf->mv[L0], &cand_list[j]);
1648  if (same_motion)
1649  break;
1650  }
1651  if (!same_motion) {
1652  cand_list[num_cands++] = mvf->mv[L0];
1653  if (num_cands > merge_idx)
1654  return 1;
1655  }
1656  }
1657 
1658  *nb_merge_cand = num_cands;
1659  return 0;
1660 }
1661 
1662 #define MV_BITS 18
1663 #define IBC_SHIFT(v) ((v) >= (1 << (MV_BITS - 1)) ? ((v) - (1 << MV_BITS)) : (v))
1664 
1665 static inline void ibc_add_mvp(Mv *mv, Mv *mvp, const int amvr_shift)
1666 {
1667  ff_vvc_round_mv(mv, amvr_shift, 0);
1668  ff_vvc_round_mv(mvp, amvr_shift, amvr_shift);
1669  mv->x = IBC_SHIFT(mv->x + mvp->x);
1670  mv->y = IBC_SHIFT(mv->y + mvp->y);
1671 }
1672 
1673 static void ibc_merge_candidates(VVCLocalContext *lc, const int merge_idx, Mv *mv)
1674 {
1675  const CodingUnit *cu = lc->cu;
1676  LOCAL_ALIGNED_8(Mv, cand_list, [MRG_MAX_NUM_CANDS]);
1677  int nb_cands;
1678 
1679  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1680  if (ibc_spatial_candidates(lc, merge_idx, cand_list, &nb_cands) ||
1681  ibc_history_candidates(lc, merge_idx, cand_list, &nb_cands)) {
1682  *mv = cand_list[merge_idx];
1683  return;
1684  }
1685 
1686  //zero mv
1687  memset(mv, 0, sizeof(*mv));
1688 }
1689 
1690 void ff_vvc_mvp_ibc(VVCLocalContext *lc, const int mvp_l0_flag, const int amvr_shift, Mv *mv)
1691 {
1692  LOCAL_ALIGNED_8(Mv, mvp, [1]);
1693 
1694  ibc_merge_candidates(lc, mvp_l0_flag, mvp);
1695  ibc_add_mvp(mv, mvp, amvr_shift);
1696 }
1697 
1698 void ff_vvc_luma_mv_merge_ibc(VVCLocalContext *lc, const int merge_idx, Mv *mv)
1699 {
1700  ibc_merge_candidates(lc, merge_idx, mv);
1701 }
1702 
1704  const NeighbourIdx *neighbour, const int num_neighbour,
1705  const int lx, const int8_t ref_idx, const int amvr_shift, Mv *cp)
1706 {
1707  const VVCLocalContext *lc = ctx->lc;
1708  const VVCFrameContext *fc = lc->fc;
1709  const MvField *tab_mvf = fc->tab.mvf;
1710  const int min_pu_width = fc->ps.pps->min_pu_width;
1711  const RefPicList* rpl = lc->sc->rpl;
1712  int available = 0;
1713 
1714  for (int i = 0; i < num_neighbour; i++) {
1715  Neighbour *n = &ctx->neighbours[neighbour[i]];
1716  if (check_available(n, ctx->lc, 0)) {
1717  const PredFlag maskx = lx + 1;
1718  const MvField* mvf = &TAB_MVF(n->x, n->y);
1719  const int poc = rpl[lx].list[ref_idx];
1720  if ((mvf->pred_flag & maskx) && rpl[lx].list[mvf->ref_idx[lx]] == poc) {
1721  available = 1;
1722  *cp = mvf->mv[lx];
1723  } else {
1724  const int ly = !lx;
1725  const PredFlag masky = ly + 1;
1726  if ((mvf->pred_flag & masky) && rpl[ly].list[mvf->ref_idx[ly]] == poc) {
1727  available = 1;
1728  *cp = mvf->mv[ly];
1729  }
1730  }
1731  if (available) {
1732  ff_vvc_round_mv(cp, amvr_shift, amvr_shift);
1733  return 1;
1734  }
1735  }
1736  }
1737  return 0;
1738 }
1739 
1740 #define AFFINE_MVP_CONSTRUCTED_CP(cands, cp) \
1741  affine_mvp_constructed_cp(nctx, cands, FF_ARRAY_ELEMS(cands), lx, ref_idx, \
1742  amvr_shift, cp)
1743 
1744 //8.5.5.8 Derivation process for constructed affine control point motion vector prediction candidates
1746  const int lx, const int8_t ref_idx, const int amvr_shift,
1747  Mv *cps, int *available)
1748 {
1749  const NeighbourIdx tl[] = { B2, B3, A2 };
1750  const NeighbourIdx tr[] = { B1, B0 };
1751  const NeighbourIdx bl[] = { A1, A0 };
1752 
1753  available[0] = AFFINE_MVP_CONSTRUCTED_CP(tl, cps + 0);
1754  available[1] = AFFINE_MVP_CONSTRUCTED_CP(tr, cps + 1);
1755  available[2] = AFFINE_MVP_CONSTRUCTED_CP(bl, cps + 2);
1756  return available[0] && available[1];
1757 }
1758 
1759 //8.5.5.7 item 7
1760 static void affine_mvp_const2(const int idx, Mv *cps, const int num_cp)
1761 {
1762  const Mv mv = cps[idx];
1763  for (int j = 0; j < num_cp; j++)
1764  cps[j] = mv;
1765 }
1766 
1767 //8.5.5.7 Derivation process for luma affine control point motion vector predictors
1768 static void affine_mvp(const VVCLocalContext *lc,
1769  const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift,
1770  MotionModelIdc motion_model_idc, Mv *cps)
1771 {
1772  const NeighbourIdx ak[] = { A0, A1 };
1773  const NeighbourIdx bk[] = { B0, B1, B2 };
1774  const int num_cp = motion_model_idc + 1;
1775  NeighbourContext nctx;
1777  int num_cands = 0;
1778 
1779  init_neighbour_context(&nctx, lc);
1780  //Ak
1781  if (AFFINE_MVP_FROM_NBS(ak)) {
1782  if (mvp_lx_flag == num_cands)
1783  return;
1784  num_cands++;
1785  }
1786  //Bk
1787  if (AFFINE_MVP_FROM_NBS(bk)) {
1788  if (mvp_lx_flag == num_cands)
1789  return;
1790  num_cands++;
1791  }
1792 
1793  //Const1
1794  if (affine_mvp_const1(&nctx, lx, ref_idx[lx], amvr_shift, cps, available)) {
1795  if (available[2] || motion_model_idc == MOTION_4_PARAMS_AFFINE) {
1796  if (mvp_lx_flag == num_cands)
1797  return;
1798  num_cands++;
1799  }
1800  }
1801 
1802  //Const2
1803  for (int i = 2; i >= 0; i--) {
1804  if (available[i]) {
1805  if (mvp_lx_flag == num_cands) {
1806  affine_mvp_const2(i, cps, num_cp);
1807  return;
1808  }
1809  num_cands++;
1810  }
1811  }
1812  if (temporal_luma_motion_vector(lc, ref_idx[lx], cps, lx, 1, 0)) {
1813  if (mvp_lx_flag == num_cands) {
1814  ff_vvc_round_mv(cps, amvr_shift, amvr_shift);
1815  for (int i = 1; i < num_cp; i++)
1816  cps[i] = cps[0];
1817  return;
1818  }
1819  num_cands++;
1820  }
1821 
1822  //Zero Mv
1823  memset(cps, 0, num_cp * sizeof(Mv));
1824 }
1825 
1826 void ff_vvc_affine_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
1827 {
1828  const CodingUnit *cu = lc->cu;
1829 
1830  mi->num_sb_x = cu->cb_width >> MIN_PU_LOG2;
1831  mi->num_sb_y = cu->cb_height >> MIN_PU_LOG2;
1832 
1833  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1834  if (mi->pred_flag != PF_L1)
1835  affine_mvp(lc, mvp_lx_flag[L0], L0, mi->ref_idx, amvr_shift, mi->motion_model_idc, &mi->mv[L0][0]);
1836  if (mi->pred_flag != PF_L0)
1837  affine_mvp(lc, mvp_lx_flag[L1], L1, mi->ref_idx, amvr_shift, mi->motion_model_idc, &mi->mv[L1][0]);
1838 }
1839 
1840 //8.5.2.14 Rounding process for motion vectors
1841 void ff_vvc_round_mv(Mv *mv, const int lshift, const int rshift)
1842 {
1843  if (rshift) {
1844  const int offset = 1 << (rshift - 1);
1845  mv->x = ((mv->x + offset - (mv->x >= 0)) >> rshift) * (1 << lshift);
1846  mv->y = ((mv->y + offset - (mv->y >= 0)) >> rshift) * (1 << lshift);
1847  } else {
1848  mv->x = mv->x * (1 << lshift);
1849  mv->y = mv->y * (1 << lshift);
1850  }
1851 }
1852 
1854 {
1855  mv->x = av_clip(mv->x, -(1 << 17), (1 << 17) - 1);
1856  mv->y = av_clip(mv->y, -(1 << 17), (1 << 17) - 1);
1857 }
1858 
1859 //8.5.2.1 Derivation process for motion vector components and reference indices
1860 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)
1861 {
1862  const uint8_t plevel = fc->ps.sps->log2_parallel_merge_level;
1863 
1864  return x0_br >> plevel > x0 >> plevel &&
1865  y0_br >> plevel > y0 >> plevel;
1866 }
1867 
1868 static void update_hmvp(MvField *hmvp, int *num_hmvp, const MvField *mvf,
1869  int (*compare)(const MvField *n, const MvField *o))
1870 {
1871  int i;
1872  for (i = 0; i < *num_hmvp; i++) {
1873  if (compare(mvf, hmvp + i)) {
1874  (*num_hmvp)--;
1875  break;
1876  }
1877  }
1878  if (i == MAX_NUM_HMVP_CANDS) {
1879  (*num_hmvp)--;
1880  i = 0;
1881  }
1882 
1883  memmove(hmvp + i, hmvp + i + 1, (*num_hmvp - i) * sizeof(MvField));
1884  hmvp[(*num_hmvp)++] = *mvf;
1885 }
1886 
1887 static int compare_l0_mv(const MvField *n, const MvField *o)
1888 {
1889  return IS_SAME_MV(&n->mv[L0], &o->mv[L0]);
1890 }
1891 
1892 //8.6.2.4 Derivation process for IBC history-based block vector candidates
1893 //8.5.2.16 Updating process for the history-based motion vector predictor candidate list
1895 {
1896  const VVCFrameContext *fc = lc->fc;
1897  const CodingUnit *cu = lc->cu;
1898  const int min_pu_width = fc->ps.pps->min_pu_width;
1899  const MvField *tab_mvf = fc->tab.mvf;
1900  EntryPoint *ep = lc->ep;
1901 
1902  if (cu->pred_mode == MODE_IBC) {
1903  if (cu->cb_width * cu->cb_height <= 16)
1904  return;
1905  update_hmvp(ep->hmvp_ibc, &ep->num_hmvp_ibc, &TAB_MVF(cu->x0, cu->y0), compare_l0_mv);
1906  } else {
1907  if (!is_greater_mer(fc, cu->x0, cu->y0, cu->x0 + cu->cb_width, cu->y0 + cu->cb_height))
1908  return;
1909  update_hmvp(ep->hmvp, &ep->num_hmvp, &TAB_MVF(cu->x0, cu->y0), compare_mv_ref_idx);
1910  }
1911 }
1912 
1913 MvField* ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0)
1914 {
1915  const int min_pu_width = fc->ps.pps->min_pu_width;
1916  MvField* tab_mvf = fc->tab.mvf;
1917 
1918  return &TAB_MVF(x0, y0);
1919 }
mv_merge_candidate
static const MvField * mv_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand)
Definition: vvc_mvs.c:615
A
#define A(x)
Definition: vpx_arith.h:28
VVCSPS
Definition: vvc_ps.h:58
sb_mv_merge_mode
static int sb_mv_merge_mode(const VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
Definition: vvc_mvs.c:1347
affine_mvp_const2
static void affine_mvp_const2(const int idx, Mv *cps, const int num_cp)
Definition: vvc_mvs.c:1760
L1
F H1 F F H1 F F F F H1<-F-------F-------F v v v H2 H3 H2 ^ ^ ^ F-------F-------F-> H1<-F-------F-------F|||||||||F H1 F|||||||||F H1 Funavailable fullpel samples(outside the picture for example) shall be equalto the closest available fullpel sampleSmaller pel interpolation:--------------------------if diag_mc is set then points which lie on a line between 2 vertically, horizontally or diagonally adjacent halfpel points shall be interpolatedlinearly with rounding to nearest and halfway values rounded up.points which lie on 2 diagonals at the same time should only use the onediagonal not containing the fullpel point F--> O q O<--h1-> O q O<--F v \/v \/v O O O O O O O|/|\|q q q q q|/|\|O O O O O O O ^/\ ^/\ ^ h2--> O q O<--h3-> O q O<--h2 v \/v \/v O O O O O O O|\|/|q q q q q|\|/|O O O O O O O ^/\ ^/\ ^ F--> O q O<--h1-> O q O<--Fthe remaining points shall be bilinearly interpolated from theup to 4 surrounding halfpel and fullpel points, again rounding should be tonearest and halfway values rounded upcompliant Snow decoders MUST support 1-1/8 pel luma and 1/2-1/16 pel chromainterpolation at leastOverlapped block motion compensation:-------------------------------------FIXMELL band prediction:===================Each sample in the LL0 subband is predicted by the median of the left, top andleft+top-topleft samples, samples outside the subband shall be considered tobe 0. To reverse this prediction in the decoder apply the following.for(y=0;y< height;y++){ for(x=0;x< width;x++){ sample[y][x]+=median(sample[y-1][x], sample[y][x-1], sample[y-1][x]+sample[y][x-1]-sample[y-1][x-1]);}}sample[-1][ *]=sample[ *][-1]=0;width, height here are the width and height of the LL0 subband not of the finalvideoDequantization:===============FIXMEWavelet Transform:==================Snow supports 2 wavelet transforms, the symmetric biorthogonal 5/3 integertransform and an integer approximation of the symmetric biorthogonal 9/7daubechies wavelet.2D IDWT(inverse discrete wavelet transform) --------------------------------------------The 2D IDWT applies a 2D filter recursively, each time combining the4 lowest frequency subbands into a single subband until only 1 subbandremains.The 2D filter is done by first applying a 1D filter in the vertical directionand then applying it in the horizontal one. --------------- --------------- --------------- ---------------|LL0|HL0|||||||||||||---+---|HL1||L0|H0|HL1||LL1|HL1|||||LH0|HH0|||||||||||||-------+-------|-> L1 H1 LH1 HH1 LH1 HH1 LH1 HH1 L1
Definition: snow.txt:554
derive_temporal_colocated_mvs
static int derive_temporal_colocated_mvs(const VVCLocalContext *lc, MvField temp_col, int refIdxLx, Mv *mvLXCol, int X, int colPic, const RefPicList *refPicList_col, int sb_flag)
Definition: vvc_mvs.c:139
td
#define td
Definition: regdef.h:70
VVCPH
Definition: vvc_ps.h:143
VVCPPS
Definition: vvc_ps.h:92
av_clip
#define av_clip
Definition: common.h:98
mv_merge_temporal_candidate
static int mv_merge_temporal_candidate(const VVCLocalContext *lc, MvField *cand)
Definition: vvc_mvs.c:677
r
const char * r
Definition: vf_curves.c:126
init_neighbour_context
static void init_neighbour_context(NeighbourContext *ctx, const VVCLocalContext *lc)
Definition: vvc_mvs.c:568
mv_merge_zero_motion_candidate
static void mv_merge_zero_motion_candidate(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list, int num_cands)
Definition: vvc_mvs.c:751
check_available
static int check_available(Neighbour *n, const VVCLocalContext *lc, const int check_mer)
Definition: vvc_mvs.c:597
MotionInfo
Definition: vvc_ctu.h:236
av_clip_int8
#define av_clip_int8
Definition: common.h:107
NUM_NBS
@ NUM_NBS
Definition: vvc_mvs.c:528
ff_vvc_get_mvf
MvField * ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0)
Definition: vvc_mvs.c:1913
CodingUnit
Definition: hevcdec.h:282
mv
static const int8_t mv[256][2]
Definition: 4xm.c:80
ff_vvc_sb_mv_merge_mode
void ff_vvc_sb_mv_merge_mode(VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
Definition: vvc_mvs.c:1394
B3
@ B3
Definition: vvc_mvs.c:527
affine_merge_const6
static int affine_merge_const6(const MvField *c0, const MvField *c2, const int cb_width, const int cb_height, MotionInfo *mi)
Definition: vvc_mvs.c:1236
PredictionUnit::gpm_partition_idx
uint8_t gpm_partition_idx
Definition: vvc_ctu.h:258
SubblockParams::d_hor_x
int d_hor_x
Definition: vvc_mvs.c:301
MIN_PU_LOG2
#define MIN_PU_LOG2
Definition: vvcdec.h:40
av_mod_uintp2
#define av_mod_uintp2
Definition: common.h:125
ph
static int FUNC() ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
Definition: cbs_h266_syntax_template.c:3000
affine_merge_candidate
static int affine_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, MotionInfo *mi)
Definition: vvc_mvs.c:922
ibc_merge_candidates
static void ibc_merge_candidates(VVCLocalContext *lc, const int merge_idx, Mv *mv)
Definition: vvc_mvs.c:1673
w
uint8_t w
Definition: llviddspenc.c:38
NeighbourAvailable::cand_left
int cand_left
Definition: hevcdec.h:308
NeighbourAvailable::cand_up
int cand_up
Definition: hevcdec.h:309
VVCLocalContext::sc
SliceContext * sc
Definition: vvc_ctu.h:430
ff_vvc_gpm_angle_idx
const uint8_t ff_vvc_gpm_angle_idx[VVC_GPM_NUM_PARTITION]
Definition: vvc_data.c:1998
affine_merge_from_nbs
static int affine_merge_from_nbs(NeighbourContext *ctx, const NeighbourIdx *nbs, const int num_nbs, MotionInfo *cand)
Definition: vvc_mvs.c:947
b
#define b
Definition: input.c:41
affine_mvp_candidate
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: vvc_mvs.c:1430
NeighbourAvailable::cand_up_right
int cand_up_right
Definition: hevcdec.h:311
derive_corner_mvf
static const MvField * derive_corner_mvf(NeighbourContext *ctx, const NeighbourIdx *neighbour, const int num_neighbour)
Definition: vvc_mvs.c:960
Mv::y
int16_t y
vertical component of motion vector
Definition: hevcdec.h:297
ff_vvc_luma_mv_merge_mode
void ff_vvc_luma_mv_merge_mode(VVCLocalContext *lc, const int merge_idx, const int ciip_flag, MvField *mv)
Definition: vvc_mvs.c:804
Neighbour::x
int x
Definition: vvc_mvs.c:533
VVCSH::r
const H266RawSliceHeader * r
RefStruct reference.
Definition: vvc_ps.h:225
sb_clip_location
static av_always_inline void sb_clip_location(const VVCFrameContext *fc, const int x_ctb, const int y_ctb, const Mv *temp_mv, int *x, int *y)
Definition: vvc_mvs.c:994
ff_vvc_mvp
void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
Definition: vvc_mvs.c:1584
Neighbour
Definition: vvc_mvs.c:532
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:464
affine_mvp
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: vvc_mvs.c:1768
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AFFINE_MVP_CONSTRUCTED_CP
#define AFFINE_MVP_CONSTRUCTED_CP(cands, cp)
Definition: vvc_mvs.c:1740
c1
static const uint64_t c1
Definition: murmur3.c:52
mv_merge_pairwise_candidate
static int mv_merge_pairwise_candidate(MvField *cand_list, const int num_cands, const int is_b)
Definition: vvc_mvs.c:712
Neighbour::available
int available
Definition: vvc_mvs.c:537
RefPicList
Definition: hevcdec.h:189
PF_INTRA
@ PF_INTRA
Definition: hevcdec.h:113
is_greater_mer
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: vvc_mvs.c:1860
is_same_mer
static av_always_inline int is_same_mer(const VVCFrameContext *fc, const int xN, const int yN, const int xP, const int yP)
Definition: vvc_mvs.c:31
ff_vvc_store_gpm_mvf
void ff_vvc_store_gpm_mvf(const VVCLocalContext *lc, const PredictionUnit *pu)
Definition: vvc_mvs.c:449
NB_IDX_NONE
@ NB_IDX_NONE
Definition: vvc_mvs.c:529
A1
@ A1
Definition: vvc_mvs.c:522
B2
@ B2
Definition: vvc_mvs.c:526
SubblockParams::cb_height
int cb_height
Definition: vvc_mvs.c:310
ibc_add_mvp
static void ibc_add_mvp(Mv *mv, Mv *mvp, const int amvr_shift)
Definition: vvc_mvs.c:1665
mvp_from_nbs
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: vvc_mvs.c:1462
VVCFrameParamSets::sps
const VVCSPS * sps
RefStruct reference.
Definition: vvc_ps.h:216
PredictionUnit::gpm_mv
MvField gpm_mv[2]
Definition: vvc_ctu.h:259
vvc_data.h
b1
static double b1(void *priv, double x, double y)
Definition: vf_xfade.c:2035
is_a0_available
static int is_a0_available(const VVCLocalContext *lc, const CodingUnit *cu)
Definition: vvc_mvs.c:545
VVCLocalContext::fc
VVCFrameContext * fc
Definition: vvc_ctu.h:431
H266RawPictureHeader::ph_prof_disabled_flag
uint8_t ph_prof_disabled_flag
Definition: cbs_h266.h:742
PredictionUnit
Definition: hevcdec.h:315
MODE_INTER
@ MODE_INTER
Definition: hevcdec.h:101
IS_SAME_MV
#define IS_SAME_MV(a, b)
Definition: vvc_mvs.c:28
SubblockParams::d_ver_y
int d_ver_y
Definition: vvc_mvs.c:304
vvc_refs.h
AFFINE_MERGE_FROM_NBS
#define AFFINE_MERGE_FROM_NBS(nbs)
Definition: vvc_mvs.c:957
SliceContext::rpl
RefPicList * rpl
Definition: vvcdec.h:88
RefPicList::nb_refs
int nb_refs
Definition: hevcdec.h:193
MotionModelIdc
MotionModelIdc
Definition: vvc_ctu.h:209
SubblockParams::d_ver_x
int d_ver_x
Definition: vvc_mvs.c:302
ibc_spatial_candidates
static int ibc_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *const cand_list, int *nb_merge_cand)
Definition: vvc_mvs.c:1597
CodingUnit::cb_width
int cb_width
Definition: vvc_ctu.h:278
MRG_MAX_NUM_CANDS
#define MRG_MAX_NUM_CANDS
Definition: hevcdec.h:55
a1
#define a1
Definition: regdef.h:47
H266RawSliceHeader::num_ref_idx_active
uint8_t num_ref_idx_active[2]
NumRefIdxActive[].
Definition: cbs_h266.h:837
C
s EdgeDetect Foobar g libavfilter vf_edgedetect c libavfilter vf_foobar c edit libavfilter and add an entry for foobar following the pattern of the other filters edit libavfilter allfilters and add an entry for foobar following the pattern of the other filters configure make j< whatever > ffmpeg ffmpeg i you should get a foobar png with Lena edge detected That s your new playground is ready Some little details about what s going which in turn will define variables for the build system and the C
Definition: writing_filters.txt:58
ff_vvc_luma_mv_merge_gpm
void ff_vvc_luma_mv_merge_gpm(VVCLocalContext *lc, const int merge_gpm_idx[2], MvField *mv)
Definition: vvc_mvs.c:817
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
mask
static const uint16_t mask[17]
Definition: lzw.c:38
SubblockParams::mv_scale_ver
int mv_scale_ver
Definition: vvc_mvs.c:306
s
#define s(width, name)
Definition: cbs_vp9.c:198
AV_ZERO64
#define AV_ZERO64(d)
Definition: intreadwrite.h:629
mi
#define mi
Definition: vf_colormatrix.c:106
affine_merge_const3
static int affine_merge_const3(const MvField *c0, const MvField *c2, const MvField *c3, MotionInfo *mi)
Definition: vvc_mvs.c:1163
ff_vvc_store_mv
void ff_vvc_store_mv(const VVCLocalContext *lc, const MotionInfo *mi)
Definition: vvc_mvs.c:500
vvc_mvs.h
B
#define B
Definition: huffyuv.h:42
SubblockParams::is_fallback
int is_fallback
Definition: vvc_mvs.c:307
ff_vvc_mv_scale
void ff_vvc_mv_scale(Mv *dst, const Mv *src, int td, int tb)
Definition: vvc_mvs.c:71
VVCSH
Definition: vvc_ps.h:224
ctx
AVFormatContext * ctx
Definition: movenc.c:48
VVCFrameParamSets::ph
VVCPH ph
Definition: vvc_ps.h:218
affine_merge_const4
static int affine_merge_const4(const MvField *c1, const MvField *c2, const MvField *c3, MotionInfo *mi)
Definition: vvc_mvs.c:1188
MAX_NUM_HMVP_CANDS
#define MAX_NUM_HMVP_CANDS
Definition: vvc_ctu.h:66
compare_l0_mv
static int compare_l0_mv(const MvField *n, const MvField *o)
Definition: vvc_mvs.c:1887
affine_cps_from_nb
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: vvc_mvs.c:843
LOCAL_ALIGNED_8
#define LOCAL_ALIGNED_8(t, v,...)
Definition: mem_internal.h:144
MOTION_6_PARAMS_AFFINE
@ MOTION_6_PARAMS_AFFINE
Definition: vvc_ctu.h:212
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
if
if(ret)
Definition: filter_design.txt:179
SubblockParams
Definition: vvc_mvs.c:300
mvp_temporal_candidates
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: vvc_mvs.c:1523
MAX_CONTROL_POINTS
#define MAX_CONTROL_POINTS
Definition: vvc_ctu.h:61
ff_vvc_no_backward_pred_flag
int ff_vvc_no_backward_pred_flag(const VVCLocalContext *lc)
Definition: vvc_mvs.c:121
mv_merge_mode
static void mv_merge_mode(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list)
Definition: vvc_mvs.c:777
NULL
#define NULL
Definition: coverity.c:32
sb_temporal_luma_motion_data
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: vvc_mvs.c:1031
av_clip_intp2
#define av_clip_intp2
Definition: common.h:119
B1
@ B1
Definition: vvc_mvs.c:525
is_fallback_mode
static int is_fallback_mode(const SubblockParams *sp, const PredFlag pred_flag)
Definition: vvc_mvs.c:313
VVCLocalContext
Definition: vvc_ctu.h:368
VVC_SLICE_TYPE_B
@ VVC_SLICE_TYPE_B
Definition: vvc.h:64
L0
#define L0
Definition: hevcdec.h:57
list
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining list
Definition: filter_design.txt:25
DERIVE_CORNER_MV
#define DERIVE_CORNER_MV(nbs)
Definition: vvc_mvs.c:974
B0
@ B0
Definition: vvc_mvs.c:524
ff_log2
#define ff_log2
Definition: intmath.h:51
ff_vvc_set_intra_mvf
void ff_vvc_set_intra_mvf(const VVCLocalContext *lc, const int dmvr)
Definition: vvc_mvs.c:265
update_hmvp
static void update_hmvp(MvField *hmvp, int *num_hmvp, const MvField *mvf, int(*compare)(const MvField *n, const MvField *o))
Definition: vvc_mvs.c:1868
abs
#define abs(x)
Definition: cuda_runtime.h:35
SubblockParams::d_hor_y
int d_hor_y
Definition: vvc_mvs.c:303
MvField::ciip_flag
uint8_t ciip_flag
ciip_flag
Definition: vvc_ctu.h:201
MV_MERGE_FROM_NB
#define MV_MERGE_FROM_NB(nb)
Definition: vvc_mvs.c:634
Mv::x
int16_t x
horizontal component of motion vector
Definition: hevcdec.h:296
Neighbour::checked
int checked
Definition: vvc_mvs.c:536
VVCPH::r
const H266RawPictureHeader * r
Definition: vvc_ps.h:144
SubblockParams::cb_width
int cb_width
Definition: vvc_mvs.c:309
mv_compression
static av_always_inline void mv_compression(Mv *motion)
Definition: vvc_mvs.c:57
PF_BI
@ PF_BI
Definition: hevcdec.h:116
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
SAMPLE_CTB
#define SAMPLE_CTB(tab, x, y)
Definition: hevcdec.h:73
ff_vvc_luma_mv_merge_ibc
void ff_vvc_luma_mv_merge_ibc(VVCLocalContext *lc, const int merge_idx, Mv *mv)
Definition: vvc_mvs.c:1698
X
@ X
Definition: vf_addroi.c:27
SliceContext
Definition: mss12.h:70
mvp
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: vvc_mvs.c:1567
NeighbourContext::neighbours
Neighbour neighbours[NUM_NBS]
Definition: vvc_mvs.c:541
f
f
Definition: af_crystalizer.c:121
EntryPoint::num_hmvp_ibc
int num_hmvp_ibc
NumHmvpIbcCand.
Definition: vvc_ctu.h:365
H266RawSliceHeader::sh_collocated_from_l0_flag
uint8_t sh_collocated_from_l0_flag
Definition: cbs_h266.h:800
pps
static int FUNC() pps(CodedBitstreamContext *ctx, RWContext *rw, H264RawPPS *current)
Definition: cbs_h264_syntax_template.c:404
RefPicList::isLongTerm
int isLongTerm[HEVC_MAX_REFS]
Definition: hevcdec.h:192
shift
static int shift(int a, int b)
Definition: bonk.c:262
NeighbourContext::lc
const VVCLocalContext * lc
Definition: vvc_mvs.c:542
sp
#define sp
Definition: regdef.h:63
mvp_candidate
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: vvc_mvs.c:1403
AFFINE_MIN_BLOCK_SIZE
#define AFFINE_MIN_BLOCK_SIZE
Definition: vvc_ctu.h:63
PredictionUnit::cb_prof_flag
int cb_prof_flag[2]
Definition: vvc_ctu.h:271
SubblockParams::mv_scale_hor
int mv_scale_hor
Definition: vvc_mvs.c:305
MvField
Definition: hevcdec.h:300
diff
static av_always_inline int diff(const struct color_info *a, const struct color_info *b, const int trans_thresh)
Definition: vf_paletteuse.c:164
PF_L1
@ PF_L1
Definition: hevcdec.h:115
PredictionUnit::diff_mv_x
int16_t diff_mv_x[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
Definition: vvc_ctu.h:269
VVCFrame
Definition: vvcdec.h:56
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
CHECK_MVSET
#define CHECK_MVSET(l)
Definition: vvc_mvs.c:114
affine_mvp_constructed_cp
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: vvc_mvs.c:1703
NeighbourIdx
NeighbourIdx
Definition: vvc_mvs.c:520
mv_merge_from_nb
static const MvField * mv_merge_from_nb(NeighbourContext *ctx, const NeighbourIdx nb)
Definition: vvc_mvs.c:625
VVCLocalContext::na
NeighbourAvailable na
Definition: vvc_ctu.h:420
MvField::pred_flag
int8_t pred_flag
Definition: hevcdec.h:303
MvField::hpel_if_idx
uint8_t hpel_if_idx
hpelIfIdx
Definition: vvc_ctu.h:198
ff_vvc_mvp_ibc
void ff_vvc_mvp_ibc(VVCLocalContext *lc, const int mvp_l0_flag, const int amvr_shift, Mv *mv)
Definition: vvc_mvs.c:1690
affine_merge_const1
static int affine_merge_const1(const MvField *c0, const MvField *c1, const MvField *c2, MotionInfo *mi)
Definition: vvc_mvs.c:1114
MAX_CU_DEPTH
#define MAX_CU_DEPTH
Definition: vvc_ctu.h:36
ff_vvc_set_mvf
void ff_vvc_set_mvf(const VVCLocalContext *lc, const int x0, const int y0, const int w, const int h, const MvField *mvf)
Definition: vvc_mvs.c:250
H266RawSliceHeader
Definition: cbs_h266.h:769
PredictionUnit::mi
MotionInfo mi
Definition: vvc_ctu.h:263
MODE_INTRA
#define MODE_INTRA
Definition: vp3.c:83
affine_merge_const_candidates
static int affine_merge_const_candidates(const VVCLocalContext *lc, MotionInfo *mi, NeighbourContext *nctx, const int merge_subblock_idx, int num_cands)
Definition: vvc_mvs.c:1275
mv_merge_spatial_candidates
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: vvc_mvs.c:637
sb_temporal_merge_candidate
static int sb_temporal_merge_candidate(const VVCLocalContext *lc, NeighbourContext *nctx, PredictionUnit *pu)
Definition: vvc_mvs.c:1066
DERIVE_TEMPORAL_COLOCATED_MVS
#define DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag)
Definition: vvc_mvs.c:194
mvp_spatial_candidates
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: vvc_mvs.c:1493
EntryPoint::hmvp
MvField hmvp[MAX_NUM_HMVP_CANDS]
HmvpCandList.
Definition: vvc_ctu.h:362
MODE_IBC
@ MODE_IBC
Definition: vvc_ctu.h:187
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
round
static av_always_inline av_const double round(double x)
Definition: libm.h:444
vvc_ctu.h
NeighbourAvailable::cand_up_left
int cand_up_left
Definition: hevcdec.h:310
available
if no frame is available
Definition: filter_design.txt:166
ff_vvc_store_sb_mvs
void ff_vvc_store_sb_mvs(const VVCLocalContext *lc, PredictionUnit *pu)
Definition: vvc_mvs.c:403
compare_mv_ref_idx
static av_always_inline int compare_mv_ref_idx(const MvField *n, const MvField *o)
Definition: vvc_mvs.c:40
IS_B
#define IS_B(rsh)
Definition: vvc_ps.h:40
pred_flag_to_mode
static av_always_inline PredMode pred_flag_to_mode(PredFlag pred)
Definition: vvc_mvs.c:592
av_always_inline
#define av_always_inline
Definition: attributes.h:49
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
PF_L0
@ PF_L0
Definition: hevcdec.h:114
CodingUnit::x0
int x0
Definition: vvc_ctu.h:276
tb
#define tb
Definition: regdef.h:68
VVCPH::poc
int32_t poc
PicOrderCntVal.
Definition: vvc_ps.h:149
affine_neighbour_cb
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: vvc_mvs.c:905
EntryPoint
Definition: vvc_ctu.h:349
ff_vvc_update_hmvp
void ff_vvc_update_hmvp(VVCLocalContext *lc, const MotionInfo *mi)
Definition: vvc_mvs.c:1894
ff_vvc_set_neighbour_available
void ff_vvc_set_neighbour_available(VVCLocalContext *lc, const int x0, const int y0, const int w, const int h)
Definition: vvc_ctu.c:2503
TAB_CP_MV
#define TAB_CP_MV(lx, x, y)
Definition: vvc_mvs.c:190
dmvr
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)
Definition: vvc_inter_template.c:324
VVCLocalContext::cu
CodingUnit * cu
Definition: vvc_ctu.h:416
ff_vvc_affine_mvp
void ff_vvc_affine_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
Definition: vvc_mvs.c:1826
ff_vvc_clip_mv
void ff_vvc_clip_mv(Mv *mv)
Definition: vvc_mvs.c:1853
pred
static const float pred[4]
Definition: siprdata.h:259
NeighbourAvailable
Definition: hevcdec.h:306
H266RawSliceHeader::sh_slice_type
uint8_t sh_slice_type
Definition: cbs_h266.h:778
sps
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
Definition: cbs_h264_syntax_template.c:260
PredictionUnit::inter_affine_flag
uint8_t inter_affine_flag
Definition: vvc_ctu.h:252
CodingUnit::cb_height
int cb_height
Definition: vvc_ctu.h:279
init_subblock_params
static void init_subblock_params(SubblockParams *sp, const MotionInfo *mi, const int cb_width, const int cb_height, const int lx)
Definition: vvc_mvs.c:338
compare
static float compare(const AVFrame *haystack, const AVFrame *obj, int offx, int offy)
Definition: vf_find_rect.c:96
c2
static const uint64_t c2
Definition: murmur3.c:53
IS_P
#define IS_P(rsh)
Definition: vvc_ps.h:39
PredMode
PredMode
Definition: hevcdec.h:100
derive_cb_prof_flag_lx
static int derive_cb_prof_flag_lx(const VVCLocalContext *lc, const PredictionUnit *pu, int lx, int is_fallback)
Definition: vvc_mvs.c:282
ff_vvc_round_mv
void ff_vvc_round_mv(Mv *mv, const int lshift, const int rshift)
Definition: vvc_mvs.c:1841
CodingUnit::pred_mode
enum PredMode pred_mode
PredMode.
Definition: hevcdec.h:286
IBC_SHIFT
#define IBC_SHIFT(v)
Definition: vvc_mvs.c:1663
affine_merge_const2
static int affine_merge_const2(const MvField *c0, const MvField *c1, const MvField *c3, MotionInfo *mi)
Definition: vvc_mvs.c:1138
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:112
affine_merge_zero_motion
static void affine_merge_zero_motion(const VVCLocalContext *lc, MotionInfo *mi)
Definition: vvc_mvs.c:1263
AFFINE_MVP_FROM_NBS
#define AFFINE_MVP_FROM_NBS(nbs)
Definition: vvc_mvs.c:1487
ff_vvc_gpm_distance_lut
const int8_t ff_vvc_gpm_distance_lut[VVC_GPM_NUM_ANGLES]
Definition: vvc_data.c:2012
RefPicList::list
int list[HEVC_MAX_REFS]
Definition: hevcdec.h:191
EntryPoint::num_hmvp
int num_hmvp
NumHmvpCand.
Definition: vvc_ctu.h:363
PredictionUnit::diff_mv_y
int16_t diff_mv_y[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
Definition: vvc_ctu.h:270
MvField::mv
Mv mv[2]
mvL0, vvL1
Definition: hevcdec.h:301
Mv
Definition: hevcdec.h:295
MOTION_4_PARAMS_AFFINE
@ MOTION_4_PARAMS_AFFINE
Definition: vvc_ctu.h:211
EntryPoint::hmvp_ibc
MvField hmvp_ibc[MAX_NUM_HMVP_CANDS]
HmvpIbcCandList.
Definition: vvc_ctu.h:364
Neighbour::y
int y
Definition: vvc_mvs.c:534
MvField::ref_idx
int8_t ref_idx[2]
refIdxL0, refIdxL1
Definition: hevcdec.h:302
derive_subblock_diff_mvs
static void derive_subblock_diff_mvs(const VVCLocalContext *lc, PredictionUnit *pu, const SubblockParams *sp, const int lx)
Definition: vvc_mvs.c:361
VVCFrameContext::ps
VVCFrameParamSets ps
Definition: vvcdec.h:101
sb_temproal_luma_motion
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: vvc_mvs.c:1003
mvp_history_candidates
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: vvc_mvs.c:1538
NeighbourContext
Definition: vvc_mvs.c:540
mv_merge_history_candidates
static int mv_merge_history_candidates(const VVCLocalContext *lc, const int merge_idx, const MvField **nb_list, MvField *cand_list, int *num_cands)
Definition: vvc_mvs.c:693
PredFlag
PredFlag
Definition: hevcdec.h:112
compare_pf_ref_idx
static av_always_inline int compare_pf_ref_idx(const MvField *A, const struct MvField *B, const struct MvField *C, const int lx)
Definition: vvc_mvs.c:977
MIN_CU_LOG2
#define MIN_CU_LOG2
Definition: vvc_ctu.h:35
SliceContext::sh
VVCSH sh
Definition: vvcdec.h:85
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
store_cp_mv
static void store_cp_mv(const VVCLocalContext *lc, const MotionInfo *mi, const int lx)
Definition: vvc_mvs.c:381
VVCFrameContext
Definition: vvcdec.h:92
d
d
Definition: ffmpeg_filter.c:409
MvField::bcw_idx
uint8_t bcw_idx
bcwIdx
Definition: vvc_ctu.h:199
A2
@ A2
Definition: vvc_mvs.c:523
check_mvset
static int check_mvset(Mv *mvLXCol, Mv *mvCol, int colPic, int poc, const RefPicList *refPicList, int X, int refIdxLx, const RefPicList *refPicList_col, int listCol, int refidxCol)
Definition: vvc_mvs.c:86
temporal_luma_motion_vector
static int temporal_luma_motion_vector(const VVCLocalContext *lc, const int refIdxLx, Mv *mvLXCol, const int X, int check_center, int sb_flag)
Definition: vvc_mvs.c:200
TAB_MVF
#define TAB_MVF(x, y)
Definition: vvc_mvs.c:184
h
h
Definition: vp9dsp_template.c:2038
ff_vvc_gpm_distance_idx
const uint8_t ff_vvc_gpm_distance_idx[VVC_GPM_NUM_PARTITION]
Definition: vvc_data.c:2005
VVCLocalContext::ep
EntryPoint * ep
Definition: vvc_ctu.h:432
ff_vvc_store_mvf
void ff_vvc_store_mvf(const VVCLocalContext *lc, const MvField *mvf)
Definition: vvc_mvs.c:494
av_log2
int av_log2(unsigned v)
Definition: intmath.c:26
ibc_history_candidates
static int ibc_history_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *cand_list, int *nb_merge_cand)
Definition: vvc_mvs.c:1635
affine_mvp_const1
static int affine_mvp_const1(NeighbourContext *nctx, const int lx, const int8_t ref_idx, const int amvr_shift, Mv *cps, int *available)
Definition: vvc_mvs.c:1745
VVCLocalContext::ctb_left_flag
uint8_t ctb_left_flag
Definition: vvc_ctu.h:369
affine_merge_const5
static int affine_merge_const5(const MvField *c0, const MvField *c1, MotionInfo *mi)
Definition: vvc_mvs.c:1213
CodingUnit::y0
int y0
Definition: vvc_ctu.h:277
MVP_FROM_NBS
#define MVP_FROM_NBS(nbs)
Definition: vvc_mvs.c:1490
A0
@ A0
Definition: vvc_mvs.c:521
PF_IBC
@ PF_IBC
Definition: vvc_ctu.h:220