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