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 = {0};
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  for (int i = 0; i < 2; i++) {
416  const PredFlag mask = i + 1;
417  if (mi->pred_flag & mask) {
418  store_cp_mv(lc, mi, i);
419  init_subblock_params(params + i, mi, cu->cb_width, cu->cb_height, i);
420  derive_subblock_diff_mvs(lc, pu, params + i, i);
421  mvf.ref_idx[i] = mi->ref_idx[i];
422  }
423  }
424 
425  for (int sby = 0; sby < mi->num_sb_y; sby++) {
426  for (int sbx = 0; sbx < mi->num_sb_x; sbx++) {
427  const int x0 = cu->x0 + sbx * sbw;
428  const int y0 = cu->y0 + sby * sbh;
429  for (int i = 0; i < 2; i++) {
430  const PredFlag mask = i + 1;
431  if (mi->pred_flag & mask) {
432  const SubblockParams* sp = params + i;
433  const int x_pos_cb = sp->is_fallback ? (cu->cb_width >> 1) : (2 + (sbx << MIN_CU_LOG2));
434  const int y_pos_cb = sp->is_fallback ? (cu->cb_height >> 1) : (2 + (sby << MIN_CU_LOG2));
435  Mv *mv = mvf.mv + i;
436 
437  mv->x = sp->mv_scale_hor + sp->d_hor_x * x_pos_cb + sp->d_hor_y * y_pos_cb;
438  mv->y = sp->mv_scale_ver + sp->d_ver_x * x_pos_cb + sp->d_ver_y * y_pos_cb;
441  }
442  }
443  ff_vvc_set_mvf(lc, x0, y0, sbw, sbh, &mvf);
444  }
445  }
446 }
447 
449 {
450  const CodingUnit *cu = lc->cu;
451  const int angle_idx = ff_vvc_gpm_angle_idx[pu->gpm_partition_idx];
452  const int distance_idx = ff_vvc_gpm_distance_idx[pu->gpm_partition_idx];
453  const int displacement_x = ff_vvc_gpm_distance_lut[angle_idx];
454  const int displacement_y = ff_vvc_gpm_distance_lut[(angle_idx + 8) % 32];
455  const int is_flip = angle_idx >= 13 &&angle_idx <= 27;
456  const int shift_hor = (angle_idx % 16 == 8 || (angle_idx % 16 && cu->cb_height >= cu->cb_width)) ? 0 : 1;
457  const int sign = angle_idx < 16 ? 1 : -1;
458  const int block_size = 4;
459  int offset_x = (-cu->cb_width) >> 1;
460  int offset_y = (-cu->cb_height) >> 1;
461 
462  if (!shift_hor)
463  offset_y += sign * ((distance_idx * cu->cb_height) >> 3);
464  else
465  offset_x += sign * ((distance_idx * cu->cb_width) >> 3);
466 
467  for (int y = 0; y < cu->cb_height; y += block_size) {
468  for (int x = 0; x < cu->cb_width; x += block_size) {
469  const int motion_idx = (((x + offset_x) * (1 << 1)) + 5) * displacement_x +
470  (((y + offset_y) * (1 << 1)) + 5) * displacement_y;
471  const int s_type = FFABS(motion_idx) < 32 ? 2 : (motion_idx <= 0 ? (1 - is_flip) : is_flip);
472  const int pred_flag = pu->gpm_mv[0].pred_flag | pu->gpm_mv[1].pred_flag;
473  const int x0 = cu->x0 + x;
474  const int y0 = cu->y0 + y;
475 
476  if (!s_type)
477  ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, pu->gpm_mv + 0);
478  else if (s_type == 1 || (s_type == 2 && pred_flag != PF_BI))
479  ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, pu->gpm_mv + 1);
480  else {
481  MvField mvf = pu->gpm_mv[0];
482  const MvField *mv1 = &pu->gpm_mv[1];
483  const int lx = mv1->pred_flag - PF_L0;
484  mvf.pred_flag = PF_BI;
485  mvf.ref_idx[lx] = mv1->ref_idx[lx];
486  mvf.mv[lx] = mv1->mv[lx];
487  ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, &mvf);
488  }
489  }
490  }
491 }
492 
493 void ff_vvc_store_mvf(const VVCLocalContext *lc, const MvField *mvf)
494 {
495  const CodingUnit *cu = lc->cu;
496  ff_vvc_set_mvf(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height, mvf);
497 }
498 
500 {
501  const CodingUnit *cu = lc->cu;
502  MvField mvf = {0};
503 
504  mvf.hpel_if_idx = mi->hpel_if_idx;
505  mvf.bcw_idx = mi->bcw_idx;
506  mvf.pred_flag = mi->pred_flag;
507 
508  for (int i = 0; i < 2; i++) {
509  const PredFlag mask = i + 1;
510  if (mvf.pred_flag & mask) {
511  mvf.mv[i] = mi->mv[i][0];
512  mvf.ref_idx[i] = mi->ref_idx[i];
513  }
514  }
515  ff_vvc_set_mvf(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height, &mvf);
516 }
517 
518 typedef enum NeighbourIdx {
519  A0,
520  A1,
521  A2,
522  B0,
523  B1,
524  B2,
525  B3,
528 } NeighbourIdx;
529 
530 typedef struct Neighbour {
531  int x;
532  int y;
533 
534  int checked;
536 } Neighbour;
537 
538 typedef struct NeighbourContext {
542 
543 static int is_a0_available(const VVCLocalContext *lc, const CodingUnit *cu)
544 {
545  const VVCFrameContext *fc = lc->fc;
546  const VVCSPS *sps = fc->ps.sps;
547  const int x0b = av_mod_uintp2(cu->x0, sps->ctb_log2_size_y);
548  int cand_bottom_left;
549 
550  if (!x0b && !lc->ctb_left_flag) {
551  cand_bottom_left = 0;
552  } else {
553  const int log2_min_cb_size = sps->min_cb_log2_size_y;
554  const int min_cb_width = fc->ps.pps->min_cb_width;
555  const int x = (cu->x0 - 1) >> log2_min_cb_size;
556  const int y = (cu->y0 + cu->cb_height) >> log2_min_cb_size;
557  const int max_y = FFMIN(fc->ps.pps->height, ((cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y);
558  if (cu->y0 + cu->cb_height >= max_y)
559  cand_bottom_left = 0;
560  else
561  cand_bottom_left = SAMPLE_CTB(fc->tab.cb_width[0], x, y) != 0;
562  }
563  return cand_bottom_left;
564 }
565 
567 {
568  const CodingUnit *cu = lc->cu;
569  const NeighbourAvailable *na = &lc->na;
570  const int x0 = cu->x0;
571  const int y0 = cu->y0;
572  const int cb_width = cu->cb_width;
573  const int cb_height = cu->cb_height;
574  const int a0_available = is_a0_available(lc, cu);
575 
576  Neighbour neighbours[NUM_NBS] = {
577  { x0 - 1, y0 + cb_height, !a0_available }, //A0
578  { x0 - 1, y0 + cb_height - 1, !na->cand_left }, //A1
579  { x0 - 1, y0, !na->cand_left }, //A2
580  { x0 + cb_width, y0 - 1, !na->cand_up_right }, //B0
581  { x0 + cb_width - 1, y0 - 1, !na->cand_up }, //B1
582  { x0 - 1, y0 - 1, !na->cand_up_left }, //B2
583  { x0, y0 - 1, !na->cand_up }, //B3
584  };
585 
586  memcpy(ctx->neighbours, neighbours, sizeof(neighbours));
587  ctx->lc = lc;
588 }
589 
591 {
592  return pred == PF_IBC ? MODE_IBC : (pred == PF_INTRA ? MODE_INTRA : MODE_INTER);
593 }
594 
595 static int check_available(Neighbour *n, const VVCLocalContext *lc, const int check_mer)
596 {
597  const VVCFrameContext *fc = lc->fc;
598  const VVCSPS *sps = fc->ps.sps;
599  const CodingUnit *cu = lc->cu;
600  const MvField *tab_mvf = fc->tab.mvf;
601  const int min_pu_width = fc->ps.pps->min_pu_width;
602 
603  if (!n->checked) {
604  n->checked = 1;
605  n->available = !sps->r->sps_entropy_coding_sync_enabled_flag || ((n->x >> sps->ctb_log2_size_y) <= (cu->x0 >> sps->ctb_log2_size_y));
606  n->available &= cu->pred_mode == pred_flag_to_mode(TAB_MVF(n->x, n->y).pred_flag);
607  if (check_mer)
608  n->available &= !is_same_mer(fc, n->x, n->y, cu->x0, cu->y0);
609  }
610  return n->available;
611 }
612 
613 static const MvField *mv_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand)
614 {
615  const VVCFrameContext *fc = lc->fc;
616  const int min_pu_width = fc->ps.pps->min_pu_width;
617  const MvField* tab_mvf = fc->tab.mvf;
618  const MvField *mvf = &TAB_MVF(x_cand, y_cand);
619 
620  return mvf;
621 }
622 
624 {
625  const VVCLocalContext *lc = ctx->lc;
626  Neighbour *n = &ctx->neighbours[nb];
627 
628  if (check_available(n, lc, 1))
629  return mv_merge_candidate(lc, n->x, n->y);
630  return 0;
631 }
632 #define MV_MERGE_FROM_NB(nb) mv_merge_from_nb(&nctx, nb)
633 
634 //8.5.2.3 Derivation process for spatial merging candidates
635 static int mv_merge_spatial_candidates(const VVCLocalContext *lc, const int merge_idx,
636  const MvField **nb_list, MvField *cand_list, int *nb_merge_cand)
637 {
638  const MvField *cand;
639  int num_cands = 0;
640  NeighbourContext nctx;
641 
642  static NeighbourIdx nbs[][2] = {
643  {B1, NB_IDX_NONE },
644  {A1, B1 },
645  {B0, B1 },
646  {A0, A1 },
647  };
648 
649  init_neighbour_context(&nctx, lc);
650  for (int i = 0; i < FF_ARRAY_ELEMS(nbs); i++) {
651  NeighbourIdx nb = nbs[i][0];
652  NeighbourIdx old = nbs[i][1];
653  cand = nb_list[nb] = MV_MERGE_FROM_NB(nb);
654  if (cand && !compare_mv_ref_idx(cand, nb_list[old])) {
655  cand_list[num_cands] = *cand;
656  if (merge_idx == num_cands)
657  return 1;
658  num_cands++;
659  }
660  }
661  if (num_cands != 4) {
662  cand = MV_MERGE_FROM_NB(B2);
663  if (cand && !compare_mv_ref_idx(cand, nb_list[A1])
664  && !compare_mv_ref_idx(cand, nb_list[B1])) {
665  cand_list[num_cands] = *cand;
666  if (merge_idx == num_cands)
667  return 1;
668  num_cands++;
669  }
670  }
671  *nb_merge_cand = num_cands;
672  return 0;
673 }
674 
676 {
677  const VVCFrameContext *fc = lc->fc;
678  const CodingUnit *cu = lc->cu;
679 
680  memset(cand, 0, sizeof(*cand));
681  if (fc->ps.ph.r->ph_temporal_mvp_enabled_flag && (cu->cb_width * cu->cb_height > 32)) {
682  int available_l0 = temporal_luma_motion_vector(lc, 0, cand->mv + 0, 0, 1, 0);
683  int available_l1 = IS_B(lc->sc->sh.r) ?
684  temporal_luma_motion_vector(lc, 0, cand->mv + 1, 1, 1, 0) : 0;
685  cand->pred_flag = available_l0 + (available_l1 << 1);
686  }
687  return cand->pred_flag;
688 }
689 
690 //8.5.2.6 Derivation process for history-based merging candidates
691 static int mv_merge_history_candidates(const VVCLocalContext *lc, const int merge_idx,
692  const MvField **nb_list, MvField *cand_list, int *num_cands)
693 {
694  const VVCSPS *sps = lc->fc->ps.sps;
695  const EntryPoint* ep = lc->ep;
696  for (int i = 1; i <= ep->num_hmvp && (*num_cands < sps->max_num_merge_cand - 1); i++) {
697  const MvField *h = &ep->hmvp[ep->num_hmvp - i];
698  const int same_motion = i <= 2 && (compare_mv_ref_idx(h, nb_list[A1]) || compare_mv_ref_idx(h, nb_list[B1]));
699  if (!same_motion) {
700  cand_list[*num_cands] = *h;
701  if (merge_idx == *num_cands)
702  return 1;
703  (*num_cands)++;
704  }
705  }
706  return 0;
707 }
708 
709 //8.5.2.4 Derivation process for pairwise average merging candidate
710 static int mv_merge_pairwise_candidate(MvField *cand_list, const int num_cands, const int is_b)
711 {
712  if (num_cands > 1) {
713  const int num_ref_rists = is_b ? 2 : 1;
714  const MvField* p0 = cand_list + 0;
715  const MvField* p1 = cand_list + 1;
716  MvField* cand = cand_list + num_cands;
717 
718  cand->pred_flag = 0;
719  for (int i = 0; i < num_ref_rists; i++) {
720  PredFlag mask = i + 1;
721  if (p0->pred_flag & mask) {
722  cand->pred_flag |= mask;
723  cand->ref_idx[i] = p0->ref_idx[i];
724  if (p1->pred_flag & mask) {
725  Mv *mv = cand->mv + i;
726  mv->x = p0->mv[i].x + p1->mv[i].x;
727  mv->y = p0->mv[i].y + p1->mv[i].y;
728  ff_vvc_round_mv(mv, 0, 1);
729  } else {
730  cand->mv[i] = p0->mv[i];
731  }
732  } else if (p1->pred_flag & mask) {
733  cand->pred_flag |= mask;
734  cand->mv[i] = p1->mv[i];
735  cand->ref_idx[i] = p1->ref_idx[i];
736  }
737  }
738  if (cand->pred_flag) {
739  cand->hpel_if_idx = p0->hpel_if_idx == p1->hpel_if_idx ? p0->hpel_if_idx : 0;
740  cand->bcw_idx = 0;
741  cand->ciip_flag = 0;
742  return 1;
743  }
744  }
745  return 0;
746 }
747 
748 //8.5.2.5 Derivation process for zero motion vector merging candidates
749 static void mv_merge_zero_motion_candidate(const VVCLocalContext *lc, const int merge_idx,
750  MvField *cand_list, int num_cands)
751 {
752  const VVCSPS *sps = lc->fc->ps.sps;
753  const H266RawSliceHeader *rsh = lc->sc->sh.r;
754  const int num_ref_idx = IS_P(rsh) ?
756  int zero_idx = 0;
757 
758  while (num_cands < sps->max_num_merge_cand) {
759  MvField *cand = cand_list + num_cands;
760 
761  cand->pred_flag = PF_L0 + (IS_B(rsh) << 1);
762  AV_ZERO64(cand->mv + 0);
763  AV_ZERO64(cand->mv + 1);
764  cand->ref_idx[0] = zero_idx < num_ref_idx ? zero_idx : 0;
765  cand->ref_idx[1] = zero_idx < num_ref_idx ? zero_idx : 0;
766  cand->bcw_idx = 0;
767  cand->hpel_if_idx = 0;
768  if (merge_idx == num_cands)
769  return;
770  num_cands++;
771  zero_idx++;
772  }
773 }
774 
775 static void mv_merge_mode(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list)
776 {
777  int num_cands = 0;
778  const MvField *nb_list[NUM_NBS + 1] = { NULL };
779 
780  if (mv_merge_spatial_candidates(lc, merge_idx, nb_list, cand_list, &num_cands))
781  return;
782 
783  if (mv_merge_temporal_candidate(lc, &cand_list[num_cands])) {
784  if (merge_idx == num_cands)
785  return;
786  num_cands++;
787  }
788 
789  if (mv_merge_history_candidates(lc, merge_idx, nb_list, cand_list, &num_cands))
790  return;
791 
792  if (mv_merge_pairwise_candidate(cand_list, num_cands, IS_B(lc->sc->sh.r))) {
793  if (merge_idx == num_cands)
794  return;
795  num_cands++;
796  }
797 
798  mv_merge_zero_motion_candidate(lc, merge_idx, cand_list, num_cands);
799 }
800 
801 //8.5.2.2 Derivation process for luma motion vectors for merge mode
802 void ff_vvc_luma_mv_merge_mode(VVCLocalContext *lc, const int merge_idx, const int ciip_flag, MvField *mv)
803 {
804  const CodingUnit *cu = lc->cu;
805  MvField cand_list[MRG_MAX_NUM_CANDS];
806 
807  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
808  mv_merge_mode(lc, merge_idx, cand_list);
809  *mv = cand_list[merge_idx];
810  //ciip flag in not inhritable
811  mv->ciip_flag = ciip_flag;
812 }
813 
814 //8.5.4.2 Derivation process for luma motion vectors for geometric partitioning merge mode
815 void ff_vvc_luma_mv_merge_gpm(VVCLocalContext *lc, const int merge_gpm_idx[2], MvField *mv)
816 {
817  const CodingUnit *cu = lc->cu;
818  MvField cand_list[MRG_MAX_NUM_CANDS];
819 
820  const int idx[] = { merge_gpm_idx[0], merge_gpm_idx[1] + (merge_gpm_idx[1] >= merge_gpm_idx[0]) };
821 
822  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
823  mv_merge_mode(lc, FFMAX(idx[0], idx[1]), cand_list);
824  memset(mv, 0, 2 * sizeof(*mv));
825  for (int i = 0; i < 2; i++) {
826  int lx = idx[i] & 1;
827  int mask = lx + PF_L0;
828  MvField *cand = cand_list + idx[i];
829  if (!(cand->pred_flag & mask)) {
830  lx = !lx;
831  mask = lx + PF_L0;
832  }
833  mv[i].pred_flag = mask;
834  mv[i].ref_idx[lx] = cand->ref_idx[lx];
835  mv[i].mv[lx] = cand->mv[lx];
836  }
837 
838 }
839 
840 //8.5.5.5 Derivation process for luma affine control point motion vectors from a neighbouring block
841 static void affine_cps_from_nb(const VVCLocalContext *lc,
842  const int x_nb, int y_nb, const int nbw, const int nbh, const int lx,
843  Mv *cps, int num_cps)
844 {
845  const VVCFrameContext *fc = lc->fc;
846  const CodingUnit *cu = lc->cu;
847  const int x0 = cu->x0;
848  const int y0 = cu->y0;
849  const int cb_width = cu->cb_width;
850  const int cb_height = cu->cb_height;
851  const MvField* tab_mvf = fc->tab.mvf;
852  const int min_cb_log2_size = fc->ps.sps->min_cb_log2_size_y;
853  const int min_cb_width = fc->ps.pps->min_cb_width;
854 
855  const int log2_nbw = ff_log2(nbw);
856  const int log2_nbh = ff_log2(nbh);
857  const int is_ctb_boundary = !((y_nb + nbh) % fc->ps.sps->ctb_size_y) && (y_nb + nbh == y0);
858  const Mv *l, *r;
859  int mv_scale_hor, mv_scale_ver, d_hor_x, d_ver_x, d_hor_y, d_ver_y, motion_model_idc_nb;
860  if (is_ctb_boundary) {
861  const int min_pu_width = fc->ps.pps->min_pu_width;
862  l = &TAB_MVF(x_nb, y_nb + nbh - 1).mv[lx];
863  r = &TAB_MVF(x_nb + nbw - 1, y_nb + nbh - 1).mv[lx];
864  } else {
865  const int x = x_nb >> min_cb_log2_size;
866  const int y = y_nb >> min_cb_log2_size;
867  motion_model_idc_nb = SAMPLE_CTB(fc->tab.mmi, x, y);
868 
869  l = &TAB_CP_MV(lx, x_nb, y_nb);
870  r = &TAB_CP_MV(lx, x_nb + nbw - 1, y_nb) + 1;
871  }
872  mv_scale_hor = l->x * (1 << 7);
873  mv_scale_ver = l->y * (1 << 7);
874  d_hor_x = (r->x - l->x) * (1 << (7 - log2_nbw));
875  d_ver_x = (r->y - l->y) * (1 << (7 - log2_nbw));
876  if (!is_ctb_boundary && motion_model_idc_nb == MOTION_6_PARAMS_AFFINE) {
877  const Mv* lb = &TAB_CP_MV(lx, x_nb, y_nb + nbh - 1) + 2;
878  d_hor_y = (lb->x - l->x) * (1 << (7 - log2_nbh));
879  d_ver_y = (lb->y - l->y) * (1 << (7 - log2_nbh));
880  } else {
881  d_hor_y = -d_ver_x;
882  d_ver_y = d_hor_x;
883  }
884 
885  if (is_ctb_boundary) {
886  y_nb = y0;
887  }
888  cps[0].x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 - y_nb);
889  cps[0].y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 - y_nb);
890  cps[1].x = mv_scale_hor + d_hor_x * (x0 + cb_width - x_nb) + d_hor_y * (y0 - y_nb);
891  cps[1].y = mv_scale_ver + d_ver_x * (x0 + cb_width - x_nb) + d_ver_y * (y0 - y_nb);
892  if (num_cps == 3) {
893  cps[2].x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 + cb_height - y_nb);
894  cps[2].y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 + cb_height - y_nb);
895  }
896  for (int i = 0; i < num_cps; i++) {
897  ff_vvc_round_mv(cps + i, 0, 7);
898  ff_vvc_clip_mv(cps + i);
899  }
900 }
901 
902 //derive affine neighbour's postion, width and height,
903 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)
904 {
905  const int log2_min_cb_size = fc->ps.sps->min_cb_log2_size_y;
906  const int min_cb_width = fc->ps.pps->min_cb_width;
907  const int x = x_nb >> log2_min_cb_size;
908  const int y = y_nb >> log2_min_cb_size;
909  const int motion_model_idc = SAMPLE_CTB(fc->tab.mmi, x, y);
910  if (motion_model_idc) {
911  *x_cb = SAMPLE_CTB(fc->tab.cb_pos_x[0], x, y);
912  *y_cb = SAMPLE_CTB(fc->tab.cb_pos_y[0], x, y);
913  *cbw = SAMPLE_CTB(fc->tab.cb_width[0], x, y);
914  *cbh = SAMPLE_CTB(fc->tab.cb_height[0], x, y);
915  }
916  return motion_model_idc;
917 }
918 
919 //part of 8.5.5.2 Derivation process for motion vectors and reference indices in subblock merge mode
920 static int affine_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand, MotionInfo* mi)
921 {
922  const VVCFrameContext *fc = lc->fc;
923  int x, y, w, h, motion_model_idc;
924 
925  motion_model_idc = affine_neighbour_cb(fc, x_cand, y_cand, &x, &y, &w, &h);
926  if (motion_model_idc) {
927  const int min_pu_width = fc->ps.pps->min_pu_width;
928  const MvField* tab_mvf = fc->tab.mvf;
929  const MvField *mvf = &TAB_MVF(x, y);
930 
931  mi->bcw_idx = mvf->bcw_idx;
932  mi->pred_flag = mvf->pred_flag;
933  for (int i = 0; i < 2; i++) {
934  PredFlag mask = i + 1;
935  if (mi->pred_flag & mask) {
936  affine_cps_from_nb(lc, x, y, w, h, i, &mi->mv[i][0], motion_model_idc + 1);
937  }
938  mi->ref_idx[i] = mvf->ref_idx[i];
939  }
940  mi->motion_model_idc = motion_model_idc;
941  }
942  return motion_model_idc;
943 }
944 
945 static int affine_merge_from_nbs(NeighbourContext *ctx, const NeighbourIdx *nbs, const int num_nbs, MotionInfo* cand)
946 {
947  const VVCLocalContext *lc = ctx->lc;
948  for (int i = 0; i < num_nbs; i++) {
949  Neighbour *n = &ctx->neighbours[nbs[i]];
950  if (check_available(n, lc, 1) && affine_merge_candidate(lc, n->x, n->y, cand))
951  return 1;
952  }
953  return 0;
954 }
955 #define AFFINE_MERGE_FROM_NBS(nbs) affine_merge_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), mi)
956 
957 
958 static const MvField* derive_corner_mvf(NeighbourContext *ctx, const NeighbourIdx *neighbour, const int num_neighbour)
959 {
960  const VVCFrameContext *fc = ctx->lc->fc;
961  const MvField *tab_mvf = fc->tab.mvf;
962  const int min_pu_width = fc->ps.pps->min_pu_width;
963  for (int i = 0; i < num_neighbour; i++) {
964  Neighbour *n = &ctx->neighbours[neighbour[i]];
965  if (check_available(n, ctx->lc, 1)) {
966  return &TAB_MVF(n->x, n->y);
967  }
968  }
969  return NULL;
970 }
971 
972 #define DERIVE_CORNER_MV(nbs) derive_corner_mvf(nctx, nbs, FF_ARRAY_ELEMS(nbs))
973 
974 // check if the mv's and refidx are the same between A and B
975 static av_always_inline int compare_pf_ref_idx(const MvField *A, const struct MvField *B, const struct MvField *C, const int lx)
976 {
977 
978  const PredFlag mask = (lx + 1) & A->pred_flag;
979  if (!(B->pred_flag & mask))
980  return 0;
981  if (A->ref_idx[lx] != B->ref_idx[lx])
982  return 0;
983  if (C) {
984  if (!(C->pred_flag & mask))
985  return 0;
986  if (A->ref_idx[lx] != C->ref_idx[lx])
987  return 0;
988  }
989  return 1;
990 }
991 
993  const int x_ctb, const int y_ctb, const Mv* temp_mv, int *x, int *y)
994 {
995  const VVCPPS *pps = fc->ps.pps;
996  const int ctb_log2_size = fc->ps.sps->ctb_log2_size_y;
997  *y = av_clip(*y + temp_mv->y, y_ctb, FFMIN(pps->height - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7;
998  *x = av_clip(*x + temp_mv->x, x_ctb, FFMIN(pps->width - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7;
999 }
1000 
1002  const int x_ctb, const int y_ctb, const Mv *temp_mv,
1003  int x, int y, uint8_t *pred_flag, Mv *mv)
1004 {
1005  MvField temp_col;
1006  Mv* mvLXCol;
1007  const int refIdxLx = 0;
1008  const VVCFrameContext *fc = lc->fc;
1009  const VVCSH *sh = &lc->sc->sh;
1010  const int min_pu_width = fc->ps.pps->min_pu_width;
1011  VVCFrame *ref = fc->ref->collocated_ref;
1012  MvField *tab_mvf = ref->tab_dmvr_mvf;
1013  int colPic = ref->poc;
1014  int X = 0;
1015 
1016  sb_clip_location(fc, x_ctb, y_ctb, temp_mv, &x, &y);
1017 
1018  temp_col = TAB_MVF(x, y);
1019  mvLXCol = mv + 0;
1020  *pred_flag = DERIVE_TEMPORAL_COLOCATED_MVS(1);
1021  if (IS_B(sh->r)) {
1022  X = 1;
1023  mvLXCol = mv + 1;
1024  *pred_flag |= (DERIVE_TEMPORAL_COLOCATED_MVS(1)) << 1;
1025  }
1026 }
1027 
1028 //8.5.5.4 Derivation process for subblock-based temporal merging base motion data
1030  const int x_ctb, const int y_ctb, MvField *ctr_mvf, Mv *temp_mv)
1031 {
1032  const VVCFrameContext *fc = lc->fc;
1033  const RefPicList *rpl = lc->sc->rpl;
1034  const CodingUnit *cu = lc->cu;
1035  const int x = cu->x0 + cu->cb_width / 2;
1036  const int y = cu->y0 + cu->cb_height / 2;
1037  const VVCFrame *ref = fc->ref->collocated_ref;
1038 
1039  int colPic;
1040 
1041  memset(temp_mv, 0, sizeof(*temp_mv));
1042 
1043  if (!ref) {
1044  memset(ctr_mvf, 0, sizeof(*ctr_mvf));
1045  return 0;
1046  }
1047 
1048  colPic = ref->poc;
1049 
1050  if (a1) {
1051  if ((a1->pred_flag & PF_L0) && colPic == rpl[0].list[a1->ref_idx[0]])
1052  *temp_mv = a1->mv[0];
1053  else if ((a1->pred_flag & PF_L1) && colPic == rpl[1].list[a1->ref_idx[1]])
1054  *temp_mv = a1->mv[1];
1055  ff_vvc_round_mv(temp_mv, 0, 4);
1056  }
1057  sb_temproal_luma_motion(lc, x_ctb, y_ctb, temp_mv, x, y, &ctr_mvf->pred_flag , ctr_mvf->mv);
1058 
1059  return ctr_mvf->pred_flag;
1060 }
1061 
1062 
1063 //8.5.5.3 Derivation process for subblock-based temporal merging candidates
1065 {
1066  const VVCFrameContext *fc = lc->fc;
1067  const CodingUnit *cu = lc->cu;
1068  const VVCSPS *sps = fc->ps.sps;
1069  const VVCPH *ph = &fc->ps.ph;
1070  MotionInfo *mi = &pu->mi;
1071  const int ctb_log2_size = sps->ctb_log2_size_y;
1072  const int x0 = cu->x0;
1073  const int y0 = cu->y0;
1074  const NeighbourIdx n = A1;
1075  const MvField *a1;
1076  MvField ctr_mvf;
1077  LOCAL_ALIGNED_8(Mv, temp_mv, [1]);
1078  const int x_ctb = (x0 >> ctb_log2_size) << ctb_log2_size;
1079  const int y_ctb = (y0 >> ctb_log2_size) << ctb_log2_size;
1080 
1081 
1082  if (!ph->r->ph_temporal_mvp_enabled_flag ||
1083  !sps->r->sps_sbtmvp_enabled_flag ||
1084  (cu->cb_width < 8 && cu->cb_height < 8))
1085  return 0;
1086 
1087  mi->num_sb_x = cu->cb_width >> 3;
1088  mi->num_sb_y = cu->cb_height >> 3;
1089 
1090  a1 = derive_corner_mvf(nctx, &n, 1);
1091  if (sb_temporal_luma_motion_data(lc, a1, x_ctb, y_ctb, &ctr_mvf, temp_mv)) {
1092  const int sbw = cu->cb_width / mi->num_sb_x;
1093  const int sbh = cu->cb_height / mi->num_sb_y;
1094  MvField mvf = {0};
1095  for (int sby = 0; sby < mi->num_sb_y; sby++) {
1096  for (int sbx = 0; sbx < mi->num_sb_x; sbx++) {
1097  int x = x0 + sbx * sbw;
1098  int y = y0 + sby * sbh;
1099  sb_temproal_luma_motion(lc, x_ctb, y_ctb, temp_mv, x + sbw / 2, y + sbh / 2, &mvf.pred_flag, mvf.mv);
1100  if (!mvf.pred_flag) {
1101  mvf.pred_flag = ctr_mvf.pred_flag;
1102  memcpy(mvf.mv, ctr_mvf.mv, sizeof(mvf.mv));
1103  }
1104  ff_vvc_set_mvf(lc, x, y, sbw, sbh, &mvf);
1105  }
1106  }
1107  return 1;
1108  }
1109  return 0;
1110 }
1111 
1112 static int affine_merge_const1(const MvField *c0, const MvField *c1, const MvField *c2, MotionInfo *mi)
1113 {
1114  if (c0 && c1 && c2) {
1115  mi->pred_flag = 0;
1116  for (int i = 0; i < 2; i++) {
1117  PredFlag mask = i + 1;
1118  if (compare_pf_ref_idx(c0, c1, c2, i)) {
1119  mi->pred_flag |= mask;
1120  mi->ref_idx[i] = c0->ref_idx[i];
1121  mi->mv[i][0] = c0->mv[i];
1122  mi->mv[i][1] = c1->mv[i];
1123  mi->mv[i][2] = c2->mv[i];
1124  }
1125  }
1126  if (mi->pred_flag) {
1127  if (mi->pred_flag == PF_BI)
1128  mi->bcw_idx = c0->bcw_idx;
1129  mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1130  return 1;
1131  }
1132  }
1133  return 0;
1134 }
1135 
1136 static int affine_merge_const2(const MvField *c0, const MvField *c1, const MvField *c3, MotionInfo *mi)
1137 {
1138  if (c0 && c1 && c3) {
1139  mi->pred_flag = 0;
1140  for (int i = 0; i < 2; i++) {
1141  PredFlag mask = i + 1;
1142  if (compare_pf_ref_idx(c0, c1, c3, i)) {
1143  mi->pred_flag |= mask;
1144  mi->ref_idx[i] = c0->ref_idx[i];
1145  mi->mv[i][0] = c0->mv[i];
1146  mi->mv[i][1] = c1->mv[i];
1147  mi->mv[i][2].x = c3->mv[i].x + c0->mv[i].x - c1->mv[i].x;
1148  mi->mv[i][2].y = c3->mv[i].y + c0->mv[i].y - c1->mv[i].y;
1149  ff_vvc_clip_mv(&mi->mv[i][2]);
1150  }
1151  }
1152  if (mi->pred_flag) {
1153  mi->bcw_idx = mi->pred_flag == PF_BI ? c0->bcw_idx : 0;
1154  mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1155  return 1;
1156  }
1157  }
1158  return 0;
1159 }
1160 
1161 static int affine_merge_const3(const MvField *c0, const MvField *c2, const MvField *c3, MotionInfo *mi)
1162 {
1163  if (c0 && c2 && c3) {
1164  mi->pred_flag = 0;
1165  for (int i = 0; i < 2; i++) {
1166  PredFlag mask = i + 1;
1167  if (compare_pf_ref_idx(c0, c2, c3, i)) {
1168  mi->pred_flag |= mask;
1169  mi->ref_idx[i] = c0->ref_idx[i];
1170  mi->mv[i][0] = c0->mv[i];
1171  mi->mv[i][1].x = c3->mv[i].x + c0->mv[i].x - c2->mv[i].x;
1172  mi->mv[i][1].y = c3->mv[i].y + c0->mv[i].y - c2->mv[i].y;
1173  ff_vvc_clip_mv(&mi->mv[i][1]);
1174  mi->mv[i][2] = c2->mv[i];
1175  }
1176  }
1177  if (mi->pred_flag) {
1178  mi->bcw_idx = mi->pred_flag == PF_BI ? c0->bcw_idx : 0;
1179  mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1180  return 1;
1181  }
1182  }
1183  return 0;
1184 }
1185 
1186 static int affine_merge_const4(const MvField *c1, const MvField *c2, const MvField *c3, MotionInfo *mi)
1187 {
1188  if (c1 && c2 && c3) {
1189  mi->pred_flag = 0;
1190  for (int i = 0; i < 2; i++) {
1191  PredFlag mask = i + 1;
1192  if (compare_pf_ref_idx(c1, c2, c3, i)) {
1193  mi->pred_flag |= mask;
1194  mi->ref_idx[i] = c1->ref_idx[i];
1195  mi->mv[i][0].x = c1->mv[i].x + c2->mv[i].x - c3->mv[i].x;
1196  mi->mv[i][0].y = c1->mv[i].y + c2->mv[i].y - c3->mv[i].y;
1197  ff_vvc_clip_mv(&mi->mv[i][0]);
1198  mi->mv[i][1] = c1->mv[i];
1199  mi->mv[i][2] = c2->mv[i];
1200  }
1201  }
1202  if (mi->pred_flag) {
1203  mi->bcw_idx = mi->pred_flag == PF_BI ? c1->bcw_idx : 0;
1204  mi->motion_model_idc = MOTION_6_PARAMS_AFFINE;
1205  return 1;
1206  }
1207  }
1208  return 0;
1209 }
1210 
1211 static int affine_merge_const5(const MvField *c0, const MvField *c1, MotionInfo *mi)
1212 {
1213  if (c0 && c1) {
1214  mi->pred_flag = 0;
1215  for (int i = 0; i < 2; i++) {
1216  PredFlag mask = i + 1;
1217  if (compare_pf_ref_idx(c0, c1, NULL, i)) {
1218  mi->pred_flag |= mask;
1219  mi->ref_idx[i] = c0->ref_idx[i];
1220  mi->mv[i][0] = c0->mv[i];
1221  mi->mv[i][1] = c1->mv[i];
1222  }
1223  }
1224  if (mi->pred_flag) {
1225  if (mi->pred_flag == PF_BI)
1226  mi->bcw_idx = c0->bcw_idx;
1227  mi->motion_model_idc = MOTION_4_PARAMS_AFFINE;
1228  return 1;
1229  }
1230  }
1231  return 0;
1232 }
1233 
1234 static int affine_merge_const6(const MvField* c0, const MvField* c2, const int cb_width, const int cb_height, MotionInfo *mi)
1235 {
1236  if (c0 && c2) {
1237  const int shift = 7 + av_log2(cb_width) - av_log2(cb_height);
1238  mi->pred_flag = 0;
1239  for (int i = 0; i < 2; i++) {
1240  PredFlag mask = i + 1;
1241  if (compare_pf_ref_idx(c0, c2, NULL, i)) {
1242  mi->pred_flag |= mask;
1243  mi->ref_idx[i] = c0->ref_idx[i];
1244  mi->mv[i][0] = c0->mv[i];
1245  mi->mv[i][1].x = (c0->mv[i].x * (1 << 7)) + ((c2->mv[i].y - c0->mv[i].y) * (1 << shift));
1246  mi->mv[i][1].y = (c0->mv[i].y * (1 << 7)) - ((c2->mv[i].x - c0->mv[i].x) * (1 << shift));
1247  ff_vvc_round_mv(&mi->mv[i][1], 0, 7);
1248  ff_vvc_clip_mv(&mi->mv[i][1]);
1249  }
1250  }
1251  if (mi->pred_flag) {
1252  if (mi->pred_flag == PF_BI)
1253  mi->bcw_idx = c0->bcw_idx;
1254  mi->motion_model_idc = MOTION_4_PARAMS_AFFINE;
1255  return 1;
1256  }
1257  }
1258  return 0;
1259 }
1260 
1262 {
1263  const CodingUnit *cu = lc->cu;
1264 
1265  memset(mi, 0, sizeof(*mi));
1266  mi->pred_flag = PF_L0 + (IS_B(lc->sc->sh.r) << 1);
1267  mi->motion_model_idc = MOTION_4_PARAMS_AFFINE;
1268  mi->num_sb_x = cu->cb_width >> MIN_PU_LOG2;
1269  mi->num_sb_y = cu->cb_height >> MIN_PU_LOG2;
1270 }
1271 
1272 //8.5.5.6 Derivation process for constructed affine control point motion vector merging candidates
1274  NeighbourContext *nctx, const int merge_subblock_idx, int num_cands)
1275 {
1276  const VVCFrameContext *fc = lc->fc;
1277  const CodingUnit *cu = lc->cu;
1278  const NeighbourIdx tl[] = { B2, B3, A2 };
1279  const NeighbourIdx tr[] = { B1, B0};
1280  const NeighbourIdx bl[] = { A1, A0};
1281  const MvField *c0, *c1, *c2;
1282 
1283  c0 = DERIVE_CORNER_MV(tl);
1284  c1 = DERIVE_CORNER_MV(tr);
1285  c2 = DERIVE_CORNER_MV(bl);
1286 
1287  if (fc->ps.sps->r->sps_6param_affine_enabled_flag) {
1288  MvField corner3, *c3 = NULL;
1289  //Const1
1290  if (affine_merge_const1(c0, c1, c2, mi)) {
1291  if (merge_subblock_idx == num_cands)
1292  return 1;
1293  num_cands++;
1294  }
1295 
1296  memset(&corner3, 0, sizeof(corner3));
1297  if (fc->ps.ph.r->ph_temporal_mvp_enabled_flag){
1298  const int available_l0 = temporal_luma_motion_vector(lc, 0, corner3.mv + 0, 0, 0, 0);
1299  const int available_l1 = (lc->sc->sh.r->sh_slice_type == VVC_SLICE_TYPE_B) ?
1300  temporal_luma_motion_vector(lc, 0, corner3.mv + 1, 1, 0, 0) : 0;
1301 
1302  corner3.pred_flag = available_l0 + (available_l1 << 1);
1303  if (corner3.pred_flag)
1304  c3 = &corner3;
1305  }
1306 
1307  //Const2
1308  if (affine_merge_const2(c0, c1, c3, mi)) {
1309  if (merge_subblock_idx == num_cands)
1310  return 1;
1311  num_cands++;
1312  }
1313 
1314  //Const3
1315  if (affine_merge_const3(c0, c2, c3, mi)) {
1316  if (merge_subblock_idx == num_cands)
1317  return 1;
1318  num_cands++;
1319  }
1320 
1321  //Const4
1322  if (affine_merge_const4(c1, c2, c3, mi)) {
1323  if (merge_subblock_idx == num_cands)
1324  return 1;
1325  num_cands++;
1326  }
1327  }
1328 
1329  //Const5
1330  if (affine_merge_const5(c0, c1, mi)) {
1331  if (merge_subblock_idx == num_cands)
1332  return 1;
1333  num_cands++;
1334  }
1335 
1336  if (affine_merge_const6(c0, c2, cu->cb_width, cu->cb_height, mi)) {
1337  if (merge_subblock_idx == num_cands)
1338  return 1;
1339  }
1340  return 0;
1341 }
1342 
1343 //8.5.5.2 Derivation process for motion vectors and reference indices in subblock merge mode
1344 //return 1 if candidate is SbCol
1345 static int sb_mv_merge_mode(const VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
1346 {
1347  const VVCSPS *sps = lc->fc->ps.sps;
1348  const CodingUnit *cu = lc->cu;
1349  MotionInfo *mi = &pu->mi;
1350  int num_cands = 0;
1351  NeighbourContext nctx;
1352 
1353  init_neighbour_context(&nctx, lc);
1354 
1355  //SbCol
1356  if (sb_temporal_merge_candidate(lc, &nctx, pu)) {
1357  if (merge_subblock_idx == num_cands)
1358  return 1;
1359  num_cands++;
1360  }
1361 
1362  pu->inter_affine_flag = 1;
1363  mi->num_sb_x = cu->cb_width >> MIN_PU_LOG2;
1364  mi->num_sb_y = cu->cb_height >> MIN_PU_LOG2;
1365 
1366  if (sps->r->sps_affine_enabled_flag) {
1367  const NeighbourIdx ak[] = { A0, A1 };
1368  const NeighbourIdx bk[] = { B0, B1, B2 };
1369  //A
1370  if (AFFINE_MERGE_FROM_NBS(ak)) {
1371  if (merge_subblock_idx == num_cands)
1372  return 0;
1373  num_cands++;
1374  }
1375 
1376  //B
1377  if (AFFINE_MERGE_FROM_NBS(bk)) {
1378  if (merge_subblock_idx == num_cands)
1379  return 0;
1380  num_cands++;
1381  }
1382 
1383  //Const1 to Const6
1384  if (affine_merge_const_candidates(lc, mi, &nctx, merge_subblock_idx, num_cands))
1385  return 0;
1386  }
1387  //Zero
1389  return 0;
1390 }
1391 
1392 void ff_vvc_sb_mv_merge_mode(VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu)
1393 {
1394  const CodingUnit *cu = lc->cu;
1395  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1396  if (!sb_mv_merge_mode(lc, merge_subblock_idx, pu)) {
1397  ff_vvc_store_sb_mvs(lc, pu);
1398  }
1399 }
1400 
1401 static int mvp_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand,
1402  const int lx, const int8_t *ref_idx, Mv *mv)
1403 {
1404  const VVCFrameContext *fc = lc->fc;
1405  const RefPicList *rpl = lc->sc->rpl;
1406  const int min_pu_width = fc->ps.pps->min_pu_width;
1407  const MvField* tab_mvf = fc->tab.mvf;
1408  const MvField *mvf = &TAB_MVF(x_cand, y_cand);
1409  const PredFlag maskx = lx + 1;
1410  const int poc = rpl[lx].list[ref_idx[lx]];
1411  int available = 0;
1412 
1413  if ((mvf->pred_flag & maskx) && rpl[lx].list[mvf->ref_idx[lx]] == poc) {
1414  available = 1;
1415  *mv = mvf->mv[lx];
1416  } else {
1417  const int ly = !lx;
1418  const PredFlag masky = ly + 1;
1419  if ((mvf->pred_flag & masky) && rpl[ly].list[mvf->ref_idx[ly]] == poc) {
1420  available = 1;
1421  *mv = mvf->mv[ly];
1422  }
1423  }
1424 
1425  return available;
1426 }
1427 
1429  const int x_cand, const int y_cand, const int lx, const int8_t *ref_idx,
1430  Mv *cps, const int num_cp)
1431 {
1432  const VVCFrameContext *fc = lc->fc;
1433  int x_nb, y_nb, nbw, nbh, motion_model_idc, available = 0;
1434 
1435  motion_model_idc = affine_neighbour_cb(fc, x_cand, y_cand, &x_nb, &y_nb, &nbw, &nbh);
1436  if (motion_model_idc) {
1437  const int min_pu_width = fc->ps.pps->min_pu_width;
1438  const MvField* tab_mvf = fc->tab.mvf;
1439  const MvField *mvf = &TAB_MVF(x_nb, y_nb);
1440  RefPicList* rpl = lc->sc->rpl;
1441  const PredFlag maskx = lx + 1;
1442  const int poc = rpl[lx].list[ref_idx[lx]];
1443 
1444  if ((mvf->pred_flag & maskx) && rpl[lx].list[mvf->ref_idx[lx]] == poc) {
1445  available = 1;
1446  affine_cps_from_nb(lc, x_nb, y_nb, nbw, nbh, lx, cps, num_cp);
1447  } else {
1448  const int ly = !lx;
1449  const PredFlag masky = ly + 1;
1450  if ((mvf->pred_flag & masky) && rpl[ly].list[mvf->ref_idx[ly]] == poc) {
1451  available = 1;
1452  affine_cps_from_nb(lc, x_nb, y_nb, nbw, nbh, ly, cps, num_cp);
1453  }
1454  }
1455 
1456  }
1457  return available;
1458 }
1459 
1461  const NeighbourIdx *nbs, const int num_nbs, const int lx, const int8_t *ref_idx, const int amvr_shift,
1462  Mv *cps, const int num_cps)
1463 {
1464  const VVCLocalContext *lc = ctx->lc;
1465  int available = 0;
1466 
1467  for (int i = 0; i < num_nbs; i++) {
1468  Neighbour *n = &ctx->neighbours[nbs[i]];
1469  if (check_available(n, lc, 0)) {
1470  if (num_cps > 1)
1471  available = affine_mvp_candidate(lc, n->x, n->y, lx, ref_idx, cps, num_cps);
1472  else
1473  available = mvp_candidate(lc, n->x, n->y, lx, ref_idx, cps);
1474  if (available) {
1475  for (int c = 0; c < num_cps; c++)
1476  ff_vvc_round_mv(cps + c, amvr_shift, amvr_shift);
1477  return 1;
1478  }
1479  }
1480  }
1481  return 0;
1482 }
1483 
1484 //get mvp from neighbours
1485 #define AFFINE_MVP_FROM_NBS(nbs) \
1486  mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, cps, num_cp) \
1487 
1488 #define MVP_FROM_NBS(nbs) \
1489  mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, mv, 1) \
1490 
1492  const int mvp_lx_flag, const int lx, const int8_t* ref_idx, const int amvr_shift,
1493  Mv* mv, int *nb_merge_cand)
1494 {
1495  const NeighbourIdx ak[] = { A0, A1 };
1496  const NeighbourIdx bk[] = { B0, B1, B2 };
1497  NeighbourContext nctx;
1498  int available_a, num_cands = 0;
1499  LOCAL_ALIGNED_8(Mv, mv_a, [1]);
1500 
1501  init_neighbour_context(&nctx, lc);
1502 
1503  available_a = MVP_FROM_NBS(ak);
1504  if (available_a) {
1505  if (mvp_lx_flag == num_cands)
1506  return 1;
1507  num_cands++;
1508  *mv_a = *mv;
1509  }
1510  if (MVP_FROM_NBS(bk)) {
1511  if (!available_a || !IS_SAME_MV(mv_a, mv)) {
1512  if (mvp_lx_flag == num_cands)
1513  return 1;
1514  num_cands++;
1515  }
1516  }
1517  *nb_merge_cand = num_cands;
1518  return 0;
1519 }
1520 
1522  const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift,
1523  Mv* mv, int *num_cands)
1524 {
1525  if (temporal_luma_motion_vector(lc, ref_idx[lx], mv, lx, 1, 0)) {
1526  if (mvp_lx_flag == *num_cands) {
1527  ff_vvc_round_mv(mv, amvr_shift, amvr_shift);
1528  return 1;
1529  }
1530  (*num_cands)++;
1531  }
1532  return 0;
1533 
1534 }
1535 
1537  const int mvp_lx_flag, const int lx, const int8_t ref_idx, const int amvr_shift,
1538  Mv *mv, int num_cands)
1539 {
1540  const EntryPoint* ep = lc->ep;
1541  const RefPicList* rpl = lc->sc->rpl;
1542  const int poc = rpl[lx].list[ref_idx];
1543 
1544  if (ep->num_hmvp == 0)
1545  return 0;
1546  for (int i = 1; i <= FFMIN(4, ep->num_hmvp); i++) {
1547  const MvField* h = &ep->hmvp[i - 1];
1548  for (int j = 0; j < 2; j++) {
1549  const int ly = (j ? !lx : lx);
1550  PredFlag mask = PF_L0 + ly;
1551  if ((h->pred_flag & mask) && poc == rpl[ly].list[h->ref_idx[ly]]) {
1552  if (mvp_lx_flag == num_cands) {
1553  *mv = h->mv[ly];
1554  ff_vvc_round_mv(mv, amvr_shift, amvr_shift);
1555  return 1;
1556  }
1557  num_cands++;
1558  }
1559  }
1560  }
1561  return 0;
1562 }
1563 
1564 //8.5.2.8 Derivation process for luma motion vector prediction
1565 static void mvp(const VVCLocalContext *lc, const int mvp_lx_flag, const int lx,
1566  const int8_t *ref_idx, const int amvr_shift, Mv *mv)
1567 {
1568  int num_cands;
1569 
1570  if (mvp_spatial_candidates(lc, mvp_lx_flag, lx, ref_idx, amvr_shift, mv, &num_cands))
1571  return;
1572 
1573  if (mvp_temporal_candidates(lc, mvp_lx_flag, lx, ref_idx, amvr_shift, mv, &num_cands))
1574  return;
1575 
1576  if (mvp_history_candidates(lc, mvp_lx_flag, lx, ref_idx[lx], amvr_shift, mv, num_cands))
1577  return;
1578 
1579  memset(mv, 0, sizeof(*mv));
1580 }
1581 
1582 void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
1583 {
1584  const CodingUnit *cu = lc->cu;
1585  mi->num_sb_x = 1;
1586  mi->num_sb_y = 1;
1587 
1588  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1589  if (mi->pred_flag != PF_L1)
1590  mvp(lc, mvp_lx_flag[L0], L0, mi->ref_idx, amvr_shift, &mi->mv[L0][0]);
1591  if (mi->pred_flag != PF_L0)
1592  mvp(lc, mvp_lx_flag[L1], L1, mi->ref_idx, amvr_shift, &mi->mv[L1][0]);
1593 }
1594 
1595 static int ibc_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *const cand_list, int *nb_merge_cand)
1596 {
1597  const CodingUnit *cu = lc->cu;
1598  const VVCFrameContext *fc = lc->fc;
1599  const int min_pu_width = fc->ps.pps->min_pu_width;
1600  const MvField *tab_mvf = fc->tab.mvf;
1601  const int is_gt4by4 = (cu->cb_width * cu->cb_height) > 16;
1602  int num_cands = 0;
1603 
1604  NeighbourContext nctx;
1605  Neighbour *a1 = &nctx.neighbours[A1];
1606  Neighbour *b1 = &nctx.neighbours[B1];
1607 
1608  if (!is_gt4by4) {
1609  *nb_merge_cand = 0;
1610  return 0;
1611  }
1612 
1613  init_neighbour_context(&nctx, lc);
1614 
1615  if (check_available(a1, lc, 1)) {
1616  cand_list[num_cands++] = TAB_MVF(a1->x, a1->y).mv[L0];
1617  if (num_cands > merge_idx)
1618  return 1;
1619  }
1620  if (check_available(b1, lc, 1)) {
1621  const MvField *mvf = &TAB_MVF(b1->x, b1->y);
1622  if (!num_cands || !IS_SAME_MV(&cand_list[0], mvf->mv)) {
1623  cand_list[num_cands++] = mvf->mv[L0];
1624  if (num_cands > merge_idx)
1625  return 1;
1626  }
1627  }
1628 
1629  *nb_merge_cand = num_cands;
1630  return 0;
1631 }
1632 
1634  const int merge_idx, Mv *cand_list, int *nb_merge_cand)
1635 {
1636  const CodingUnit *cu = lc->cu;
1637  const EntryPoint *ep = lc->ep;
1638  const int is_gt4by4 = (cu->cb_width * cu->cb_height) > 16;
1639  int num_cands = *nb_merge_cand;
1640 
1641  for (int i = 1; i <= ep->num_hmvp_ibc; i++) {
1642  int same_motion = 0;
1643  const MvField *mvf = &ep->hmvp_ibc[ep->num_hmvp_ibc - i];
1644  for (int j = 0; j < *nb_merge_cand; j++) {
1645  same_motion = is_gt4by4 && i == 1 && IS_SAME_MV(&mvf->mv[L0], &cand_list[j]);
1646  if (same_motion)
1647  break;
1648  }
1649  if (!same_motion) {
1650  cand_list[num_cands++] = mvf->mv[L0];
1651  if (num_cands > merge_idx)
1652  return 1;
1653  }
1654  }
1655 
1656  *nb_merge_cand = num_cands;
1657  return 0;
1658 }
1659 
1660 #define MV_BITS 18
1661 #define IBC_SHIFT(v) ((v) >= (1 << (MV_BITS - 1)) ? ((v) - (1 << MV_BITS)) : (v))
1662 
1663 static inline void ibc_add_mvp(Mv *mv, Mv *mvp, const int amvr_shift)
1664 {
1665  ff_vvc_round_mv(mv, amvr_shift, 0);
1666  ff_vvc_round_mv(mvp, amvr_shift, amvr_shift);
1667  mv->x = IBC_SHIFT(mv->x + mvp->x);
1668  mv->y = IBC_SHIFT(mv->y + mvp->y);
1669 }
1670 
1671 static void ibc_merge_candidates(VVCLocalContext *lc, const int merge_idx, Mv *mv)
1672 {
1673  const CodingUnit *cu = lc->cu;
1674  LOCAL_ALIGNED_8(Mv, cand_list, [MRG_MAX_NUM_CANDS]);
1675  int nb_cands;
1676 
1677  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1678  if (ibc_spatial_candidates(lc, merge_idx, cand_list, &nb_cands) ||
1679  ibc_history_candidates(lc, merge_idx, cand_list, &nb_cands)) {
1680  *mv = cand_list[merge_idx];
1681  return;
1682  }
1683 
1684  //zero mv
1685  memset(mv, 0, sizeof(*mv));
1686 }
1687 
1688 void ff_vvc_mvp_ibc(VVCLocalContext *lc, const int mvp_l0_flag, const int amvr_shift, Mv *mv)
1689 {
1690  LOCAL_ALIGNED_8(Mv, mvp, [1]);
1691 
1692  ibc_merge_candidates(lc, mvp_l0_flag, mvp);
1693  ibc_add_mvp(mv, mvp, amvr_shift);
1694 }
1695 
1696 void ff_vvc_luma_mv_merge_ibc(VVCLocalContext *lc, const int merge_idx, Mv *mv)
1697 {
1698  ibc_merge_candidates(lc, merge_idx, mv);
1699 }
1700 
1702  const NeighbourIdx *neighbour, const int num_neighbour,
1703  const int lx, const int8_t ref_idx, const int amvr_shift, Mv *cp)
1704 {
1705  const VVCLocalContext *lc = ctx->lc;
1706  const VVCFrameContext *fc = lc->fc;
1707  const MvField *tab_mvf = fc->tab.mvf;
1708  const int min_pu_width = fc->ps.pps->min_pu_width;
1709  const RefPicList* rpl = lc->sc->rpl;
1710  int available = 0;
1711 
1712  for (int i = 0; i < num_neighbour; i++) {
1713  Neighbour *n = &ctx->neighbours[neighbour[i]];
1714  if (check_available(n, ctx->lc, 0)) {
1715  const PredFlag maskx = lx + 1;
1716  const MvField* mvf = &TAB_MVF(n->x, n->y);
1717  const int poc = rpl[lx].list[ref_idx];
1718  if ((mvf->pred_flag & maskx) && rpl[lx].list[mvf->ref_idx[lx]] == poc) {
1719  available = 1;
1720  *cp = mvf->mv[lx];
1721  } else {
1722  const int ly = !lx;
1723  const PredFlag masky = ly + 1;
1724  if ((mvf->pred_flag & masky) && rpl[ly].list[mvf->ref_idx[ly]] == poc) {
1725  available = 1;
1726  *cp = mvf->mv[ly];
1727  }
1728  }
1729  if (available) {
1730  ff_vvc_round_mv(cp, amvr_shift, amvr_shift);
1731  return 1;
1732  }
1733  }
1734  }
1735  return 0;
1736 }
1737 
1738 #define AFFINE_MVP_CONSTRUCTED_CP(cands, cp) \
1739  affine_mvp_constructed_cp(nctx, cands, FF_ARRAY_ELEMS(cands), lx, ref_idx, \
1740  amvr_shift, cp)
1741 
1742 //8.5.5.8 Derivation process for constructed affine control point motion vector prediction candidates
1744  const int lx, const int8_t ref_idx, const int amvr_shift,
1745  Mv *cps, int *available)
1746 {
1747  const NeighbourIdx tl[] = { B2, B3, A2 };
1748  const NeighbourIdx tr[] = { B1, B0 };
1749  const NeighbourIdx bl[] = { A1, A0 };
1750 
1751  available[0] = AFFINE_MVP_CONSTRUCTED_CP(tl, cps + 0);
1752  available[1] = AFFINE_MVP_CONSTRUCTED_CP(tr, cps + 1);
1753  available[2] = AFFINE_MVP_CONSTRUCTED_CP(bl, cps + 2);
1754  return available[0] && available[1];
1755 }
1756 
1757 //8.5.5.7 item 7
1758 static void affine_mvp_const2(const int idx, Mv *cps, const int num_cp)
1759 {
1760  const Mv mv = cps[idx];
1761  for (int j = 0; j < num_cp; j++)
1762  cps[j] = mv;
1763 }
1764 
1765 //8.5.5.7 Derivation process for luma affine control point motion vector predictors
1766 static void affine_mvp(const VVCLocalContext *lc,
1767  const int mvp_lx_flag, const int lx, const int8_t *ref_idx, const int amvr_shift,
1768  MotionModelIdc motion_model_idc, Mv *cps)
1769 {
1770  const NeighbourIdx ak[] = { A0, A1 };
1771  const NeighbourIdx bk[] = { B0, B1, B2 };
1772  const int num_cp = motion_model_idc + 1;
1773  NeighbourContext nctx;
1775  int num_cands = 0;
1776 
1777  init_neighbour_context(&nctx, lc);
1778  //Ak
1779  if (AFFINE_MVP_FROM_NBS(ak)) {
1780  if (mvp_lx_flag == num_cands)
1781  return;
1782  num_cands++;
1783  }
1784  //Bk
1785  if (AFFINE_MVP_FROM_NBS(bk)) {
1786  if (mvp_lx_flag == num_cands)
1787  return;
1788  num_cands++;
1789  }
1790 
1791  //Const1
1792  if (affine_mvp_const1(&nctx, lx, ref_idx[lx], amvr_shift, cps, available)) {
1793  if (available[2] || motion_model_idc == MOTION_4_PARAMS_AFFINE) {
1794  if (mvp_lx_flag == num_cands)
1795  return;
1796  num_cands++;
1797  }
1798  }
1799 
1800  //Const2
1801  for (int i = 2; i >= 0; i--) {
1802  if (available[i]) {
1803  if (mvp_lx_flag == num_cands) {
1804  affine_mvp_const2(i, cps, num_cp);
1805  return;
1806  }
1807  num_cands++;
1808  }
1809  }
1810  if (temporal_luma_motion_vector(lc, ref_idx[lx], cps, lx, 1, 0)) {
1811  if (mvp_lx_flag == num_cands) {
1812  ff_vvc_round_mv(cps, amvr_shift, amvr_shift);
1813  for (int i = 1; i < num_cp; i++)
1814  cps[i] = cps[0];
1815  return;
1816  }
1817  num_cands++;
1818  }
1819 
1820  //Zero Mv
1821  memset(cps, 0, num_cp * sizeof(Mv));
1822 }
1823 
1824 void ff_vvc_affine_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
1825 {
1826  const CodingUnit *cu = lc->cu;
1827 
1828  mi->num_sb_x = cu->cb_width >> MIN_PU_LOG2;
1829  mi->num_sb_y = cu->cb_height >> MIN_PU_LOG2;
1830 
1831  ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height);
1832  if (mi->pred_flag != PF_L1)
1833  affine_mvp(lc, mvp_lx_flag[L0], L0, mi->ref_idx, amvr_shift, mi->motion_model_idc, &mi->mv[L0][0]);
1834  if (mi->pred_flag != PF_L0)
1835  affine_mvp(lc, mvp_lx_flag[L1], L1, mi->ref_idx, amvr_shift, mi->motion_model_idc, &mi->mv[L1][0]);
1836 }
1837 
1838 //8.5.2.14 Rounding process for motion vectors
1839 void ff_vvc_round_mv(Mv *mv, const int lshift, const int rshift)
1840 {
1841  if (rshift) {
1842  const int offset = 1 << (rshift - 1);
1843  mv->x = ((mv->x + offset - (mv->x >= 0)) >> rshift) * (1 << lshift);
1844  mv->y = ((mv->y + offset - (mv->y >= 0)) >> rshift) * (1 << lshift);
1845  } else {
1846  mv->x = mv->x * (1 << lshift);
1847  mv->y = mv->y * (1 << lshift);
1848  }
1849 }
1850 
1852 {
1853  mv->x = av_clip(mv->x, -(1 << 17), (1 << 17) - 1);
1854  mv->y = av_clip(mv->y, -(1 << 17), (1 << 17) - 1);
1855 }
1856 
1857 //8.5.2.1 Derivation process for motion vector components and reference indices
1858 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)
1859 {
1860  const uint8_t plevel = fc->ps.sps->log2_parallel_merge_level;
1861 
1862  return x0_br >> plevel > x0 >> plevel &&
1863  y0_br >> plevel > y0 >> plevel;
1864 }
1865 
1866 static void update_hmvp(MvField *hmvp, int *num_hmvp, const MvField *mvf,
1867  int (*compare)(const MvField *n, const MvField *o))
1868 {
1869  int i;
1870  for (i = 0; i < *num_hmvp; i++) {
1871  if (compare(mvf, hmvp + i)) {
1872  (*num_hmvp)--;
1873  break;
1874  }
1875  }
1876  if (i == MAX_NUM_HMVP_CANDS) {
1877  (*num_hmvp)--;
1878  i = 0;
1879  }
1880 
1881  memmove(hmvp + i, hmvp + i + 1, (*num_hmvp - i) * sizeof(MvField));
1882  hmvp[(*num_hmvp)++] = *mvf;
1883 }
1884 
1885 static int compare_l0_mv(const MvField *n, const MvField *o)
1886 {
1887  return IS_SAME_MV(&n->mv[L0], &o->mv[L0]);
1888 }
1889 
1890 //8.6.2.4 Derivation process for IBC history-based block vector candidates
1891 //8.5.2.16 Updating process for the history-based motion vector predictor candidate list
1893 {
1894  const VVCFrameContext *fc = lc->fc;
1895  const CodingUnit *cu = lc->cu;
1896  const int min_pu_width = fc->ps.pps->min_pu_width;
1897  const MvField *tab_mvf = fc->tab.mvf;
1898  EntryPoint *ep = lc->ep;
1899 
1900  if (cu->pred_mode == MODE_IBC) {
1901  if (cu->cb_width * cu->cb_height <= 16)
1902  return;
1903  update_hmvp(ep->hmvp_ibc, &ep->num_hmvp_ibc, &TAB_MVF(cu->x0, cu->y0), compare_l0_mv);
1904  } else {
1905  if (!is_greater_mer(fc, cu->x0, cu->y0, cu->x0 + cu->cb_width, cu->y0 + cu->cb_height))
1906  return;
1907  update_hmvp(ep->hmvp, &ep->num_hmvp, &TAB_MVF(cu->x0, cu->y0), compare_mv_ref_idx);
1908  }
1909 }
1910 
1911 MvField* ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0)
1912 {
1913  const int min_pu_width = fc->ps.pps->min_pu_width;
1914  MvField* tab_mvf = fc->tab.mvf;
1915 
1916  return &TAB_MVF(x0, y0);
1917 }
mv_merge_candidate
static const MvField * mv_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand)
Definition: vvc_mvs.c:613
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:1345
affine_mvp_const2
static void affine_mvp_const2(const int idx, Mv *cps, const int num_cp)
Definition: vvc_mvs.c:1758
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:675
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:566
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:749
check_available
static int check_available(Neighbour *n, const VVCLocalContext *lc, const int check_mer)
Definition: vvc_mvs.c:595
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:526
ff_vvc_get_mvf
MvField * ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0)
Definition: vvc_mvs.c:1911
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:1392
B3
@ B3
Definition: vvc_mvs.c:525
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:1234
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:3002
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:920
ibc_merge_candidates
static void ibc_merge_candidates(VVCLocalContext *lc, const int merge_idx, Mv *mv)
Definition: vvc_mvs.c:1671
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:945
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:1428
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:958
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:802
Neighbour::x
int x
Definition: vvc_mvs.c:531
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:992
ff_vvc_mvp
void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi)
Definition: vvc_mvs.c:1582
Neighbour
Definition: vvc_mvs.c:530
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:472
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:1766
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
AFFINE_MVP_CONSTRUCTED_CP
#define AFFINE_MVP_CONSTRUCTED_CP(cands, cp)
Definition: vvc_mvs.c:1738
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:710
Neighbour::available
int available
Definition: vvc_mvs.c:535
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:1858
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:448
NB_IDX_NONE
@ NB_IDX_NONE
Definition: vvc_mvs.c:527
A1
@ A1
Definition: vvc_mvs.c:520
B2
@ B2
Definition: vvc_mvs.c:524
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:1663
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:1460
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:543
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:955
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:1595
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:815
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:1161
ff_vvc_store_mv
void ff_vvc_store_mv(const VVCLocalContext *lc, const MotionInfo *mi)
Definition: vvc_mvs.c:499
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:1186
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:1885
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:841
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:1521
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:775
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:1029
av_clip_intp2
#define av_clip_intp2
Definition: common.h:119
B1
@ B1
Definition: vvc_mvs.c:523
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:972
B0
@ B0
Definition: vvc_mvs.c:522
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:1866
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:632
Mv::x
int16_t x
horizontal component of motion vector
Definition: hevcdec.h:296
Neighbour::checked
int checked
Definition: vvc_mvs.c:534
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:1696
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:1565
NeighbourContext::neighbours
Neighbour neighbours[NUM_NBS]
Definition: vvc_mvs.c:539
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:540
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:1401
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:1701
NeighbourIdx
NeighbourIdx
Definition: vvc_mvs.c:518
mv_merge_from_nb
static const MvField * mv_merge_from_nb(NeighbourContext *ctx, const NeighbourIdx nb)
Definition: vvc_mvs.c:623
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:1688
affine_merge_const1
static int affine_merge_const1(const MvField *c0, const MvField *c1, const MvField *c2, MotionInfo *mi)
Definition: vvc_mvs.c:1112
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:1273
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:635
sb_temporal_merge_candidate
static int sb_temporal_merge_candidate(const VVCLocalContext *lc, NeighbourContext *nctx, PredictionUnit *pu)
Definition: vvc_mvs.c:1064
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:1491
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:590
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:903
EntryPoint
Definition: vvc_ctu.h:349
ff_vvc_update_hmvp
void ff_vvc_update_hmvp(VVCLocalContext *lc, const MotionInfo *mi)
Definition: vvc_mvs.c:1892
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:2501
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:1824
ff_vvc_clip_mv
void ff_vvc_clip_mv(Mv *mv)
Definition: vvc_mvs.c:1851
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:1839
CodingUnit::pred_mode
enum PredMode pred_mode
PredMode.
Definition: hevcdec.h:286
IBC_SHIFT
#define IBC_SHIFT(v)
Definition: vvc_mvs.c:1661
affine_merge_const2
static int affine_merge_const2(const MvField *c0, const MvField *c1, const MvField *c3, MotionInfo *mi)
Definition: vvc_mvs.c:1136
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:1261
AFFINE_MVP_FROM_NBS
#define AFFINE_MVP_FROM_NBS(nbs)
Definition: vvc_mvs.c:1485
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:532
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:1001
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:1536
NeighbourContext
Definition: vvc_mvs.c:538
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:691
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:975
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:521
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:493
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:1633
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:1743
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:1211
CodingUnit::y0
int y0
Definition: vvc_ctu.h:277
MVP_FROM_NBS
#define MVP_FROM_NBS(nbs)
Definition: vvc_mvs.c:1488
A0
@ A0
Definition: vvc_mvs.c:519
PF_IBC
@ PF_IBC
Definition: vvc_ctu.h:220