/src/ffmpeg/libavcodec/vvc/mvs.c
Line | Count | Source |
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 | 89.6k | #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 | 42.4k | { |
33 | 42.4k | const uint8_t plevel = fc->ps.sps->log2_parallel_merge_level; |
34 | | |
35 | 42.4k | return xN >> plevel == xP >> plevel && |
36 | 871 | yN >> plevel == yP >> plevel; |
37 | 42.4k | } |
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 | 87.2k | { |
42 | 87.2k | if (!o || n->pred_flag != o->pred_flag) |
43 | 21.8k | return 0; |
44 | 157k | for (int i = 0; i < 2; i++) { |
45 | 111k | PredFlag mask = i + 1; |
46 | 111k | if (n->pred_flag & mask) { |
47 | 66.5k | const int same_ref_idx = n->ref_idx[i] == o->ref_idx[i]; |
48 | 66.5k | const int same_mv = IS_SAME_MV(n->mv + i, o->mv + i); |
49 | 66.5k | if (!same_ref_idx || !same_mv) |
50 | 20.0k | return 0; |
51 | 66.5k | } |
52 | 111k | } |
53 | 45.2k | return 1; |
54 | 65.3k | } |
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 | 2.64k | { |
59 | 2.64k | int mv[2] = {motion->x, motion->y}; |
60 | 7.92k | for (int i = 0; i < 2; i++) { |
61 | 5.28k | const int s = mv[i] >> 17; |
62 | 5.28k | const int f = av_log2((mv[i] ^ s) | 31) - 4; |
63 | 5.28k | const int mask = (-1 * (1 << f)) >> 1; |
64 | 5.28k | const int round = (1 << f) >> 2; |
65 | 5.28k | mv[i] = (mv[i] + round) & mask; |
66 | 5.28k | } |
67 | 2.64k | motion->x = mv[0]; |
68 | 2.64k | motion->y = mv[1]; |
69 | 2.64k | } |
70 | | |
71 | | void ff_vvc_mv_scale(Mv *dst, const Mv *src, int td, int tb) |
72 | 6.96k | { |
73 | 6.96k | int tx, scale_factor; |
74 | | |
75 | 6.96k | td = av_clip_int8(td); |
76 | 6.96k | tb = av_clip_int8(tb); |
77 | 6.96k | tx = (0x4000 + (abs(td) >> 1)) / td; |
78 | 6.96k | scale_factor = av_clip_intp2((tb * tx + 32) >> 6, 12); |
79 | 6.96k | dst->x = av_clip_intp2((scale_factor * src->x + 127 + |
80 | 6.96k | (scale_factor * src->x < 0)) >> 8, 17); |
81 | 6.96k | dst->y = av_clip_intp2((scale_factor * src->y + 127 + |
82 | 6.96k | (scale_factor * src->y < 0)) >> 8, 17); |
83 | 6.96k | } |
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 | 2.65k | { |
91 | 2.65k | int cur_lt = refPicList[X].refs[refIdxLx].is_lt; |
92 | 2.65k | int col_lt = refPicList_col[listCol].refs[refidxCol].is_lt; |
93 | 2.65k | int col_poc_diff, cur_poc_diff; |
94 | | |
95 | 2.65k | if (cur_lt != col_lt) { |
96 | 19 | mvLXCol->x = 0; |
97 | 19 | mvLXCol->y = 0; |
98 | 19 | return 0; |
99 | 19 | } |
100 | | |
101 | 2.64k | col_poc_diff = colPic - refPicList_col[listCol].refs[refidxCol].poc; |
102 | 2.64k | cur_poc_diff = poc - refPicList[X].refs[refIdxLx].poc; |
103 | | |
104 | 2.64k | mv_compression(mvCol); |
105 | 2.64k | if (cur_lt || col_poc_diff == cur_poc_diff) { |
106 | 806 | mvLXCol->x = av_clip_intp2(mvCol->x, 17); |
107 | 806 | mvLXCol->y = av_clip_intp2(mvCol->y, 17); |
108 | 1.83k | } else { |
109 | 1.83k | ff_vvc_mv_scale(mvLXCol, mvCol, col_poc_diff, cur_poc_diff); |
110 | 1.83k | } |
111 | 2.64k | return 1; |
112 | 2.65k | } |
113 | | |
114 | | #define CHECK_MVSET(l) \ |
115 | 2.65k | check_mvset(mvLXCol, temp_col.mv + l, \ |
116 | 2.65k | colPic, fc->ps.ph.poc, \ |
117 | 2.65k | refPicList, X, refIdxLx, \ |
118 | 2.65k | refPicList_col, L ## l, temp_col.ref_idx[l]) |
119 | | |
120 | | //derive NoBackwardPredFlag |
121 | | int ff_vvc_no_backward_pred_flag(const VVCLocalContext *lc) |
122 | 2.46k | { |
123 | 2.46k | int check_diffpicount = 0; |
124 | 2.46k | int i, j; |
125 | 2.46k | const RefPicList *rpl = lc->sc->rpl; |
126 | | |
127 | 7.38k | for (j = 0; j < 2; j++) { |
128 | 13.3k | for (i = 0; i < lc->sc->sh.r->num_ref_idx_active[j]; i++) { |
129 | 9.77k | if (rpl[j].refs[i].poc > lc->fc->ps.ph.poc) { |
130 | 1.39k | check_diffpicount++; |
131 | 1.39k | break; |
132 | 1.39k | } |
133 | 9.77k | } |
134 | 4.92k | } |
135 | 2.46k | return !check_diffpicount; |
136 | 2.46k | } |
137 | | |
138 | | //8.5.2.12 Derivation process for collocated motion vectors |
139 | | static int derive_temporal_colocated_mvs(const VVCLocalContext *lc, MvField temp_col, |
140 | | int refIdxLx, Mv *mvLXCol, int X, |
141 | | int colPic, const RefPicList *refPicList_col, int sb_flag) |
142 | 40.2k | { |
143 | 40.2k | const VVCFrameContext *fc = lc->fc; |
144 | 40.2k | const SliceContext *sc = lc->sc; |
145 | 40.2k | RefPicList* refPicList = sc->rpl; |
146 | | |
147 | 40.2k | if (temp_col.pred_flag == PF_INTRA || |
148 | 2.67k | temp_col.pred_flag == PF_IBC || |
149 | 2.66k | temp_col.pred_flag == PF_PLT) |
150 | 37.6k | return 0; |
151 | | |
152 | 2.66k | if (sb_flag){ |
153 | 100 | if (X == 0) { |
154 | 50 | if (temp_col.pred_flag & PF_L0) |
155 | 44 | return CHECK_MVSET(0); |
156 | 6 | else if (ff_vvc_no_backward_pred_flag(lc) && (temp_col.pred_flag & PF_L1)) |
157 | 2 | return CHECK_MVSET(1); |
158 | 50 | } else { |
159 | 50 | if (temp_col.pred_flag & PF_L1) |
160 | 42 | return CHECK_MVSET(1); |
161 | 8 | else if (ff_vvc_no_backward_pred_flag(lc) && (temp_col.pred_flag & PF_L0)) |
162 | 4 | return CHECK_MVSET(0); |
163 | 50 | } |
164 | 2.56k | } else { |
165 | 2.56k | if (!(temp_col.pred_flag & PF_L0)) |
166 | 5 | return CHECK_MVSET(1); |
167 | 2.56k | else if (temp_col.pred_flag == PF_L0) |
168 | 113 | return CHECK_MVSET(0); |
169 | 2.44k | else if (temp_col.pred_flag == PF_BI) { |
170 | 2.44k | if (ff_vvc_no_backward_pred_flag(lc)) { |
171 | 1.07k | if (X == 0) |
172 | 544 | return CHECK_MVSET(0); |
173 | 530 | else |
174 | 530 | return CHECK_MVSET(1); |
175 | 1.37k | } else { |
176 | 1.37k | if (!lc->sc->sh.r->sh_collocated_from_l0_flag) |
177 | 67 | return CHECK_MVSET(0); |
178 | 1.30k | else |
179 | 1.30k | return CHECK_MVSET(1); |
180 | 1.37k | } |
181 | 2.44k | } |
182 | 2.56k | } |
183 | 8 | return 0; |
184 | 2.66k | } |
185 | | |
186 | | #define TAB_MVF(x, y) \ |
187 | 145M | 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 | 0 | 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 | 40.2k | derive_temporal_colocated_mvs(lc, temp_col, \ |
198 | 40.2k | refIdxLx, mvLXCol, X, colPic, \ |
199 | 40.2k | 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 |
202 | | static int temporal_luma_motion_vector(const VVCLocalContext *lc, |
203 | | const int refIdxLx, Mv *mvLXCol, const int X, int check_center, int sb_flag) |
204 | 96.1k | { |
205 | 96.1k | const VVCFrameContext *fc = lc->fc; |
206 | 96.1k | const VVCSPS *sps = fc->ps.sps; |
207 | 96.1k | const VVCPPS *pps = fc->ps.pps; |
208 | 96.1k | const CodingUnit *cu = lc->cu; |
209 | 96.1k | const int subpic_idx = lc->sc->sh.r->curr_subpic_idx; |
210 | 96.1k | int x, y, x_end, y_end, colPic, availableFlagLXCol = 0; |
211 | 96.1k | int min_pu_width = fc->ps.pps->min_pu_width; |
212 | 96.1k | VVCFrame *ref = fc->ref->collocated_ref; |
213 | 96.1k | MvField *tab_mvf; |
214 | 96.1k | MvField temp_col; |
215 | | |
216 | 96.1k | if (!ref) { |
217 | 48.5k | memset(mvLXCol, 0, sizeof(*mvLXCol)); |
218 | 48.5k | return 0; |
219 | 48.5k | } |
220 | | |
221 | 47.6k | if (!fc->ps.ph.r->ph_temporal_mvp_enabled_flag || (cu->cb_width * cu->cb_height <= 32)) |
222 | 4.82k | return 0; |
223 | | |
224 | 42.8k | tab_mvf = ref->tab_dmvr_mvf; |
225 | 42.8k | colPic = ref->poc; |
226 | | |
227 | | //bottom right collocated motion vector |
228 | 42.8k | x = cu->x0 + cu->cb_width; |
229 | 42.8k | y = cu->y0 + cu->cb_height; |
230 | | |
231 | 42.8k | x_end = pps->subpic_x[subpic_idx] + pps->subpic_width[subpic_idx]; |
232 | 42.8k | y_end = pps->subpic_y[subpic_idx] + pps->subpic_height[subpic_idx]; |
233 | | |
234 | 42.8k | if (tab_mvf && |
235 | 42.8k | (cu->y0 >> sps->ctb_log2_size_y) == (y >> sps->ctb_log2_size_y) && |
236 | 42.8k | x < x_end && y < y_end) { |
237 | 0 | x &= ~7; |
238 | 0 | y &= ~7; |
239 | 0 | temp_col = TAB_MVF(x, y); |
240 | 0 | availableFlagLXCol = DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag); |
241 | 0 | } |
242 | 42.8k | if (check_center) { |
243 | | // derive center collocated motion vector |
244 | 40.0k | if (tab_mvf && !availableFlagLXCol) { |
245 | 40.0k | x = cu->x0 + (cu->cb_width >> 1); |
246 | 40.0k | y = cu->y0 + (cu->cb_height >> 1); |
247 | 40.0k | x &= ~7; |
248 | 40.0k | y &= ~7; |
249 | 40.0k | temp_col = TAB_MVF(x, y); |
250 | 40.0k | availableFlagLXCol = DERIVE_TEMPORAL_COLOCATED_MVS(sb_flag); |
251 | 40.0k | } |
252 | 40.0k | } |
253 | 42.8k | return availableFlagLXCol; |
254 | 47.6k | } |
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 | 476k | { |
258 | 476k | const VVCFrameContext *fc = lc->fc; |
259 | 476k | MvField *tab_mvf = fc->tab.mvf; |
260 | 476k | const int min_pu_width = fc->ps.pps->min_pu_width; |
261 | 476k | const int min_pu_size = 1 << MIN_PU_LOG2; |
262 | 1.13M | for (int dy = 0; dy < h; dy += min_pu_size) { |
263 | 2.42M | for (int dx = 0; dx < w; dx += min_pu_size) { |
264 | 1.76M | const int x = x0 + dx; |
265 | 1.76M | const int y = y0 + dy; |
266 | 1.76M | TAB_MVF(x, y) = *mvf; |
267 | 1.76M | } |
268 | 656k | } |
269 | 476k | } |
270 | | |
271 | | void ff_vvc_set_intra_mvf(const VVCLocalContext *lc, const bool dmvr, const PredFlag pf, const bool ciip_flag) |
272 | 7.60M | { |
273 | 7.60M | const VVCFrameContext *fc = lc->fc; |
274 | 7.60M | const CodingUnit *cu = lc->cu; |
275 | 7.60M | MvField *tab_mvf = dmvr ? fc->ref->tab_dmvr_mvf : fc->tab.mvf; |
276 | 7.60M | const int min_pu_width = fc->ps.pps->min_pu_width; |
277 | 7.60M | const int min_pu_size = 1 << MIN_PU_LOG2; |
278 | 29.8M | for (int dy = 0; dy < cu->cb_height; dy += min_pu_size) { |
279 | 166M | for (int dx = 0; dx < cu->cb_width; dx += min_pu_size) { |
280 | 143M | const int x = cu->x0 + dx; |
281 | 143M | const int y = cu->y0 + dy; |
282 | 143M | MvField *mv = &TAB_MVF(x, y); |
283 | | |
284 | 143M | mv->pred_flag = pf; |
285 | 143M | mv->ciip_flag = ciip_flag; |
286 | 143M | } |
287 | 22.2M | } |
288 | 7.60M | } |
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 | 7.60k | { |
293 | 7.60k | const MotionInfo* mi = &pu->mi; |
294 | 7.60k | const Mv* cp_mv = &mi->mv[lx][0]; |
295 | 7.60k | if (lc->fc->ps.ph.r->ph_prof_disabled_flag || is_fallback) |
296 | 6.68k | return 0; |
297 | 916 | if (mi->motion_model_idc == MOTION_4_PARAMS_AFFINE) { |
298 | 916 | if (IS_SAME_MV(cp_mv, cp_mv + 1)) |
299 | 916 | return 0; |
300 | 916 | } |
301 | 0 | if (mi->motion_model_idc == MOTION_6_PARAMS_AFFINE) { |
302 | 0 | if (IS_SAME_MV(cp_mv, cp_mv + 1) && IS_SAME_MV(cp_mv, cp_mv + 2)) |
303 | 0 | return 0; |
304 | 0 | } |
305 | 0 | if (lc->sc->rpl[lx].refs[mi->ref_idx[lx]].is_scaled) |
306 | 0 | return 0; |
307 | 0 | return 1; |
308 | 0 | } |
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; |
315 | | int mv_scale_hor; |
316 | | int mv_scale_ver; |
317 | | int is_fallback; |
318 | | |
319 | | int cb_width; |
320 | | int cb_height; |
321 | | } SubblockParams; |
322 | | |
323 | | static int is_fallback_mode(const SubblockParams *sp, const PredFlag pred_flag) |
324 | 7.60k | { |
325 | 7.60k | const int a = 4 * (2048 + sp->d_hor_x); |
326 | 7.60k | const int b = 4 * sp->d_hor_y; |
327 | 7.60k | const int c = 4 * (2048 + sp->d_ver_y); |
328 | 7.60k | const int d = 4 * sp->d_ver_x; |
329 | 7.60k | if (pred_flag == PF_BI) { |
330 | 7.11k | const int max_w4 = FFMAX(0, FFMAX(a, FFMAX(b, a + b))); |
331 | 7.11k | const int min_w4 = FFMIN(0, FFMIN(a, FFMIN(b, a + b))); |
332 | 7.11k | const int max_h4 = FFMAX(0, FFMAX(c, FFMAX(d, c + d))); |
333 | 7.11k | const int min_h4 = FFMIN(0, FFMIN(c, FFMIN(d, c + d))); |
334 | 7.11k | const int bx_wx4 = ((max_w4 - min_w4) >> 11) + 9; |
335 | 7.11k | const int bx_hx4 = ((max_h4 - min_h4) >> 11) + 9; |
336 | 7.11k | return bx_wx4 * bx_hx4 > 225; |
337 | 7.11k | } else { |
338 | 485 | const int bx_wxh = (FFABS(a) >> 11) + 9; |
339 | 485 | const int bx_hxh = (FFABS(d) >> 11) + 9; |
340 | 485 | const int bx_wxv = (FFABS(b) >> 11) + 9; |
341 | 485 | const int bx_hxv = (FFABS(c) >> 11) + 9; |
342 | 485 | if (bx_wxh * bx_hxh <= 165 && bx_wxv * bx_hxv <= 165) |
343 | 485 | return 0; |
344 | 485 | } |
345 | 0 | return 1; |
346 | 7.60k | } |
347 | | |
348 | | static void init_subblock_params(SubblockParams *sp, const MotionInfo* mi, |
349 | | const int cb_width, const int cb_height, const int lx) |
350 | 7.60k | { |
351 | 7.60k | const int log2_cbw = av_log2(cb_width); |
352 | 7.60k | const int log2_cbh = av_log2(cb_height); |
353 | 7.60k | const Mv* cp_mv = mi->mv[lx]; |
354 | 7.60k | const int num_cp_mv = mi->motion_model_idc + 1; |
355 | 7.60k | sp->d_hor_x = (cp_mv[1].x - cp_mv[0].x) * (1 << (MAX_CU_DEPTH - log2_cbw)); |
356 | 7.60k | sp->d_ver_x = (cp_mv[1].y - cp_mv[0].y) * (1 << (MAX_CU_DEPTH - log2_cbw)); |
357 | 7.60k | if (num_cp_mv == 3) { |
358 | 0 | sp->d_hor_y = (cp_mv[2].x - cp_mv[0].x) * (1 << (MAX_CU_DEPTH - log2_cbh)); |
359 | 0 | sp->d_ver_y = (cp_mv[2].y - cp_mv[0].y) * (1 << (MAX_CU_DEPTH - log2_cbh)); |
360 | 7.60k | } else { |
361 | 7.60k | sp->d_hor_y = -sp->d_ver_x; |
362 | 7.60k | sp->d_ver_y = sp->d_hor_x; |
363 | 7.60k | } |
364 | 7.60k | sp->mv_scale_hor = (cp_mv[0].x) * (1 << MAX_CU_DEPTH); |
365 | 7.60k | sp->mv_scale_ver = (cp_mv[0].y) * (1 << MAX_CU_DEPTH); |
366 | 7.60k | sp->cb_width = cb_width; |
367 | 7.60k | sp->cb_height = cb_height; |
368 | 7.60k | sp->is_fallback = is_fallback_mode(sp, mi->pred_flag); |
369 | 7.60k | } |
370 | | |
371 | | static void derive_subblock_diff_mvs(const VVCLocalContext *lc, PredictionUnit* pu, const SubblockParams* sp, const int lx) |
372 | 7.60k | { |
373 | 7.60k | pu->cb_prof_flag[lx] = derive_cb_prof_flag_lx(lc, pu, lx, sp->is_fallback); |
374 | 7.60k | if (pu->cb_prof_flag[lx]) { |
375 | 0 | const int dmv_limit = 1 << 5; |
376 | 0 | const int pos_offset_x = 6 * (sp->d_hor_x + sp->d_hor_y); |
377 | 0 | const int pos_offset_y = 6 * (sp->d_ver_x + sp->d_ver_y); |
378 | 0 | for (int x = 0; x < AFFINE_MIN_BLOCK_SIZE; x++) { |
379 | 0 | for (int y = 0; y < AFFINE_MIN_BLOCK_SIZE; y++) { |
380 | 0 | LOCAL_ALIGNED_8(Mv, diff, [1]); |
381 | 0 | diff->x = x * (sp->d_hor_x * (1 << 2)) + y * (sp->d_hor_y * (1 << 2)) - pos_offset_x; |
382 | 0 | diff->y = x * (sp->d_ver_x * (1 << 2)) + y * (sp->d_ver_y * (1 << 2)) - pos_offset_y; |
383 | 0 | ff_vvc_round_mv(diff, 0, 8); |
384 | 0 | pu->diff_mv_x[lx][AFFINE_MIN_BLOCK_SIZE * y + x] = av_clip(diff->x, -dmv_limit + 1, dmv_limit - 1); |
385 | 0 | pu->diff_mv_y[lx][AFFINE_MIN_BLOCK_SIZE * y + x] = av_clip(diff->y, -dmv_limit + 1, dmv_limit - 1); |
386 | 0 | } |
387 | 0 | } |
388 | 0 | } |
389 | 7.60k | } |
390 | | |
391 | | static void store_cp_mv(const VVCLocalContext *lc, const MotionInfo *mi, const int lx) |
392 | 7.60k | { |
393 | 7.60k | VVCFrameContext *fc = lc->fc; |
394 | 7.60k | const CodingUnit *cu = lc->cu; |
395 | 7.60k | const int log2_min_cb_size = fc->ps.sps->min_cb_log2_size_y; |
396 | 7.60k | const int min_cb_size = fc->ps.sps->min_cb_size_y; |
397 | 7.60k | const int min_cb_width = fc->ps.pps->min_cb_width; |
398 | 7.60k | const int num_cp_mv = mi->motion_model_idc + 1; |
399 | | |
400 | 22.2k | for (int dy = 0; dy < cu->cb_height; dy += min_cb_size) { |
401 | 43.4k | for (int dx = 0; dx < cu->cb_width; dx += min_cb_size) { |
402 | 28.7k | const int x_cb = (cu->x0 + dx) >> log2_min_cb_size; |
403 | 28.7k | const int y_cb = (cu->y0 + dy) >> log2_min_cb_size; |
404 | 28.7k | const int offset = (y_cb * min_cb_width + x_cb) * MAX_CONTROL_POINTS; |
405 | | |
406 | 28.7k | memcpy(&fc->tab.cp_mv[lx][offset], mi->mv[lx], sizeof(Mv) * num_cp_mv); |
407 | 28.7k | } |
408 | 14.6k | } |
409 | 7.60k | } |
410 | | |
411 | | //8.5.5.9 Derivation process for motion vector arrays from affine control point motion vectors |
412 | | void ff_vvc_store_sb_mvs(const VVCLocalContext *lc, PredictionUnit *pu) |
413 | 4.04k | { |
414 | 4.04k | const CodingUnit *cu = lc->cu; |
415 | 4.04k | const MotionInfo *mi = &pu->mi; |
416 | 4.04k | const int sbw = cu->cb_width / mi->num_sb_x; |
417 | 4.04k | const int sbh = cu->cb_height / mi->num_sb_y; |
418 | 4.04k | SubblockParams params[2]; |
419 | 4.04k | MvField mvf = {0}; |
420 | | |
421 | 4.04k | mvf.pred_flag = mi->pred_flag; |
422 | 4.04k | mvf.bcw_idx = mi->bcw_idx; |
423 | 4.04k | mvf.hpel_if_idx = mi->hpel_if_idx; |
424 | 12.1k | for (int i = 0; i < 2; i++) { |
425 | 8.08k | const PredFlag mask = i + 1; |
426 | 8.08k | if (mi->pred_flag & mask) { |
427 | 7.60k | store_cp_mv(lc, mi, i); |
428 | 7.60k | init_subblock_params(params + i, mi, cu->cb_width, cu->cb_height, i); |
429 | 7.60k | derive_subblock_diff_mvs(lc, pu, params + i, i); |
430 | 7.60k | mvf.ref_idx[i] = mi->ref_idx[i]; |
431 | 7.60k | } |
432 | 8.08k | } |
433 | | |
434 | 12.1k | for (int sby = 0; sby < mi->num_sb_y; sby++) { |
435 | 24.2k | for (int sbx = 0; sbx < mi->num_sb_x; sbx++) { |
436 | 16.1k | const int x0 = cu->x0 + sbx * sbw; |
437 | 16.1k | const int y0 = cu->y0 + sby * sbh; |
438 | 48.5k | for (int i = 0; i < 2; i++) { |
439 | 32.3k | const PredFlag mask = i + 1; |
440 | 32.3k | if (mi->pred_flag & mask) { |
441 | 30.4k | const SubblockParams* sp = params + i; |
442 | 30.4k | const int x_pos_cb = sp->is_fallback ? (cu->cb_width >> 1) : (2 + (sbx << MIN_CU_LOG2)); |
443 | 30.4k | const int y_pos_cb = sp->is_fallback ? (cu->cb_height >> 1) : (2 + (sby << MIN_CU_LOG2)); |
444 | 30.4k | Mv *mv = mvf.mv + i; |
445 | | |
446 | 30.4k | mv->x = sp->mv_scale_hor + sp->d_hor_x * x_pos_cb + sp->d_hor_y * y_pos_cb; |
447 | 30.4k | mv->y = sp->mv_scale_ver + sp->d_ver_x * x_pos_cb + sp->d_ver_y * y_pos_cb; |
448 | 30.4k | ff_vvc_round_mv(mv, 0, MAX_CU_DEPTH); |
449 | 30.4k | ff_vvc_clip_mv(mv); |
450 | 30.4k | } |
451 | 32.3k | } |
452 | 16.1k | ff_vvc_set_mvf(lc, x0, y0, sbw, sbh, &mvf); |
453 | 16.1k | } |
454 | 8.08k | } |
455 | 4.04k | } |
456 | | |
457 | | void ff_vvc_store_gpm_mvf(const VVCLocalContext *lc, const PredictionUnit *pu) |
458 | 9.23k | { |
459 | 9.23k | const CodingUnit *cu = lc->cu; |
460 | 9.23k | const int angle_idx = ff_vvc_gpm_angle_idx[pu->gpm_partition_idx]; |
461 | 9.23k | const int distance_idx = ff_vvc_gpm_distance_idx[pu->gpm_partition_idx]; |
462 | 9.23k | const int displacement_x = ff_vvc_gpm_distance_lut[angle_idx]; |
463 | 9.23k | const int displacement_y = ff_vvc_gpm_distance_lut[(angle_idx + 8) % 32]; |
464 | 9.23k | const int is_flip = angle_idx >= 13 &&angle_idx <= 27; |
465 | 9.23k | const int shift_hor = (angle_idx % 16 == 8 || (angle_idx % 16 && cu->cb_height >= cu->cb_width)) ? 0 : 1; |
466 | 9.23k | const int sign = angle_idx < 16 ? 1 : -1; |
467 | 9.23k | const int block_size = 4; |
468 | 9.23k | int offset_x = (-cu->cb_width) >> 1; |
469 | 9.23k | int offset_y = (-cu->cb_height) >> 1; |
470 | | |
471 | 9.23k | if (!shift_hor) |
472 | 8.59k | offset_y += sign * ((distance_idx * cu->cb_height) >> 3); |
473 | 632 | else |
474 | 632 | offset_x += sign * ((distance_idx * cu->cb_width) >> 3); |
475 | | |
476 | 27.6k | for (int y = 0; y < cu->cb_height; y += block_size) { |
477 | 55.3k | for (int x = 0; x < cu->cb_width; x += block_size) { |
478 | 36.9k | const int motion_idx = (((x + offset_x) * (1 << 1)) + 5) * displacement_x + |
479 | 36.9k | (((y + offset_y) * (1 << 1)) + 5) * displacement_y; |
480 | 36.9k | const int s_type = FFABS(motion_idx) < 32 ? 2 : (motion_idx <= 0 ? (1 - is_flip) : is_flip); |
481 | 36.9k | const int pred_flag = pu->gpm_mv[0].pred_flag | pu->gpm_mv[1].pred_flag; |
482 | 36.9k | const int x0 = cu->x0 + x; |
483 | 36.9k | const int y0 = cu->y0 + y; |
484 | | |
485 | 36.9k | if (!s_type) |
486 | 11.0k | ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, pu->gpm_mv + 0); |
487 | 25.9k | else if (s_type == 1 || (s_type == 2 && pred_flag != PF_BI)) |
488 | 15.9k | ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, pu->gpm_mv + 1); |
489 | 9.96k | else { |
490 | 9.96k | MvField mvf = pu->gpm_mv[0]; |
491 | 9.96k | const MvField *mv1 = &pu->gpm_mv[1]; |
492 | 9.96k | const int lx = mv1->pred_flag - PF_L0; |
493 | 9.96k | mvf.pred_flag = PF_BI; |
494 | 9.96k | mvf.ref_idx[lx] = mv1->ref_idx[lx]; |
495 | 9.96k | mvf.mv[lx] = mv1->mv[lx]; |
496 | 9.96k | ff_vvc_set_mvf(lc, x0, y0, block_size, block_size, &mvf); |
497 | 9.96k | } |
498 | 36.9k | } |
499 | 18.4k | } |
500 | 9.23k | } |
501 | | |
502 | | void ff_vvc_store_mvf(const VVCLocalContext *lc, const MvField *mvf) |
503 | 54.0k | { |
504 | 54.0k | const CodingUnit *cu = lc->cu; |
505 | 54.0k | ff_vvc_set_mvf(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height, mvf); |
506 | 54.0k | } |
507 | | |
508 | | void ff_vvc_store_mv(const VVCLocalContext *lc, const MotionInfo *mi) |
509 | 369k | { |
510 | 369k | const CodingUnit *cu = lc->cu; |
511 | 369k | MvField mvf = {0}; |
512 | | |
513 | 369k | mvf.hpel_if_idx = mi->hpel_if_idx; |
514 | 369k | mvf.bcw_idx = mi->bcw_idx; |
515 | 369k | mvf.pred_flag = mi->pred_flag; |
516 | | |
517 | 1.10M | for (int i = 0; i < 2; i++) { |
518 | 738k | const PredFlag mask = i + 1; |
519 | 738k | if (mvf.pred_flag & mask) { |
520 | 371k | mvf.mv[i] = mi->mv[i][0]; |
521 | 371k | mvf.ref_idx[i] = mi->ref_idx[i]; |
522 | 371k | } |
523 | 738k | } |
524 | 369k | ff_vvc_set_mvf(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height, &mvf); |
525 | 369k | } |
526 | | |
527 | | typedef enum NeighbourIdx { |
528 | | A0, |
529 | | A1, |
530 | | A2, |
531 | | B0, |
532 | | B1, |
533 | | B2, |
534 | | B3, |
535 | | NUM_NBS, |
536 | | NB_IDX_NONE = NUM_NBS, |
537 | | } NeighbourIdx; |
538 | | |
539 | | typedef struct Neighbour { |
540 | | int x; |
541 | | int y; |
542 | | |
543 | | int checked; |
544 | | int available; |
545 | | } Neighbour; |
546 | | |
547 | | typedef struct NeighbourContext { |
548 | | Neighbour neighbours[NUM_NBS]; |
549 | | const VVCLocalContext *lc; |
550 | | } NeighbourContext; |
551 | | |
552 | | static int is_available(const VVCFrameContext *fc, const int x0, const int y0) |
553 | 131k | { |
554 | 131k | const VVCSPS *sps = fc->ps.sps; |
555 | 131k | const int x = x0 >> sps->min_cb_log2_size_y; |
556 | 131k | const int y = y0 >> sps->min_cb_log2_size_y; |
557 | 131k | const int min_cb_width = fc->ps.pps->min_cb_width; |
558 | | |
559 | 131k | return SAMPLE_CTB(fc->tab.cb_width[0], x, y) != 0; |
560 | 131k | } |
561 | | |
562 | | static int is_a0_available(const VVCLocalContext *lc, const CodingUnit *cu) |
563 | 238k | { |
564 | 238k | const VVCFrameContext *fc = lc->fc; |
565 | 238k | const VVCSPS *sps = fc->ps.sps; |
566 | 238k | const int x0b = av_zero_extend(cu->x0, sps->ctb_log2_size_y); |
567 | 238k | int cand_bottom_left; |
568 | | |
569 | 238k | if (!x0b && !lc->ctb_left_flag) { |
570 | 205k | cand_bottom_left = 0; |
571 | 205k | } else { |
572 | 33.6k | const int max_y = FFMIN(fc->ps.pps->height, ((cu->y0 >> sps->ctb_log2_size_y) + 1) << sps->ctb_log2_size_y); |
573 | 33.6k | if (cu->y0 + cu->cb_height >= max_y) |
574 | 20.4k | cand_bottom_left = 0; |
575 | 13.2k | else |
576 | 13.2k | cand_bottom_left = is_available(fc, cu->x0 - 1, cu->y0 + cu->cb_height); |
577 | 33.6k | } |
578 | 238k | return cand_bottom_left; |
579 | 238k | } |
580 | | |
581 | | static void init_neighbour_context(NeighbourContext *ctx, const VVCLocalContext *lc) |
582 | 238k | { |
583 | 238k | const CodingUnit *cu = lc->cu; |
584 | 238k | const NeighbourAvailable *na = &lc->na; |
585 | 238k | const int x0 = cu->x0; |
586 | 238k | const int y0 = cu->y0; |
587 | 238k | const int cb_width = cu->cb_width; |
588 | 238k | const int cb_height = cu->cb_height; |
589 | 238k | const int a0_available = is_a0_available(lc, cu); |
590 | | |
591 | 238k | Neighbour neighbours[NUM_NBS] = { |
592 | 238k | { x0 - 1, y0 + cb_height, !a0_available }, //A0 |
593 | 238k | { x0 - 1, y0 + cb_height - 1, !na->cand_left }, //A1 |
594 | 238k | { x0 - 1, y0, !na->cand_left }, //A2 |
595 | 238k | { x0 + cb_width, y0 - 1, !na->cand_up_right }, //B0 |
596 | 238k | { x0 + cb_width - 1, y0 - 1, !na->cand_up }, //B1 |
597 | 238k | { x0 - 1, y0 - 1, !na->cand_up_left }, //B2 |
598 | 238k | { x0, y0 - 1, !na->cand_up }, //B3 |
599 | 238k | }; |
600 | | |
601 | 238k | memcpy(ctx->neighbours, neighbours, sizeof(neighbours)); |
602 | 238k | ctx->lc = lc; |
603 | 238k | } |
604 | | |
605 | | static av_always_inline PredMode pred_flag_to_mode(PredFlag pred) |
606 | 115k | { |
607 | 115k | static const PredMode lut[] = { |
608 | 115k | MODE_INTRA, // PF_INTRA |
609 | 115k | MODE_INTER, // PF_L0 |
610 | 115k | MODE_INTER, // PF_L1 |
611 | 115k | MODE_INTER, // PF_BI |
612 | 115k | 0, // invalid |
613 | 115k | MODE_IBC, // PF_IBC |
614 | 115k | 0, // invalid |
615 | 115k | 0, // invalid |
616 | 115k | MODE_PLT, // PF_PLT |
617 | 115k | }; |
618 | | |
619 | 115k | return lut[pred]; |
620 | 115k | } |
621 | | |
622 | | static int check_available(Neighbour *n, const VVCLocalContext *lc, const int check_mer) |
623 | 787k | { |
624 | 787k | const VVCFrameContext *fc = lc->fc; |
625 | 787k | const VVCSPS *sps = fc->ps.sps; |
626 | 787k | const CodingUnit *cu = lc->cu; |
627 | 787k | const MvField *tab_mvf = fc->tab.mvf; |
628 | 787k | const int min_pu_width = fc->ps.pps->min_pu_width; |
629 | | |
630 | 787k | if (!n->checked) { |
631 | 117k | n->checked = 1; |
632 | 117k | 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 | 117k | 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 | 117k | if (check_mer) |
635 | 45.6k | n->available = n->available && !is_same_mer(fc, n->x, n->y, cu->x0, cu->y0); |
636 | 117k | } |
637 | 787k | return n->available; |
638 | 787k | } |
639 | | |
640 | | static const MvField *mv_merge_candidate(const VVCLocalContext *lc, const int x_cand, const int y_cand) |
641 | 42.0k | { |
642 | 42.0k | const VVCFrameContext *fc = lc->fc; |
643 | 42.0k | const int min_pu_width = fc->ps.pps->min_pu_width; |
644 | 42.0k | const MvField* tab_mvf = fc->tab.mvf; |
645 | 42.0k | const MvField *mvf = &TAB_MVF(x_cand, y_cand); |
646 | | |
647 | 42.0k | return mvf; |
648 | 42.0k | } |
649 | | |
650 | | static const MvField* mv_merge_from_nb(NeighbourContext *ctx, const NeighbourIdx nb) |
651 | 283k | { |
652 | 283k | const VVCLocalContext *lc = ctx->lc; |
653 | 283k | Neighbour *n = &ctx->neighbours[nb]; |
654 | | |
655 | 283k | if (check_available(n, lc, 1)) |
656 | 42.0k | return mv_merge_candidate(lc, n->x, n->y); |
657 | 241k | return 0; |
658 | 283k | } |
659 | 283k | #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 | 63.2k | { |
665 | 63.2k | const MvField *cand; |
666 | 63.2k | int num_cands = 0; |
667 | 63.2k | NeighbourContext nctx; |
668 | | |
669 | 63.2k | static NeighbourIdx nbs[][2] = { |
670 | 63.2k | {B1, NB_IDX_NONE }, |
671 | 63.2k | {A1, B1 }, |
672 | 63.2k | {B0, B1 }, |
673 | 63.2k | {A0, A1 }, |
674 | 63.2k | }; |
675 | | |
676 | 63.2k | init_neighbour_context(&nctx, lc); |
677 | 283k | for (int i = 0; i < FF_ARRAY_ELEMS(nbs); i++) { |
678 | 229k | NeighbourIdx nb = nbs[i][0]; |
679 | 229k | NeighbourIdx old = nbs[i][1]; |
680 | 229k | cand = nb_list[nb] = MV_MERGE_FROM_NB(nb); |
681 | 229k | if (cand && !compare_mv_ref_idx(cand, nb_list[old])) { |
682 | 20.8k | cand_list[num_cands] = *cand; |
683 | 20.8k | if (merge_idx == num_cands) |
684 | 8.84k | return 1; |
685 | 12.0k | num_cands++; |
686 | 12.0k | } |
687 | 229k | } |
688 | 54.4k | if (num_cands != 4) { |
689 | 54.3k | cand = MV_MERGE_FROM_NB(B2); |
690 | 54.3k | if (cand && !compare_mv_ref_idx(cand, nb_list[A1]) |
691 | 408 | && !compare_mv_ref_idx(cand, nb_list[B1])) { |
692 | 255 | cand_list[num_cands] = *cand; |
693 | 255 | if (merge_idx == num_cands) |
694 | 129 | return 1; |
695 | 126 | num_cands++; |
696 | 126 | } |
697 | 54.3k | } |
698 | 54.2k | *nb_merge_cand = num_cands; |
699 | 54.2k | return 0; |
700 | 54.4k | } |
701 | | |
702 | | static int mv_merge_temporal_candidate(const VVCLocalContext *lc, MvField *cand) |
703 | 54.2k | { |
704 | 54.2k | const VVCFrameContext *fc = lc->fc; |
705 | 54.2k | const CodingUnit *cu = lc->cu; |
706 | | |
707 | 54.2k | memset(cand, 0, sizeof(*cand)); |
708 | 54.2k | if (fc->ps.ph.r->ph_temporal_mvp_enabled_flag && (cu->cb_width * cu->cb_height > 32)) { |
709 | 26.3k | int available_l0 = temporal_luma_motion_vector(lc, 0, cand->mv + 0, 0, 1, 0); |
710 | 26.3k | int available_l1 = IS_B(lc->sc->sh.r) ? |
711 | 26.2k | temporal_luma_motion_vector(lc, 0, cand->mv + 1, 1, 1, 0) : 0; |
712 | 26.3k | cand->pred_flag = available_l0 + (available_l1 << 1); |
713 | 26.3k | } |
714 | 54.2k | return cand->pred_flag; |
715 | 54.2k | } |
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 | 53.9k | { |
721 | 53.9k | const VVCSPS *sps = lc->fc->ps.sps; |
722 | 53.9k | const EntryPoint* ep = lc->ep; |
723 | 65.0k | for (int i = 1; i <= ep->num_hmvp && (*num_cands < sps->max_num_merge_cand - 1); i++) { |
724 | 11.8k | const MvField *h = &ep->hmvp[ep->num_hmvp - i]; |
725 | 11.8k | const int same_motion = i <= 2 && (compare_mv_ref_idx(h, nb_list[A1]) || compare_mv_ref_idx(h, nb_list[B1])); |
726 | 11.8k | if (!same_motion) { |
727 | 1.45k | cand_list[*num_cands] = *h; |
728 | 1.45k | if (merge_idx == *num_cands) |
729 | 744 | return 1; |
730 | 714 | (*num_cands)++; |
731 | 714 | } |
732 | 11.8k | } |
733 | 53.2k | return 0; |
734 | 53.9k | } |
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 | 53.2k | { |
739 | 53.2k | if (num_cands > 1) { |
740 | 117 | const int num_ref_rists = is_b ? 2 : 1; |
741 | 117 | const MvField* p0 = cand_list + 0; |
742 | 117 | const MvField* p1 = cand_list + 1; |
743 | 117 | MvField* cand = cand_list + num_cands; |
744 | | |
745 | 117 | cand->pred_flag = 0; |
746 | 234 | for (int i = 0; i < num_ref_rists; i++) { |
747 | 117 | PredFlag mask = i + 1; |
748 | 117 | if (p0->pred_flag & mask) { |
749 | 117 | cand->pred_flag |= mask; |
750 | 117 | cand->ref_idx[i] = p0->ref_idx[i]; |
751 | 117 | if (p1->pred_flag & mask) { |
752 | 117 | Mv *mv = cand->mv + i; |
753 | 117 | mv->x = p0->mv[i].x + p1->mv[i].x; |
754 | 117 | mv->y = p0->mv[i].y + p1->mv[i].y; |
755 | 117 | ff_vvc_round_mv(mv, 0, 1); |
756 | 117 | } else { |
757 | 0 | cand->mv[i] = p0->mv[i]; |
758 | 0 | } |
759 | 117 | } else if (p1->pred_flag & mask) { |
760 | 0 | cand->pred_flag |= mask; |
761 | 0 | cand->mv[i] = p1->mv[i]; |
762 | 0 | cand->ref_idx[i] = p1->ref_idx[i]; |
763 | 0 | } |
764 | 117 | } |
765 | 117 | if (cand->pred_flag) { |
766 | 117 | cand->hpel_if_idx = p0->hpel_if_idx == p1->hpel_if_idx ? p0->hpel_if_idx : 0; |
767 | 117 | cand->bcw_idx = 0; |
768 | 117 | cand->ciip_flag = 0; |
769 | 117 | return 1; |
770 | 117 | } |
771 | 117 | } |
772 | 53.1k | return 0; |
773 | 53.2k | } |
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 | 53.1k | { |
779 | 53.1k | const VVCSPS *sps = lc->fc->ps.sps; |
780 | 53.1k | const H266RawSliceHeader *rsh = lc->sc->sh.r; |
781 | 53.1k | const int num_ref_idx = IS_P(rsh) ? |
782 | 44.9k | rsh->num_ref_idx_active[L0] : FFMIN(rsh->num_ref_idx_active[L0], rsh->num_ref_idx_active[L1]); |
783 | 53.1k | int zero_idx = 0; |
784 | | |
785 | 104k | while (num_cands < sps->max_num_merge_cand) { |
786 | 104k | MvField *cand = cand_list + num_cands; |
787 | | |
788 | 104k | cand->pred_flag = PF_L0 + (IS_B(rsh) << 1); |
789 | 104k | AV_ZERO64(cand->mv + 0); |
790 | 104k | AV_ZERO64(cand->mv + 1); |
791 | 104k | cand->ref_idx[0] = zero_idx < num_ref_idx ? zero_idx : 0; |
792 | 104k | cand->ref_idx[1] = zero_idx < num_ref_idx ? zero_idx : 0; |
793 | 104k | cand->bcw_idx = 0; |
794 | 104k | cand->hpel_if_idx = 0; |
795 | 104k | if (merge_idx == num_cands) |
796 | 53.1k | return; |
797 | 51.4k | num_cands++; |
798 | 51.4k | zero_idx++; |
799 | 51.4k | } |
800 | 53.1k | } |
801 | | |
802 | | static void mv_merge_mode(const VVCLocalContext *lc, const int merge_idx, MvField *cand_list) |
803 | 63.2k | { |
804 | 63.2k | int num_cands = 0; |
805 | 63.2k | const MvField *nb_list[NUM_NBS + 1] = { NULL }; |
806 | | |
807 | 63.2k | if (mv_merge_spatial_candidates(lc, merge_idx, nb_list, cand_list, &num_cands)) |
808 | 8.97k | return; |
809 | | |
810 | 54.2k | if (mv_merge_temporal_candidate(lc, &cand_list[num_cands])) { |
811 | 1.20k | if (merge_idx == num_cands) |
812 | 307 | return; |
813 | 898 | num_cands++; |
814 | 898 | } |
815 | | |
816 | 53.9k | if (mv_merge_history_candidates(lc, merge_idx, nb_list, cand_list, &num_cands)) |
817 | 744 | return; |
818 | | |
819 | 53.2k | if (mv_merge_pairwise_candidate(cand_list, num_cands, IS_B(lc->sc->sh.r))) { |
820 | 117 | if (merge_idx == num_cands) |
821 | 105 | return; |
822 | 12 | num_cands++; |
823 | 12 | } |
824 | | |
825 | 53.1k | mv_merge_zero_motion_candidate(lc, merge_idx, cand_list, num_cands); |
826 | 53.1k | } |
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 | 54.0k | { |
831 | 54.0k | const CodingUnit *cu = lc->cu; |
832 | 54.0k | MvField cand_list[MRG_MAX_NUM_CANDS]; |
833 | | |
834 | 54.0k | ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height); |
835 | 54.0k | mv_merge_mode(lc, merge_idx, cand_list); |
836 | 54.0k | *mv = cand_list[merge_idx]; |
837 | | //ciip flag in not inhritable |
838 | 54.0k | mv->ciip_flag = ciip_flag; |
839 | 54.0k | } |
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 | 9.23k | { |
844 | 9.23k | const CodingUnit *cu = lc->cu; |
845 | 9.23k | MvField cand_list[MRG_MAX_NUM_CANDS]; |
846 | | |
847 | 9.23k | const int idx[] = { merge_gpm_idx[0], merge_gpm_idx[1] + (merge_gpm_idx[1] >= merge_gpm_idx[0]) }; |
848 | | |
849 | 9.23k | ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height); |
850 | 9.23k | mv_merge_mode(lc, FFMAX(idx[0], idx[1]), cand_list); |
851 | 9.23k | memset(mv, 0, 2 * sizeof(*mv)); |
852 | 27.6k | for (int i = 0; i < 2; i++) { |
853 | 18.4k | int lx = idx[i] & 1; |
854 | 18.4k | int mask = lx + PF_L0; |
855 | 18.4k | MvField *cand = cand_list + idx[i]; |
856 | 18.4k | if (!(cand->pred_flag & mask)) { |
857 | 0 | lx = !lx; |
858 | 0 | mask = lx + PF_L0; |
859 | 0 | } |
860 | 18.4k | mv[i].pred_flag = mask; |
861 | 18.4k | mv[i].ref_idx[lx] = cand->ref_idx[lx]; |
862 | 18.4k | mv[i].mv[lx] = cand->mv[lx]; |
863 | 18.4k | } |
864 | | |
865 | 9.23k | } |
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 | 0 | { |
872 | 0 | const VVCFrameContext *fc = lc->fc; |
873 | 0 | const CodingUnit *cu = lc->cu; |
874 | 0 | const int x0 = cu->x0; |
875 | 0 | const int y0 = cu->y0; |
876 | 0 | const int cb_width = cu->cb_width; |
877 | 0 | const int cb_height = cu->cb_height; |
878 | 0 | const MvField* tab_mvf = fc->tab.mvf; |
879 | 0 | const int min_cb_log2_size = fc->ps.sps->min_cb_log2_size_y; |
880 | 0 | const int min_cb_width = fc->ps.pps->min_cb_width; |
881 | |
|
882 | 0 | const int log2_nbw = ff_log2(nbw); |
883 | 0 | const int log2_nbh = ff_log2(nbh); |
884 | 0 | const int is_ctb_boundary = !((y_nb + nbh) % fc->ps.sps->ctb_size_y) && (y_nb + nbh == y0); |
885 | 0 | const Mv *l, *r; |
886 | 0 | int mv_scale_hor, mv_scale_ver, d_hor_x, d_ver_x, d_hor_y, d_ver_y, motion_model_idc_nb; |
887 | 0 | if (is_ctb_boundary) { |
888 | 0 | const int min_pu_width = fc->ps.pps->min_pu_width; |
889 | 0 | l = &TAB_MVF(x_nb, y_nb + nbh - 1).mv[lx]; |
890 | 0 | r = &TAB_MVF(x_nb + nbw - 1, y_nb + nbh - 1).mv[lx]; |
891 | 0 | } else { |
892 | 0 | const int x = x_nb >> min_cb_log2_size; |
893 | 0 | const int y = y_nb >> min_cb_log2_size; |
894 | 0 | motion_model_idc_nb = SAMPLE_CTB(fc->tab.mmi, x, y); |
895 | |
|
896 | 0 | l = &TAB_CP_MV(lx, x_nb, y_nb); |
897 | 0 | r = &TAB_CP_MV(lx, x_nb + nbw - 1, y_nb) + 1; |
898 | 0 | } |
899 | 0 | mv_scale_hor = l->x * (1 << 7); |
900 | 0 | mv_scale_ver = l->y * (1 << 7); |
901 | 0 | d_hor_x = (r->x - l->x) * (1 << (7 - log2_nbw)); |
902 | 0 | d_ver_x = (r->y - l->y) * (1 << (7 - log2_nbw)); |
903 | 0 | if (!is_ctb_boundary && motion_model_idc_nb == MOTION_6_PARAMS_AFFINE) { |
904 | 0 | const Mv* lb = &TAB_CP_MV(lx, x_nb, y_nb + nbh - 1) + 2; |
905 | 0 | d_hor_y = (lb->x - l->x) * (1 << (7 - log2_nbh)); |
906 | 0 | d_ver_y = (lb->y - l->y) * (1 << (7 - log2_nbh)); |
907 | 0 | } else { |
908 | 0 | d_hor_y = -d_ver_x; |
909 | 0 | d_ver_y = d_hor_x; |
910 | 0 | } |
911 | |
|
912 | 0 | if (is_ctb_boundary) { |
913 | 0 | y_nb = y0; |
914 | 0 | } |
915 | 0 | cps[0].x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 - y_nb); |
916 | 0 | cps[0].y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 - y_nb); |
917 | 0 | cps[1].x = mv_scale_hor + d_hor_x * (x0 + cb_width - x_nb) + d_hor_y * (y0 - y_nb); |
918 | 0 | cps[1].y = mv_scale_ver + d_ver_x * (x0 + cb_width - x_nb) + d_ver_y * (y0 - y_nb); |
919 | 0 | if (num_cps == 3) { |
920 | 0 | cps[2].x = mv_scale_hor + d_hor_x * (x0 - x_nb) + d_hor_y * (y0 + cb_height - y_nb); |
921 | 0 | cps[2].y = mv_scale_ver + d_ver_x * (x0 - x_nb) + d_ver_y * (y0 + cb_height - y_nb); |
922 | 0 | } |
923 | 0 | for (int i = 0; i < num_cps; i++) { |
924 | 0 | ff_vvc_round_mv(cps + i, 0, 7); |
925 | 0 | ff_vvc_clip_mv(cps + i); |
926 | 0 | } |
927 | 0 | } |
928 | | |
929 | | //derive affine neighbour's position, 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 | 0 | { |
932 | 0 | const int log2_min_cb_size = fc->ps.sps->min_cb_log2_size_y; |
933 | 0 | const int min_cb_width = fc->ps.pps->min_cb_width; |
934 | 0 | const int x = x_nb >> log2_min_cb_size; |
935 | 0 | const int y = y_nb >> log2_min_cb_size; |
936 | 0 | const int motion_model_idc = SAMPLE_CTB(fc->tab.mmi, x, y); |
937 | 0 | if (motion_model_idc) { |
938 | 0 | *x_cb = SAMPLE_CTB(fc->tab.cb_pos_x[0], x, y); |
939 | 0 | *y_cb = SAMPLE_CTB(fc->tab.cb_pos_y[0], x, y); |
940 | 0 | *cbw = SAMPLE_CTB(fc->tab.cb_width[0], x, y); |
941 | 0 | *cbh = SAMPLE_CTB(fc->tab.cb_height[0], x, y); |
942 | 0 | } |
943 | 0 | return motion_model_idc; |
944 | 0 | } |
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 | 0 | { |
949 | 0 | const VVCFrameContext *fc = lc->fc; |
950 | 0 | int x, y, w, h, motion_model_idc; |
951 | |
|
952 | 0 | motion_model_idc = affine_neighbour_cb(fc, x_cand, y_cand, &x, &y, &w, &h); |
953 | 0 | if (motion_model_idc) { |
954 | 0 | const int min_pu_width = fc->ps.pps->min_pu_width; |
955 | 0 | const MvField* tab_mvf = fc->tab.mvf; |
956 | 0 | const MvField *mvf = &TAB_MVF(x, y); |
957 | |
|
958 | 0 | mi->bcw_idx = mvf->bcw_idx; |
959 | 0 | mi->pred_flag = mvf->pred_flag; |
960 | 0 | for (int i = 0; i < 2; i++) { |
961 | 0 | PredFlag mask = i + 1; |
962 | 0 | if (mi->pred_flag & mask) { |
963 | 0 | affine_cps_from_nb(lc, x, y, w, h, i, &mi->mv[i][0], motion_model_idc + 1); |
964 | 0 | } |
965 | 0 | mi->ref_idx[i] = mvf->ref_idx[i]; |
966 | 0 | } |
967 | 0 | mi->motion_model_idc = motion_model_idc; |
968 | 0 | } |
969 | 0 | return motion_model_idc; |
970 | 0 | } |
971 | | |
972 | | static int affine_merge_from_nbs(NeighbourContext *ctx, const NeighbourIdx *nbs, const int num_nbs, MotionInfo* cand) |
973 | 7.68k | { |
974 | 7.68k | const VVCLocalContext *lc = ctx->lc; |
975 | 26.8k | for (int i = 0; i < num_nbs; i++) { |
976 | 19.2k | Neighbour *n = &ctx->neighbours[nbs[i]]; |
977 | 19.2k | if (check_available(n, lc, 1) && affine_merge_candidate(lc, n->x, n->y, cand)) |
978 | 0 | return 1; |
979 | 19.2k | } |
980 | 7.68k | return 0; |
981 | 7.68k | } |
982 | 7.68k | #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 | 11.7k | { |
987 | 11.7k | const VVCFrameContext *fc = ctx->lc->fc; |
988 | 11.7k | const MvField *tab_mvf = fc->tab.mvf; |
989 | 11.7k | const int min_pu_width = fc->ps.pps->min_pu_width; |
990 | 38.8k | for (int i = 0; i < num_neighbour; i++) { |
991 | 27.1k | Neighbour *n = &ctx->neighbours[neighbour[i]]; |
992 | 27.1k | if (check_available(n, ctx->lc, 1)) { |
993 | 0 | return &TAB_MVF(n->x, n->y); |
994 | 0 | } |
995 | 27.1k | } |
996 | 11.7k | return NULL; |
997 | 11.7k | } |
998 | | |
999 | 11.5k | #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 | 0 | { |
1004 | |
|
1005 | 0 | const PredFlag mask = (lx + 1) & A->pred_flag; |
1006 | 0 | if (!(B->pred_flag & mask)) |
1007 | 0 | return 0; |
1008 | 0 | if (A->ref_idx[lx] != B->ref_idx[lx]) |
1009 | 0 | return 0; |
1010 | 0 | if (C) { |
1011 | 0 | if (!(C->pred_flag & mask)) |
1012 | 0 | return 0; |
1013 | 0 | if (A->ref_idx[lx] != C->ref_idx[lx]) |
1014 | 0 | return 0; |
1015 | 0 | } |
1016 | 0 | return 1; |
1017 | 0 | } |
1018 | | |
1019 | | static av_always_inline void sb_clip_location(const VVCLocalContext *lc, |
1020 | | const int x_ctb, const int y_ctb, const Mv* temp_mv, int *x, int *y) |
1021 | 131 | { |
1022 | 131 | const VVCFrameContext *fc = lc->fc; |
1023 | 131 | const VVCPPS *pps = fc->ps.pps; |
1024 | 131 | const int ctb_log2_size = fc->ps.sps->ctb_log2_size_y; |
1025 | 131 | const int subpic_idx = lc->sc->sh.r->curr_subpic_idx; |
1026 | 131 | const int x_end = pps->subpic_x[subpic_idx] + pps->subpic_width[subpic_idx]; |
1027 | 131 | const int y_end = pps->subpic_y[subpic_idx] + pps->subpic_height[subpic_idx]; |
1028 | | |
1029 | 131 | *x = av_clip(*x + temp_mv->x, x_ctb, FFMIN(x_end - 1, x_ctb + (1 << ctb_log2_size) + 3)) & ~7; |
1030 | 131 | *y = av_clip(*y + temp_mv->y, y_ctb, FFMIN(y_end - 1, y_ctb + (1 << ctb_log2_size) - 1)) & ~7; |
1031 | 131 | } |
1032 | | |
1033 | | static void sb_temproal_luma_motion(const VVCLocalContext *lc, |
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 | 131 | { |
1037 | 131 | MvField temp_col; |
1038 | 131 | Mv* mvLXCol; |
1039 | 131 | const int refIdxLx = 0; |
1040 | 131 | const VVCFrameContext *fc = lc->fc; |
1041 | 131 | const VVCSH *sh = &lc->sc->sh; |
1042 | 131 | const int min_pu_width = fc->ps.pps->min_pu_width; |
1043 | 131 | VVCFrame *ref = fc->ref->collocated_ref; |
1044 | 131 | MvField *tab_mvf = ref->tab_dmvr_mvf; |
1045 | 131 | int colPic = ref->poc; |
1046 | 131 | int X = 0; |
1047 | | |
1048 | 131 | sb_clip_location(lc, x_ctb, y_ctb, temp_mv, &x, &y); |
1049 | | |
1050 | 131 | temp_col = TAB_MVF(x, y); |
1051 | 131 | mvLXCol = mv + 0; |
1052 | 131 | *pred_flag = DERIVE_TEMPORAL_COLOCATED_MVS(1); |
1053 | 131 | if (IS_B(sh->r)) { |
1054 | 130 | X = 1; |
1055 | 130 | mvLXCol = mv + 1; |
1056 | 130 | *pred_flag |= (DERIVE_TEMPORAL_COLOCATED_MVS(1)) << 1; |
1057 | 130 | } |
1058 | 131 | } |
1059 | | |
1060 | | //8.5.5.4 Derivation process for subblock-based temporal merging base motion data |
1061 | | static int sb_temporal_luma_motion_data(const VVCLocalContext *lc, const MvField *a1, |
1062 | | const int x_ctb, const int y_ctb, MvField *ctr_mvf, Mv *temp_mv) |
1063 | 236 | { |
1064 | 236 | const VVCFrameContext *fc = lc->fc; |
1065 | 236 | const RefPicList *rpl = lc->sc->rpl; |
1066 | 236 | const CodingUnit *cu = lc->cu; |
1067 | 236 | const int x = cu->x0 + cu->cb_width / 2; |
1068 | 236 | const int y = cu->y0 + cu->cb_height / 2; |
1069 | 236 | const VVCFrame *ref = fc->ref->collocated_ref; |
1070 | | |
1071 | 236 | int colPic; |
1072 | | |
1073 | 236 | memset(temp_mv, 0, sizeof(*temp_mv)); |
1074 | | |
1075 | 236 | if (!ref) { |
1076 | 130 | memset(ctr_mvf, 0, sizeof(*ctr_mvf)); |
1077 | 130 | return 0; |
1078 | 130 | } |
1079 | | |
1080 | 106 | colPic = ref->poc; |
1081 | | |
1082 | 106 | if (a1) { |
1083 | 0 | if ((a1->pred_flag & PF_L0) && colPic == rpl[L0].refs[a1->ref_idx[L0]].poc) |
1084 | 0 | *temp_mv = a1->mv[0]; |
1085 | 0 | else if ((a1->pred_flag & PF_L1) && colPic == rpl[L1].refs[a1->ref_idx[L1]].poc) |
1086 | 0 | *temp_mv = a1->mv[1]; |
1087 | 0 | ff_vvc_round_mv(temp_mv, 0, 4); |
1088 | 0 | } |
1089 | 106 | sb_temproal_luma_motion(lc, x_ctb, y_ctb, temp_mv, x, y, &ctr_mvf->pred_flag , ctr_mvf->mv); |
1090 | | |
1091 | 106 | return ctr_mvf->pred_flag; |
1092 | 236 | } |
1093 | | |
1094 | | |
1095 | | //8.5.5.3 Derivation process for subblock-based temporal merging candidates |
1096 | | static int sb_temporal_merge_candidate(const VVCLocalContext* lc, NeighbourContext *nctx, PredictionUnit *pu) |
1097 | 4.06k | { |
1098 | 4.06k | const VVCFrameContext *fc = lc->fc; |
1099 | 4.06k | const CodingUnit *cu = lc->cu; |
1100 | 4.06k | const VVCSPS *sps = fc->ps.sps; |
1101 | 4.06k | const VVCPH *ph = &fc->ps.ph; |
1102 | 4.06k | MotionInfo *mi = &pu->mi; |
1103 | 4.06k | const int ctb_log2_size = sps->ctb_log2_size_y; |
1104 | 4.06k | const int x0 = cu->x0; |
1105 | 4.06k | const int y0 = cu->y0; |
1106 | 4.06k | const NeighbourIdx n = A1; |
1107 | 4.06k | const MvField *a1; |
1108 | 4.06k | MvField ctr_mvf; |
1109 | 4.06k | LOCAL_ALIGNED_8(Mv, temp_mv, [1]); |
1110 | 4.06k | const int x_ctb = (x0 >> ctb_log2_size) << ctb_log2_size; |
1111 | 4.06k | const int y_ctb = (y0 >> ctb_log2_size) << ctb_log2_size; |
1112 | | |
1113 | | |
1114 | 4.06k | if (!ph->r->ph_temporal_mvp_enabled_flag || |
1115 | 3.98k | !sps->r->sps_sbtmvp_enabled_flag || |
1116 | 236 | (cu->cb_width < 8 && cu->cb_height < 8)) |
1117 | 3.83k | return 0; |
1118 | | |
1119 | 236 | mi->num_sb_x = cu->cb_width >> 3; |
1120 | 236 | mi->num_sb_y = cu->cb_height >> 3; |
1121 | | |
1122 | 236 | a1 = derive_corner_mvf(nctx, &n, 1); |
1123 | 236 | if (sb_temporal_luma_motion_data(lc, a1, x_ctb, y_ctb, &ctr_mvf, temp_mv)) { |
1124 | 25 | const int sbw = cu->cb_width / mi->num_sb_x; |
1125 | 25 | const int sbh = cu->cb_height / mi->num_sb_y; |
1126 | 25 | MvField mvf = {0}; |
1127 | 50 | for (int sby = 0; sby < mi->num_sb_y; sby++) { |
1128 | 50 | for (int sbx = 0; sbx < mi->num_sb_x; sbx++) { |
1129 | 25 | int x = x0 + sbx * sbw; |
1130 | 25 | int y = y0 + sby * sbh; |
1131 | 25 | sb_temproal_luma_motion(lc, x_ctb, y_ctb, temp_mv, x + sbw / 2, y + sbh / 2, &mvf.pred_flag, mvf.mv); |
1132 | 25 | if (!mvf.pred_flag) { |
1133 | 0 | mvf.pred_flag = ctr_mvf.pred_flag; |
1134 | 0 | memcpy(mvf.mv, ctr_mvf.mv, sizeof(mvf.mv)); |
1135 | 0 | } |
1136 | 25 | ff_vvc_set_mvf(lc, x, y, sbw, sbh, &mvf); |
1137 | 25 | } |
1138 | 25 | } |
1139 | 25 | return 1; |
1140 | 25 | } |
1141 | 211 | return 0; |
1142 | 236 | } |
1143 | | |
1144 | | static int affine_merge_const1(const MvField *c0, const MvField *c1, const MvField *c2, MotionInfo *mi) |
1145 | 2.75k | { |
1146 | 2.75k | if (c0 && c1 && c2) { |
1147 | 0 | mi->pred_flag = 0; |
1148 | 0 | for (int i = 0; i < 2; i++) { |
1149 | 0 | PredFlag mask = i + 1; |
1150 | 0 | if (compare_pf_ref_idx(c0, c1, c2, i)) { |
1151 | 0 | mi->pred_flag |= mask; |
1152 | 0 | mi->ref_idx[i] = c0->ref_idx[i]; |
1153 | 0 | mi->mv[i][0] = c0->mv[i]; |
1154 | 0 | mi->mv[i][1] = c1->mv[i]; |
1155 | 0 | mi->mv[i][2] = c2->mv[i]; |
1156 | 0 | } |
1157 | 0 | } |
1158 | 0 | if (mi->pred_flag) { |
1159 | 0 | if (mi->pred_flag == PF_BI) |
1160 | 0 | mi->bcw_idx = c0->bcw_idx; |
1161 | 0 | mi->motion_model_idc = MOTION_6_PARAMS_AFFINE; |
1162 | 0 | return 1; |
1163 | 0 | } |
1164 | 0 | } |
1165 | 2.75k | return 0; |
1166 | 2.75k | } |
1167 | | |
1168 | | static int affine_merge_const2(const MvField *c0, const MvField *c1, const MvField *c3, MotionInfo *mi) |
1169 | 2.75k | { |
1170 | 2.75k | if (c0 && c1 && c3) { |
1171 | 0 | mi->pred_flag = 0; |
1172 | 0 | for (int i = 0; i < 2; i++) { |
1173 | 0 | PredFlag mask = i + 1; |
1174 | 0 | if (compare_pf_ref_idx(c0, c1, c3, i)) { |
1175 | 0 | mi->pred_flag |= mask; |
1176 | 0 | mi->ref_idx[i] = c0->ref_idx[i]; |
1177 | 0 | mi->mv[i][0] = c0->mv[i]; |
1178 | 0 | mi->mv[i][1] = c1->mv[i]; |
1179 | 0 | mi->mv[i][2].x = c3->mv[i].x + c0->mv[i].x - c1->mv[i].x; |
1180 | 0 | mi->mv[i][2].y = c3->mv[i].y + c0->mv[i].y - c1->mv[i].y; |
1181 | 0 | ff_vvc_clip_mv(&mi->mv[i][2]); |
1182 | 0 | } |
1183 | 0 | } |
1184 | 0 | if (mi->pred_flag) { |
1185 | 0 | mi->bcw_idx = mi->pred_flag == PF_BI ? c0->bcw_idx : 0; |
1186 | 0 | mi->motion_model_idc = MOTION_6_PARAMS_AFFINE; |
1187 | 0 | return 1; |
1188 | 0 | } |
1189 | 0 | } |
1190 | 2.75k | return 0; |
1191 | 2.75k | } |
1192 | | |
1193 | | static int affine_merge_const3(const MvField *c0, const MvField *c2, const MvField *c3, MotionInfo *mi) |
1194 | 2.75k | { |
1195 | 2.75k | if (c0 && c2 && c3) { |
1196 | 0 | mi->pred_flag = 0; |
1197 | 0 | for (int i = 0; i < 2; i++) { |
1198 | 0 | PredFlag mask = i + 1; |
1199 | 0 | if (compare_pf_ref_idx(c0, c2, c3, i)) { |
1200 | 0 | mi->pred_flag |= mask; |
1201 | 0 | mi->ref_idx[i] = c0->ref_idx[i]; |
1202 | 0 | mi->mv[i][0] = c0->mv[i]; |
1203 | 0 | mi->mv[i][1].x = c3->mv[i].x + c0->mv[i].x - c2->mv[i].x; |
1204 | 0 | mi->mv[i][1].y = c3->mv[i].y + c0->mv[i].y - c2->mv[i].y; |
1205 | 0 | ff_vvc_clip_mv(&mi->mv[i][1]); |
1206 | 0 | mi->mv[i][2] = c2->mv[i]; |
1207 | 0 | } |
1208 | 0 | } |
1209 | 0 | if (mi->pred_flag) { |
1210 | 0 | mi->bcw_idx = mi->pred_flag == PF_BI ? c0->bcw_idx : 0; |
1211 | 0 | mi->motion_model_idc = MOTION_6_PARAMS_AFFINE; |
1212 | 0 | return 1; |
1213 | 0 | } |
1214 | 0 | } |
1215 | 2.75k | return 0; |
1216 | 2.75k | } |
1217 | | |
1218 | | static int affine_merge_const4(const MvField *c1, const MvField *c2, const MvField *c3, MotionInfo *mi) |
1219 | 2.75k | { |
1220 | 2.75k | if (c1 && c2 && c3) { |
1221 | 0 | mi->pred_flag = 0; |
1222 | 0 | for (int i = 0; i < 2; i++) { |
1223 | 0 | PredFlag mask = i + 1; |
1224 | 0 | if (compare_pf_ref_idx(c1, c2, c3, i)) { |
1225 | 0 | mi->pred_flag |= mask; |
1226 | 0 | mi->ref_idx[i] = c1->ref_idx[i]; |
1227 | 0 | mi->mv[i][0].x = c1->mv[i].x + c2->mv[i].x - c3->mv[i].x; |
1228 | 0 | mi->mv[i][0].y = c1->mv[i].y + c2->mv[i].y - c3->mv[i].y; |
1229 | 0 | ff_vvc_clip_mv(&mi->mv[i][0]); |
1230 | 0 | mi->mv[i][1] = c1->mv[i]; |
1231 | 0 | mi->mv[i][2] = c2->mv[i]; |
1232 | 0 | } |
1233 | 0 | } |
1234 | 0 | if (mi->pred_flag) { |
1235 | 0 | mi->bcw_idx = mi->pred_flag == PF_BI ? c1->bcw_idx : 0; |
1236 | 0 | mi->motion_model_idc = MOTION_6_PARAMS_AFFINE; |
1237 | 0 | return 1; |
1238 | 0 | } |
1239 | 0 | } |
1240 | 2.75k | return 0; |
1241 | 2.75k | } |
1242 | | |
1243 | | static int affine_merge_const5(const MvField *c0, const MvField *c1, MotionInfo *mi) |
1244 | 3.84k | { |
1245 | 3.84k | if (c0 && c1) { |
1246 | 0 | mi->pred_flag = 0; |
1247 | 0 | for (int i = 0; i < 2; i++) { |
1248 | 0 | PredFlag mask = i + 1; |
1249 | 0 | if (compare_pf_ref_idx(c0, c1, NULL, i)) { |
1250 | 0 | mi->pred_flag |= mask; |
1251 | 0 | mi->ref_idx[i] = c0->ref_idx[i]; |
1252 | 0 | mi->mv[i][0] = c0->mv[i]; |
1253 | 0 | mi->mv[i][1] = c1->mv[i]; |
1254 | 0 | } |
1255 | 0 | } |
1256 | 0 | if (mi->pred_flag) { |
1257 | 0 | if (mi->pred_flag == PF_BI) |
1258 | 0 | mi->bcw_idx = c0->bcw_idx; |
1259 | 0 | mi->motion_model_idc = MOTION_4_PARAMS_AFFINE; |
1260 | 0 | return 1; |
1261 | 0 | } |
1262 | 0 | } |
1263 | 3.84k | return 0; |
1264 | 3.84k | } |
1265 | | |
1266 | | static int affine_merge_const6(const MvField* c0, const MvField* c2, const int cb_width, const int cb_height, MotionInfo *mi) |
1267 | 3.84k | { |
1268 | 3.84k | if (c0 && c2) { |
1269 | 0 | const int shift = 7 + av_log2(cb_width) - av_log2(cb_height); |
1270 | 0 | mi->pred_flag = 0; |
1271 | 0 | for (int i = 0; i < 2; i++) { |
1272 | 0 | PredFlag mask = i + 1; |
1273 | 0 | if (compare_pf_ref_idx(c0, c2, NULL, i)) { |
1274 | 0 | mi->pred_flag |= mask; |
1275 | 0 | mi->ref_idx[i] = c0->ref_idx[i]; |
1276 | 0 | mi->mv[i][0] = c0->mv[i]; |
1277 | 0 | mi->mv[i][1].x = (c0->mv[i].x * (1 << 7)) + ((c2->mv[i].y - c0->mv[i].y) * (1 << shift)); |
1278 | 0 | mi->mv[i][1].y = (c0->mv[i].y * (1 << 7)) - ((c2->mv[i].x - c0->mv[i].x) * (1 << shift)); |
1279 | 0 | ff_vvc_round_mv(&mi->mv[i][1], 0, 7); |
1280 | 0 | ff_vvc_clip_mv(&mi->mv[i][1]); |
1281 | 0 | } |
1282 | 0 | } |
1283 | 0 | if (mi->pred_flag) { |
1284 | 0 | if (mi->pred_flag == PF_BI) |
1285 | 0 | mi->bcw_idx = c0->bcw_idx; |
1286 | 0 | mi->motion_model_idc = MOTION_4_PARAMS_AFFINE; |
1287 | 0 | return 1; |
1288 | 0 | } |
1289 | 0 | } |
1290 | 3.84k | return 0; |
1291 | 3.84k | } |
1292 | | |
1293 | | static void affine_merge_zero_motion(const VVCLocalContext *lc, MotionInfo *mi) |
1294 | 4.04k | { |
1295 | 4.04k | const CodingUnit *cu = lc->cu; |
1296 | | |
1297 | 4.04k | memset(mi, 0, sizeof(*mi)); |
1298 | 4.04k | mi->pred_flag = PF_L0 + (IS_B(lc->sc->sh.r) << 1); |
1299 | 4.04k | mi->motion_model_idc = MOTION_4_PARAMS_AFFINE; |
1300 | 4.04k | mi->num_sb_x = cu->cb_width >> MIN_PU_LOG2; |
1301 | 4.04k | mi->num_sb_y = cu->cb_height >> MIN_PU_LOG2; |
1302 | 4.04k | } |
1303 | | |
1304 | | //8.5.5.6 Derivation process for constructed affine control point motion vector merging candidates |
1305 | | static int affine_merge_const_candidates(const VVCLocalContext *lc, MotionInfo *mi, |
1306 | | NeighbourContext *nctx, const int merge_subblock_idx, int num_cands) |
1307 | 3.84k | { |
1308 | 3.84k | const VVCFrameContext *fc = lc->fc; |
1309 | 3.84k | const CodingUnit *cu = lc->cu; |
1310 | 3.84k | const NeighbourIdx tl[] = { B2, B3, A2 }; |
1311 | 3.84k | const NeighbourIdx tr[] = { B1, B0}; |
1312 | 3.84k | const NeighbourIdx bl[] = { A1, A0}; |
1313 | 3.84k | const MvField *c0, *c1, *c2; |
1314 | | |
1315 | 3.84k | c0 = DERIVE_CORNER_MV(tl); |
1316 | 3.84k | c1 = DERIVE_CORNER_MV(tr); |
1317 | 3.84k | c2 = DERIVE_CORNER_MV(bl); |
1318 | | |
1319 | 3.84k | if (fc->ps.sps->r->sps_6param_affine_enabled_flag) { |
1320 | 2.75k | MvField corner3, *c3 = NULL; |
1321 | | //Const1 |
1322 | 2.75k | if (affine_merge_const1(c0, c1, c2, mi)) { |
1323 | 0 | if (merge_subblock_idx == num_cands) |
1324 | 0 | return 1; |
1325 | 0 | num_cands++; |
1326 | 0 | } |
1327 | | |
1328 | 2.75k | memset(&corner3, 0, sizeof(corner3)); |
1329 | 2.75k | if (fc->ps.ph.r->ph_temporal_mvp_enabled_flag){ |
1330 | 2.67k | const int available_l0 = temporal_luma_motion_vector(lc, 0, corner3.mv + 0, 0, 0, 0); |
1331 | 2.67k | const int available_l1 = (lc->sc->sh.r->sh_slice_type == VVC_SLICE_TYPE_B) ? |
1332 | 2.23k | temporal_luma_motion_vector(lc, 0, corner3.mv + 1, 1, 0, 0) : 0; |
1333 | | |
1334 | 2.67k | corner3.pred_flag = available_l0 + (available_l1 << 1); |
1335 | 2.67k | if (corner3.pred_flag) |
1336 | 0 | c3 = &corner3; |
1337 | 2.67k | } |
1338 | | |
1339 | | //Const2 |
1340 | 2.75k | if (affine_merge_const2(c0, c1, c3, mi)) { |
1341 | 0 | if (merge_subblock_idx == num_cands) |
1342 | 0 | return 1; |
1343 | 0 | num_cands++; |
1344 | 0 | } |
1345 | | |
1346 | | //Const3 |
1347 | 2.75k | if (affine_merge_const3(c0, c2, c3, mi)) { |
1348 | 0 | if (merge_subblock_idx == num_cands) |
1349 | 0 | return 1; |
1350 | 0 | num_cands++; |
1351 | 0 | } |
1352 | | |
1353 | | //Const4 |
1354 | 2.75k | if (affine_merge_const4(c1, c2, c3, mi)) { |
1355 | 0 | if (merge_subblock_idx == num_cands) |
1356 | 0 | return 1; |
1357 | 0 | num_cands++; |
1358 | 0 | } |
1359 | 2.75k | } |
1360 | | |
1361 | | //Const5 |
1362 | 3.84k | if (affine_merge_const5(c0, c1, mi)) { |
1363 | 0 | if (merge_subblock_idx == num_cands) |
1364 | 0 | return 1; |
1365 | 0 | num_cands++; |
1366 | 0 | } |
1367 | | |
1368 | 3.84k | if (affine_merge_const6(c0, c2, cu->cb_width, cu->cb_height, mi)) { |
1369 | 0 | if (merge_subblock_idx == num_cands) |
1370 | 0 | return 1; |
1371 | 0 | } |
1372 | 3.84k | return 0; |
1373 | 3.84k | } |
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 | 4.06k | { |
1379 | 4.06k | const VVCSPS *sps = lc->fc->ps.sps; |
1380 | 4.06k | const CodingUnit *cu = lc->cu; |
1381 | 4.06k | MotionInfo *mi = &pu->mi; |
1382 | 4.06k | int num_cands = 0; |
1383 | 4.06k | NeighbourContext nctx; |
1384 | | |
1385 | 4.06k | init_neighbour_context(&nctx, lc); |
1386 | | |
1387 | | //SbCol |
1388 | 4.06k | if (sb_temporal_merge_candidate(lc, &nctx, pu)) { |
1389 | 25 | if (merge_subblock_idx == num_cands) |
1390 | 25 | return 1; |
1391 | 0 | num_cands++; |
1392 | 0 | } |
1393 | | |
1394 | 4.04k | pu->inter_affine_flag = 1; |
1395 | 4.04k | mi->num_sb_x = cu->cb_width >> MIN_PU_LOG2; |
1396 | 4.04k | mi->num_sb_y = cu->cb_height >> MIN_PU_LOG2; |
1397 | | |
1398 | 4.04k | if (sps->r->sps_affine_enabled_flag) { |
1399 | 3.84k | const NeighbourIdx ak[] = { A0, A1 }; |
1400 | 3.84k | const NeighbourIdx bk[] = { B0, B1, B2 }; |
1401 | | //A |
1402 | 3.84k | if (AFFINE_MERGE_FROM_NBS(ak)) { |
1403 | 0 | if (merge_subblock_idx == num_cands) |
1404 | 0 | return 0; |
1405 | 0 | num_cands++; |
1406 | 0 | } |
1407 | | |
1408 | | //B |
1409 | 3.84k | if (AFFINE_MERGE_FROM_NBS(bk)) { |
1410 | 0 | if (merge_subblock_idx == num_cands) |
1411 | 0 | return 0; |
1412 | 0 | num_cands++; |
1413 | 0 | } |
1414 | | |
1415 | | //Const1 to Const6 |
1416 | 3.84k | if (affine_merge_const_candidates(lc, mi, &nctx, merge_subblock_idx, num_cands)) |
1417 | 0 | return 0; |
1418 | 3.84k | } |
1419 | | //Zero |
1420 | 4.04k | affine_merge_zero_motion(lc, mi); |
1421 | 4.04k | return 0; |
1422 | 4.04k | } |
1423 | | |
1424 | | void ff_vvc_sb_mv_merge_mode(VVCLocalContext *lc, const int merge_subblock_idx, PredictionUnit *pu) |
1425 | 4.06k | { |
1426 | 4.06k | const CodingUnit *cu = lc->cu; |
1427 | 4.06k | ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height); |
1428 | 4.06k | if (!sb_mv_merge_mode(lc, merge_subblock_idx, pu)) { |
1429 | 4.04k | ff_vvc_store_sb_mvs(lc, pu); |
1430 | 4.04k | } |
1431 | 4.06k | } |
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 | 3.81k | { |
1436 | 3.81k | const VVCFrameContext *fc = lc->fc; |
1437 | 3.81k | const RefPicList *rpl = lc->sc->rpl; |
1438 | 3.81k | const int min_pu_width = fc->ps.pps->min_pu_width; |
1439 | 3.81k | const MvField* tab_mvf = fc->tab.mvf; |
1440 | 3.81k | const MvField *mvf = &TAB_MVF(x_cand, y_cand); |
1441 | 3.81k | const PredFlag maskx = lx + 1; |
1442 | 3.81k | const int poc = rpl[lx].refs[ref_idx[lx]].poc; |
1443 | 3.81k | int available = 0; |
1444 | | |
1445 | 3.81k | if ((mvf->pred_flag & maskx) && rpl[lx].refs[mvf->ref_idx[lx]].poc == poc) { |
1446 | 3.59k | available = 1; |
1447 | 3.59k | *mv = mvf->mv[lx]; |
1448 | 3.59k | } else { |
1449 | 216 | const int ly = !lx; |
1450 | 216 | const PredFlag masky = ly + 1; |
1451 | 216 | if ((mvf->pred_flag & masky) && rpl[ly].refs[mvf->ref_idx[ly]].poc == poc) { |
1452 | 105 | available = 1; |
1453 | 105 | *mv = mvf->mv[ly]; |
1454 | 105 | } |
1455 | 216 | } |
1456 | | |
1457 | 3.81k | return available; |
1458 | 3.81k | } |
1459 | | |
1460 | | static int affine_mvp_candidate(const VVCLocalContext *lc, |
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 | 0 | { |
1464 | 0 | const VVCFrameContext *fc = lc->fc; |
1465 | 0 | int x_nb, y_nb, nbw, nbh, motion_model_idc, available = 0; |
1466 | |
|
1467 | 0 | motion_model_idc = affine_neighbour_cb(fc, x_cand, y_cand, &x_nb, &y_nb, &nbw, &nbh); |
1468 | 0 | if (motion_model_idc) { |
1469 | 0 | const int min_pu_width = fc->ps.pps->min_pu_width; |
1470 | 0 | const MvField* tab_mvf = fc->tab.mvf; |
1471 | 0 | const MvField *mvf = &TAB_MVF(x_nb, y_nb); |
1472 | 0 | RefPicList* rpl = lc->sc->rpl; |
1473 | 0 | const PredFlag maskx = lx + 1; |
1474 | 0 | const int poc = rpl[lx].refs[ref_idx[lx]].poc; |
1475 | |
|
1476 | 0 | if ((mvf->pred_flag & maskx) && rpl[lx].refs[mvf->ref_idx[lx]].poc == poc) { |
1477 | 0 | available = 1; |
1478 | 0 | affine_cps_from_nb(lc, x_nb, y_nb, nbw, nbh, lx, cps, num_cp); |
1479 | 0 | } else { |
1480 | 0 | const int ly = !lx; |
1481 | 0 | const PredFlag masky = ly + 1; |
1482 | 0 | if ((mvf->pred_flag & masky) && rpl[ly].refs[mvf->ref_idx[ly]].poc == poc) { |
1483 | 0 | available = 1; |
1484 | 0 | affine_cps_from_nb(lc, x_nb, y_nb, nbw, nbh, ly, cps, num_cp); |
1485 | 0 | } |
1486 | 0 | } |
1487 | |
|
1488 | 0 | } |
1489 | 0 | return available; |
1490 | 0 | } |
1491 | | |
1492 | | static int mvp_from_nbs(NeighbourContext *ctx, |
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 | 81.4k | { |
1496 | 81.4k | const VVCLocalContext *lc = ctx->lc; |
1497 | 81.4k | int available = 0; |
1498 | | |
1499 | 278k | for (int i = 0; i < num_nbs; i++) { |
1500 | 200k | Neighbour *n = &ctx->neighbours[nbs[i]]; |
1501 | 200k | if (check_available(n, lc, 0)) { |
1502 | 3.81k | if (num_cps > 1) |
1503 | 0 | available = affine_mvp_candidate(lc, n->x, n->y, lx, ref_idx, cps, num_cps); |
1504 | 3.81k | else |
1505 | 3.81k | available = mvp_candidate(lc, n->x, n->y, lx, ref_idx, cps); |
1506 | 3.81k | if (available) { |
1507 | 7.40k | for (int c = 0; c < num_cps; c++) |
1508 | 3.70k | ff_vvc_round_mv(cps + c, amvr_shift, amvr_shift); |
1509 | 3.70k | return 1; |
1510 | 3.70k | } |
1511 | 3.81k | } |
1512 | 200k | } |
1513 | 77.7k | return 0; |
1514 | 81.4k | } |
1515 | | |
1516 | | //get mvp from neighbours |
1517 | | #define AFFINE_MVP_FROM_NBS(nbs) \ |
1518 | 0 | 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 | 81.4k | mvp_from_nbs(&nctx, nbs, FF_ARRAY_ELEMS(nbs), lx, ref_idx, amvr_shift, mv, 1) \ |
1522 | | |
1523 | | static int mvp_spatial_candidates(const VVCLocalContext *lc, |
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 | 40.9k | { |
1527 | 40.9k | const NeighbourIdx ak[] = { A0, A1 }; |
1528 | 40.9k | const NeighbourIdx bk[] = { B0, B1, B2 }; |
1529 | 40.9k | NeighbourContext nctx; |
1530 | 40.9k | int available_a, num_cands = 0; |
1531 | 40.9k | LOCAL_ALIGNED_8(Mv, mv_a, [1]); |
1532 | | |
1533 | 40.9k | init_neighbour_context(&nctx, lc); |
1534 | | |
1535 | 40.9k | available_a = MVP_FROM_NBS(ak); |
1536 | 40.9k | if (available_a) { |
1537 | 843 | if (mvp_lx_flag == num_cands) |
1538 | 488 | return 1; |
1539 | 355 | num_cands++; |
1540 | 355 | *mv_a = *mv; |
1541 | 355 | } |
1542 | 40.4k | if (MVP_FROM_NBS(bk)) { |
1543 | 2.86k | if (!available_a || !IS_SAME_MV(mv_a, mv)) { |
1544 | 2.84k | if (mvp_lx_flag == num_cands) |
1545 | 1.87k | return 1; |
1546 | 971 | num_cands++; |
1547 | 971 | } |
1548 | 2.86k | } |
1549 | 38.6k | *nb_merge_cand = num_cands; |
1550 | 38.6k | return 0; |
1551 | 40.4k | } |
1552 | | |
1553 | | static int mvp_temporal_candidates(const VVCLocalContext* lc, |
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 | 38.6k | { |
1557 | 38.6k | if (temporal_luma_motion_vector(lc, ref_idx[lx], mv, lx, 1, 0)) { |
1558 | 140 | if (mvp_lx_flag == *num_cands) { |
1559 | 122 | ff_vvc_round_mv(mv, amvr_shift, amvr_shift); |
1560 | 122 | return 1; |
1561 | 122 | } |
1562 | 18 | (*num_cands)++; |
1563 | 18 | } |
1564 | 38.5k | return 0; |
1565 | | |
1566 | 38.6k | } |
1567 | | |
1568 | | static int mvp_history_candidates(const VVCLocalContext *lc, |
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 | 38.5k | { |
1572 | 38.5k | const EntryPoint* ep = lc->ep; |
1573 | 38.5k | const RefPicList* rpl = lc->sc->rpl; |
1574 | 38.5k | const int poc = rpl[lx].refs[ref_idx].poc; |
1575 | | |
1576 | 38.5k | if (ep->num_hmvp == 0) |
1577 | 37.6k | return 0; |
1578 | 878 | for (int i = 1; i <= FFMIN(4, ep->num_hmvp); i++) { |
1579 | 805 | const MvField* h = &ep->hmvp[i - 1]; |
1580 | 1.04k | for (int j = 0; j < 2; j++) { |
1581 | 973 | const int ly = (j ? !lx : lx); |
1582 | 973 | PredFlag mask = PF_L0 + ly; |
1583 | 973 | if ((h->pred_flag & mask) && poc == rpl[ly].refs[h->ref_idx[ly]].poc) { |
1584 | 732 | if (mvp_lx_flag == num_cands) { |
1585 | 732 | *mv = h->mv[ly]; |
1586 | 732 | ff_vvc_round_mv(mv, amvr_shift, amvr_shift); |
1587 | 732 | return 1; |
1588 | 732 | } |
1589 | 0 | num_cands++; |
1590 | 0 | } |
1591 | 973 | } |
1592 | 805 | } |
1593 | 73 | return 0; |
1594 | 805 | } |
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 | 40.9k | { |
1600 | 40.9k | int num_cands; |
1601 | | |
1602 | 40.9k | if (mvp_spatial_candidates(lc, mvp_lx_flag, lx, ref_idx, amvr_shift, mv, &num_cands)) |
1603 | 2.35k | return; |
1604 | | |
1605 | 38.6k | if (mvp_temporal_candidates(lc, mvp_lx_flag, lx, ref_idx, amvr_shift, mv, &num_cands)) |
1606 | 122 | return; |
1607 | | |
1608 | 38.5k | if (mvp_history_candidates(lc, mvp_lx_flag, lx, ref_idx[lx], amvr_shift, mv, num_cands)) |
1609 | 732 | return; |
1610 | | |
1611 | 37.7k | memset(mv, 0, sizeof(*mv)); |
1612 | 37.7k | } |
1613 | | |
1614 | | void ff_vvc_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi) |
1615 | 38.6k | { |
1616 | 38.6k | const CodingUnit *cu = lc->cu; |
1617 | 38.6k | mi->num_sb_x = 1; |
1618 | 38.6k | mi->num_sb_y = 1; |
1619 | | |
1620 | 38.6k | ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height); |
1621 | 38.6k | if (mi->pred_flag != PF_L1) |
1622 | 36.4k | mvp(lc, mvp_lx_flag[L0], L0, mi->ref_idx, amvr_shift, &mi->mv[L0][0]); |
1623 | 38.6k | if (mi->pred_flag != PF_L0) |
1624 | 4.49k | mvp(lc, mvp_lx_flag[L1], L1, mi->ref_idx, amvr_shift, &mi->mv[L1][0]); |
1625 | 38.6k | } |
1626 | | |
1627 | | static int ibc_spatial_candidates(const VVCLocalContext *lc, const int merge_idx, Mv *const cand_list, int *nb_merge_cand) |
1628 | 348k | { |
1629 | 348k | const CodingUnit *cu = lc->cu; |
1630 | 348k | const VVCFrameContext *fc = lc->fc; |
1631 | 348k | const int min_pu_width = fc->ps.pps->min_pu_width; |
1632 | 348k | const MvField *tab_mvf = fc->tab.mvf; |
1633 | 348k | const int is_gt4by4 = (cu->cb_width * cu->cb_height) > 16; |
1634 | 348k | int num_cands = 0; |
1635 | | |
1636 | 348k | NeighbourContext nctx; |
1637 | 348k | Neighbour *a1 = &nctx.neighbours[A1]; |
1638 | 348k | Neighbour *b1 = &nctx.neighbours[B1]; |
1639 | | |
1640 | 348k | if (!is_gt4by4) { |
1641 | 217k | *nb_merge_cand = 0; |
1642 | 217k | return 0; |
1643 | 217k | } |
1644 | | |
1645 | 130k | init_neighbour_context(&nctx, lc); |
1646 | | |
1647 | 130k | if (check_available(a1, lc, 0)) { |
1648 | 5.58k | cand_list[num_cands++] = TAB_MVF(a1->x, a1->y).mv[L0]; |
1649 | 5.58k | if (num_cands > merge_idx) |
1650 | 4.64k | return 1; |
1651 | 5.58k | } |
1652 | 125k | if (check_available(b1, lc, 0)) { |
1653 | 1.33k | const MvField *mvf = &TAB_MVF(b1->x, b1->y); |
1654 | 1.33k | if (!num_cands || !IS_SAME_MV(&cand_list[0], mvf->mv)) { |
1655 | 1.27k | cand_list[num_cands++] = mvf->mv[L0]; |
1656 | 1.27k | if (num_cands > merge_idx) |
1657 | 758 | return 1; |
1658 | 1.27k | } |
1659 | 1.33k | } |
1660 | | |
1661 | 125k | *nb_merge_cand = num_cands; |
1662 | 125k | return 0; |
1663 | 125k | } |
1664 | | |
1665 | | static int ibc_history_candidates(const VVCLocalContext *lc, |
1666 | | const int merge_idx, Mv *cand_list, int *nb_merge_cand) |
1667 | 342k | { |
1668 | 342k | const CodingUnit *cu = lc->cu; |
1669 | 342k | const EntryPoint *ep = lc->ep; |
1670 | 342k | const int is_gt4by4 = (cu->cb_width * cu->cb_height) > 16; |
1671 | 342k | int num_cands = *nb_merge_cand; |
1672 | | |
1673 | 344k | for (int i = 1; i <= ep->num_hmvp_ibc; i++) { |
1674 | 2.77k | int same_motion = 0; |
1675 | 2.77k | const MvField *mvf = &ep->hmvp_ibc[ep->num_hmvp_ibc - i]; |
1676 | 3.24k | for (int j = 0; j < *nb_merge_cand; j++) { |
1677 | 1.20k | same_motion = is_gt4by4 && i == 1 && IS_SAME_MV(&mvf->mv[L0], &cand_list[j]); |
1678 | 1.20k | if (same_motion) |
1679 | 726 | break; |
1680 | 1.20k | } |
1681 | 2.77k | if (!same_motion) { |
1682 | 2.04k | cand_list[num_cands++] = mvf->mv[L0]; |
1683 | 2.04k | if (num_cands > merge_idx) |
1684 | 1.17k | return 1; |
1685 | 2.04k | } |
1686 | 2.77k | } |
1687 | | |
1688 | 341k | *nb_merge_cand = num_cands; |
1689 | 341k | return 0; |
1690 | 342k | } |
1691 | | |
1692 | 438k | #define MV_BITS 18 |
1693 | 438k | #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 | 219k | { |
1697 | 219k | ff_vvc_round_mv(mv, amvr_shift, 0); |
1698 | 219k | ff_vvc_round_mv(mvp, amvr_shift, amvr_shift); |
1699 | 219k | mv->x = IBC_SHIFT(mv->x + mvp->x); |
1700 | 219k | mv->y = IBC_SHIFT(mv->y + mvp->y); |
1701 | 219k | } |
1702 | | |
1703 | | static void ibc_merge_candidates(VVCLocalContext *lc, const int merge_idx, Mv *mv) |
1704 | 348k | { |
1705 | 348k | const CodingUnit *cu = lc->cu; |
1706 | 348k | LOCAL_ALIGNED_8(Mv, cand_list, [MRG_MAX_NUM_CANDS]); |
1707 | 348k | int nb_cands; |
1708 | | |
1709 | 348k | ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height); |
1710 | 348k | if (ibc_spatial_candidates(lc, merge_idx, cand_list, &nb_cands) || |
1711 | 342k | ibc_history_candidates(lc, merge_idx, cand_list, &nb_cands)) { |
1712 | 6.58k | *mv = cand_list[merge_idx]; |
1713 | 6.58k | return; |
1714 | 6.58k | } |
1715 | | |
1716 | | //zero mv |
1717 | 341k | memset(mv, 0, sizeof(*mv)); |
1718 | 341k | } |
1719 | | |
1720 | | static int ibc_check_mv(VVCLocalContext *lc, Mv *mv) |
1721 | 348k | { |
1722 | 348k | const VVCFrameContext *fc = lc->fc; |
1723 | 348k | const VVCSPS *sps = lc->fc->ps.sps; |
1724 | 348k | const CodingUnit *cu = lc->cu; |
1725 | 348k | const Mv *bv = &cu->pu.mi.mv[L0][0]; |
1726 | | |
1727 | 348k | if (sps->ctb_size_y < ((cu->y0 + (bv->y >> 4)) & (sps->ctb_size_y - 1)) + cu->cb_height) { |
1728 | 17.8k | av_log(fc->log_ctx, AV_LOG_ERROR, "IBC region spans multiple CTBs.\n"); |
1729 | 17.8k | return AVERROR_INVALIDDATA; |
1730 | 17.8k | } |
1731 | | |
1732 | 330k | return 0; |
1733 | 348k | } |
1734 | | |
1735 | | int ff_vvc_mvp_ibc(VVCLocalContext *lc, const int mvp_l0_flag, const int amvr_shift, Mv *mv) |
1736 | 219k | { |
1737 | 219k | LOCAL_ALIGNED_8(Mv, mvp, [1]); |
1738 | | |
1739 | 219k | ibc_merge_candidates(lc, mvp_l0_flag, mvp); |
1740 | 219k | ibc_add_mvp(mv, mvp, amvr_shift); |
1741 | 219k | return ibc_check_mv(lc, mv); |
1742 | 219k | } |
1743 | | |
1744 | | int ff_vvc_luma_mv_merge_ibc(VVCLocalContext *lc, const int merge_idx, Mv *mv) |
1745 | 128k | { |
1746 | 128k | ibc_merge_candidates(lc, merge_idx, mv); |
1747 | 128k | return ibc_check_mv(lc, mv); |
1748 | 128k | } |
1749 | | |
1750 | | static int affine_mvp_constructed_cp(NeighbourContext *ctx, |
1751 | | const NeighbourIdx *neighbour, const int num_neighbour, |
1752 | | const int lx, const int8_t ref_idx, const int amvr_shift, Mv *cp) |
1753 | 0 | { |
1754 | 0 | const VVCLocalContext *lc = ctx->lc; |
1755 | 0 | const VVCFrameContext *fc = lc->fc; |
1756 | 0 | const MvField *tab_mvf = fc->tab.mvf; |
1757 | 0 | const int min_pu_width = fc->ps.pps->min_pu_width; |
1758 | 0 | const RefPicList* rpl = lc->sc->rpl; |
1759 | 0 | int available = 0; |
1760 | |
|
1761 | 0 | for (int i = 0; i < num_neighbour; i++) { |
1762 | 0 | Neighbour *n = &ctx->neighbours[neighbour[i]]; |
1763 | 0 | if (check_available(n, ctx->lc, 0)) { |
1764 | 0 | const PredFlag maskx = lx + 1; |
1765 | 0 | const MvField* mvf = &TAB_MVF(n->x, n->y); |
1766 | 0 | const int poc = rpl[lx].refs[ref_idx].poc; |
1767 | 0 | if ((mvf->pred_flag & maskx) && rpl[lx].refs[mvf->ref_idx[lx]].poc == poc) { |
1768 | 0 | available = 1; |
1769 | 0 | *cp = mvf->mv[lx]; |
1770 | 0 | } else { |
1771 | 0 | const int ly = !lx; |
1772 | 0 | const PredFlag masky = ly + 1; |
1773 | 0 | if ((mvf->pred_flag & masky) && rpl[ly].refs[mvf->ref_idx[ly]].poc == poc) { |
1774 | 0 | available = 1; |
1775 | 0 | *cp = mvf->mv[ly]; |
1776 | 0 | } |
1777 | 0 | } |
1778 | 0 | if (available) { |
1779 | 0 | ff_vvc_round_mv(cp, amvr_shift, amvr_shift); |
1780 | 0 | return 1; |
1781 | 0 | } |
1782 | 0 | } |
1783 | 0 | } |
1784 | 0 | return 0; |
1785 | 0 | } |
1786 | | |
1787 | | #define AFFINE_MVP_CONSTRUCTED_CP(cands, cp) \ |
1788 | 0 | affine_mvp_constructed_cp(nctx, cands, FF_ARRAY_ELEMS(cands), lx, ref_idx, \ |
1789 | 0 | amvr_shift, cp) |
1790 | | |
1791 | | //8.5.5.8 Derivation process for constructed affine control point motion vector prediction candidates |
1792 | | static int affine_mvp_const1(NeighbourContext* nctx, |
1793 | | const int lx, const int8_t ref_idx, const int amvr_shift, |
1794 | | Mv *cps, int *available) |
1795 | 0 | { |
1796 | 0 | const NeighbourIdx tl[] = { B2, B3, A2 }; |
1797 | 0 | const NeighbourIdx tr[] = { B1, B0 }; |
1798 | 0 | const NeighbourIdx bl[] = { A1, A0 }; |
1799 | |
|
1800 | 0 | available[0] = AFFINE_MVP_CONSTRUCTED_CP(tl, cps + 0); |
1801 | 0 | available[1] = AFFINE_MVP_CONSTRUCTED_CP(tr, cps + 1); |
1802 | 0 | available[2] = AFFINE_MVP_CONSTRUCTED_CP(bl, cps + 2); |
1803 | 0 | return available[0] && available[1]; |
1804 | 0 | } |
1805 | | |
1806 | | //8.5.5.7 item 7 |
1807 | | static void affine_mvp_const2(const int idx, Mv *cps, const int num_cp) |
1808 | 0 | { |
1809 | 0 | const Mv mv = cps[idx]; |
1810 | 0 | for (int j = 0; j < num_cp; j++) |
1811 | 0 | cps[j] = mv; |
1812 | 0 | } |
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 | 0 | { |
1819 | 0 | const NeighbourIdx ak[] = { A0, A1 }; |
1820 | 0 | const NeighbourIdx bk[] = { B0, B1, B2 }; |
1821 | 0 | const int num_cp = motion_model_idc + 1; |
1822 | 0 | NeighbourContext nctx; |
1823 | 0 | int available[MAX_CONTROL_POINTS]; |
1824 | 0 | int num_cands = 0; |
1825 | |
|
1826 | 0 | init_neighbour_context(&nctx, lc); |
1827 | | //Ak |
1828 | 0 | if (AFFINE_MVP_FROM_NBS(ak)) { |
1829 | 0 | if (mvp_lx_flag == num_cands) |
1830 | 0 | return; |
1831 | 0 | num_cands++; |
1832 | 0 | } |
1833 | | //Bk |
1834 | 0 | if (AFFINE_MVP_FROM_NBS(bk)) { |
1835 | 0 | if (mvp_lx_flag == num_cands) |
1836 | 0 | return; |
1837 | 0 | num_cands++; |
1838 | 0 | } |
1839 | | |
1840 | | //Const1 |
1841 | 0 | if (affine_mvp_const1(&nctx, lx, ref_idx[lx], amvr_shift, cps, available)) { |
1842 | 0 | if (available[2] || motion_model_idc == MOTION_4_PARAMS_AFFINE) { |
1843 | 0 | if (mvp_lx_flag == num_cands) |
1844 | 0 | return; |
1845 | 0 | num_cands++; |
1846 | 0 | } |
1847 | 0 | } |
1848 | | |
1849 | | //Const2 |
1850 | 0 | for (int i = 2; i >= 0; i--) { |
1851 | 0 | if (available[i]) { |
1852 | 0 | if (mvp_lx_flag == num_cands) { |
1853 | 0 | affine_mvp_const2(i, cps, num_cp); |
1854 | 0 | return; |
1855 | 0 | } |
1856 | 0 | num_cands++; |
1857 | 0 | } |
1858 | 0 | } |
1859 | 0 | if (temporal_luma_motion_vector(lc, ref_idx[lx], cps, lx, 1, 0)) { |
1860 | 0 | if (mvp_lx_flag == num_cands) { |
1861 | 0 | ff_vvc_round_mv(cps, amvr_shift, amvr_shift); |
1862 | 0 | for (int i = 1; i < num_cp; i++) |
1863 | 0 | cps[i] = cps[0]; |
1864 | 0 | return; |
1865 | 0 | } |
1866 | 0 | num_cands++; |
1867 | 0 | } |
1868 | | |
1869 | | //Zero Mv |
1870 | 0 | memset(cps, 0, num_cp * sizeof(Mv)); |
1871 | 0 | } |
1872 | | |
1873 | | void ff_vvc_affine_mvp(VVCLocalContext *lc, const int *mvp_lx_flag, const int amvr_shift, MotionInfo *mi) |
1874 | 0 | { |
1875 | 0 | const CodingUnit *cu = lc->cu; |
1876 | |
|
1877 | 0 | mi->num_sb_x = cu->cb_width >> MIN_PU_LOG2; |
1878 | 0 | mi->num_sb_y = cu->cb_height >> MIN_PU_LOG2; |
1879 | |
|
1880 | 0 | ff_vvc_set_neighbour_available(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height); |
1881 | 0 | if (mi->pred_flag != PF_L1) |
1882 | 0 | affine_mvp(lc, mvp_lx_flag[L0], L0, mi->ref_idx, amvr_shift, mi->motion_model_idc, &mi->mv[L0][0]); |
1883 | 0 | if (mi->pred_flag != PF_L0) |
1884 | 0 | affine_mvp(lc, mvp_lx_flag[L1], L1, mi->ref_idx, amvr_shift, mi->motion_model_idc, &mi->mv[L1][0]); |
1885 | 0 | } |
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 | 473k | { |
1890 | 473k | if (rshift) { |
1891 | 254k | const int offset = 1 << (rshift - 1); |
1892 | 254k | mv->x = ((mv->x + offset - (mv->x >= 0)) >> rshift) * (1 << lshift); |
1893 | 254k | mv->y = ((mv->y + offset - (mv->y >= 0)) >> rshift) * (1 << lshift); |
1894 | 254k | } else { |
1895 | 219k | mv->x = mv->x * (1 << lshift); |
1896 | 219k | mv->y = mv->y * (1 << lshift); |
1897 | 219k | } |
1898 | 473k | } |
1899 | | |
1900 | | void ff_vvc_clip_mv(Mv *mv) |
1901 | 30.4k | { |
1902 | 30.4k | mv->x = av_clip(mv->x, -(1 << 17), (1 << 17) - 1); |
1903 | 30.4k | mv->y = av_clip(mv->y, -(1 << 17), (1 << 17) - 1); |
1904 | 30.4k | } |
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 | 92.7k | { |
1909 | 92.7k | const uint8_t plevel = fc->ps.sps->log2_parallel_merge_level; |
1910 | | |
1911 | 92.7k | return x0_br >> plevel > x0 >> plevel && |
1912 | 83.5k | y0_br >> plevel > y0 >> plevel; |
1913 | 92.7k | } |
1914 | | |
1915 | | static void update_hmvp(MvField *hmvp, int *num_hmvp, const MvField *mvf, |
1916 | | int (*compare)(const MvField *n, const MvField *o)) |
1917 | 204k | { |
1918 | 204k | int i; |
1919 | 239k | for (i = 0; i < *num_hmvp; i++) { |
1920 | 51.0k | if (compare(mvf, hmvp + i)) { |
1921 | 16.6k | (*num_hmvp)--; |
1922 | 16.6k | break; |
1923 | 16.6k | } |
1924 | 51.0k | } |
1925 | 204k | if (i == MAX_NUM_HMVP_CANDS) { |
1926 | 2.68k | (*num_hmvp)--; |
1927 | 2.68k | i = 0; |
1928 | 2.68k | } |
1929 | | |
1930 | 204k | memmove(hmvp + i, hmvp + i + 1, (*num_hmvp - i) * sizeof(MvField)); |
1931 | 204k | hmvp[(*num_hmvp)++] = *mvf; |
1932 | 204k | } |
1933 | | |
1934 | | static int compare_l0_mv(const MvField *n, const MvField *o) |
1935 | 19.7k | { |
1936 | 19.7k | return IS_SAME_MV(&n->mv[L0], &o->mv[L0]); |
1937 | 19.7k | } |
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 |
1941 | | void ff_vvc_update_hmvp(VVCLocalContext *lc, const MotionInfo *mi) |
1942 | 423k | { |
1943 | 423k | const VVCFrameContext *fc = lc->fc; |
1944 | 423k | const CodingUnit *cu = lc->cu; |
1945 | 423k | const int min_pu_width = fc->ps.pps->min_pu_width; |
1946 | 423k | const MvField *tab_mvf = fc->tab.mvf; |
1947 | 423k | EntryPoint *ep = lc->ep; |
1948 | | |
1949 | 423k | if (cu->pred_mode == MODE_IBC) { |
1950 | 330k | if (cu->cb_width * cu->cb_height <= 16) |
1951 | 208k | return; |
1952 | 121k | update_hmvp(ep->hmvp_ibc, &ep->num_hmvp_ibc, &TAB_MVF(cu->x0, cu->y0), compare_l0_mv); |
1953 | 121k | } else { |
1954 | 92.7k | if (!is_greater_mer(fc, cu->x0, cu->y0, cu->x0 + cu->cb_width, cu->y0 + cu->cb_height)) |
1955 | 9.26k | return; |
1956 | 83.4k | update_hmvp(ep->hmvp, &ep->num_hmvp, &TAB_MVF(cu->x0, cu->y0), compare_mv_ref_idx); |
1957 | 83.4k | } |
1958 | 423k | } |
1959 | | |
1960 | | MvField* ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0) |
1961 | 57.8k | { |
1962 | 57.8k | const int min_pu_width = fc->ps.pps->min_pu_width; |
1963 | 57.8k | MvField* tab_mvf = fc->tab.mvf; |
1964 | | |
1965 | 57.8k | return &TAB_MVF(x0, y0); |
1966 | 57.8k | } |