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