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