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