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