FFmpeg
inter.c
Go to the documentation of this file.
1 /*
2  * VVC inter prediction
3  *
4  * Copyright (C) 2022 Nuo Mi
5  *
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 #include "libavutil/frame.h"
23 
24 #include "data.h"
25 #include "inter.h"
26 #include "mvs.h"
27 #include "refs.h"
28 
29 // +1 is enough, + 32 for asm alignment
30 #define PROF_TEMP_OFFSET (MAX_PB_SIZE + 32)
31 static const int bcw_w_lut[] = {4, 5, 3, 10, -2};
32 
33 static void subpic_get_rect(VVCRect *r, const VVCFrame *src_frame, const int subpic_idx, const int is_chroma)
34 {
35  const VVCSPS *sps = src_frame->sps;
36  const VVCPPS *pps = src_frame->pps;
37  const int hs = sps->hshift[is_chroma];
38  const int vs = sps->vshift[is_chroma];
39 
40  r->l = pps->subpic_x[subpic_idx] >> hs;
41  r->t = pps->subpic_y[subpic_idx] >> vs;
42  r->r = r->l + (pps->subpic_width[subpic_idx] >> hs);
43  r->b = r->t + (pps->subpic_height[subpic_idx] >> vs);
44 }
45 
46 // clip to subblock and subpicture process in 8.5.6.3.2 Luma sample interpolation filtering process
47 static void clip_to_subpic(int *x_off, int *y_off, int *pic_width, int *pic_height, const VVCRect *subpic, const VVCRect *sb, const int dmvr_clip)
48 {
49  const int l = dmvr_clip ? FFMIN(FFMAX(subpic->l, sb->l), subpic->r - 1) : subpic->l;
50  const int t = dmvr_clip ? FFMIN(FFMAX(subpic->t, sb->t), subpic->b - 1) : subpic->t;
51  const int r = dmvr_clip ? FFMAX(FFMIN(subpic->r, sb->r), subpic->l + 1) : subpic->r;
52  const int b = dmvr_clip ? FFMAX(FFMIN(subpic->b, sb->b), subpic->t + 1) : subpic->b;
53 
54  *x_off -= l;
55  *y_off -= t;
56  *pic_width = r - l;
57  *pic_height = b - t;
58 }
59 
60 static void emulated_edge_no_wrap(const VVCLocalContext *lc, uint8_t *dst,
61  const uint8_t **src, ptrdiff_t *src_stride,
62  int x_off, int y_off, const int block_w, const int block_h,
63  const int extra_before, const int extra_after,
64  const VVCRect *subpic, const VVCRect *sb, const int dmvr_clip)
65 {
66  const VVCFrameContext *fc = lc->fc;
67  const int extra = extra_before + extra_after;
68  int pic_width, pic_height;
69 
70  *src += y_off * *src_stride + (x_off * (1 << fc->ps.sps->pixel_shift));
71 
72  clip_to_subpic(&x_off, &y_off, &pic_width, &pic_height, subpic, sb, dmvr_clip);
73 
74  if (dmvr_clip || x_off < extra_before || y_off < extra_before ||
75  x_off >= pic_width - block_w - extra_after ||
76  y_off >= pic_height - block_h - extra_after) {
77  const int ps = fc->ps.sps->pixel_shift;
78  const ptrdiff_t edge_emu_stride = EDGE_EMU_BUFFER_STRIDE << ps;
79  const int offset = extra_before * *src_stride + (extra_before << ps);
80  const int buf_offset = extra_before * edge_emu_stride + (extra_before << ps);
81 
82  fc->vdsp.emulated_edge_mc(dst, *src - offset, edge_emu_stride, *src_stride,
83  block_w + extra, block_h + extra, x_off - extra_before, y_off - extra_before,
84  pic_width, pic_height);
85 
86  *src = dst + buf_offset;
87  *src_stride = edge_emu_stride;
88  }
89 }
90 
91 static void emulated_half(const VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride,
92  const uint8_t *src, const ptrdiff_t src_stride, const int ps,
93  int x_off, int y_off, const int block_w, const int block_h,
94  const VVCRect *subpic,const VVCRect *half_sb, const int dmvr_clip)
95 {
96  const VVCFrameContext *fc = lc->fc;
97  int pic_width, pic_height;
98 
99  src += y_off * src_stride + x_off * (1 << ps);
100 
101  clip_to_subpic(&x_off, &y_off, &pic_width, &pic_height, subpic, half_sb, dmvr_clip);
102 
103  fc->vdsp.emulated_edge_mc(dst, src, dst_stride, src_stride,
104  block_w, block_h, x_off, y_off, pic_width, pic_height);
105 }
106 
107 static void sb_set_lr(VVCRect *sb, const int l, const int r)
108 {
109  sb->l = l;
110  sb->r = r;
111 }
112 
113 static void sb_wrap(VVCRect *sb, const int wrap)
114 {
115  sb_set_lr(sb, sb->l + wrap, sb->r + wrap);
116 }
117 
118 static void emulated_edge(const VVCLocalContext *lc, uint8_t *dst,
119  const uint8_t **src, ptrdiff_t *src_stride, const VVCFrame *src_frame,
120  int x_sb, int y_sb, int x_off, int y_off, int block_w, int block_h, const int wrap_enabled,
121  const int is_chroma, const int extra_before, const int extra_after)
122 {
123  const VVCSPS *sps = src_frame->sps;
124  const VVCPPS *pps = src_frame->pps;
125  const int ps = sps->pixel_shift;
126  const int subpic_idx = lc->sc->sh.r->curr_subpic_idx;
127  const int extra = extra_before + extra_after;
128  const int dmvr_clip = x_sb != x_off || y_sb != y_off;
129  const int dmvr_left = FFMAX(x_off, x_sb) - extra_before;
130  const int dmvr_right = FFMIN(x_off, x_sb) + block_w + extra_after;
131  const int left = x_off - extra_before;
132  const int top = y_off - extra_before;
133  const int pic_width = pps->width >> sps->hshift[is_chroma];
134  const int wrap = pps->ref_wraparound_offset << (sps->min_cb_log2_size_y - sps->hshift[is_chroma]);
135  const ptrdiff_t dst_stride = EDGE_EMU_BUFFER_STRIDE << ps;
136  VVCRect sb = { x_sb - extra_before, y_sb - extra_before, x_sb + block_w + extra_after, y_sb + block_h + extra_after };
137  VVCRect subpic;
138 
139  subpic_get_rect(&subpic, src_frame, subpic_idx, is_chroma);
140 
141  if (!wrap_enabled || (dmvr_left >= 0 && dmvr_right <= pic_width)) {
142  emulated_edge_no_wrap(lc, dst, src, src_stride,
143  x_off, y_off, block_w, block_h, extra_before, extra_after, &subpic, &sb, dmvr_clip);
144  return;
145  }
146  if (dmvr_right <= 0) {
147  sb_wrap(&sb, wrap);
148  emulated_edge_no_wrap(lc, dst, src, src_stride,
149  x_off + wrap, y_off, block_w, block_h, extra_before, extra_after, &subpic, &sb, dmvr_clip);
150  return;
151  }
152  if (dmvr_left >= pic_width) {
153  sb_wrap(&sb, -wrap);
154  emulated_edge_no_wrap(lc, dst, src, src_stride,
155  x_off - wrap, y_off, block_w, block_h, extra_before, extra_after, &subpic, &sb, dmvr_clip);
156  return;
157  }
158 
159  block_w += extra;
160  block_h += extra;
161 
162  // half block are wrapped
163  if (dmvr_left < 0 ) {
164  const int w = -left;
165  VVCRect half_sb = { sb.l + wrap, sb.t, 0 + wrap, sb.b };
166  emulated_half(lc, dst, dst_stride, *src, *src_stride, ps,
167  left + wrap, top, w, block_h, &subpic, &half_sb, dmvr_clip);
168 
169  sb_set_lr(&half_sb, 0, sb.r);
170  emulated_half(lc, dst + (w << ps), dst_stride, *src, *src_stride, ps,
171  0, top, block_w - w, block_h, &subpic, &half_sb, dmvr_clip);
172  } else {
173  const int w = pic_width - left;
174  VVCRect half_sb = { sb.l, sb.t, pic_width, sb.b };
175  emulated_half(lc, dst, dst_stride, *src, *src_stride, ps,
176  left, top, w, block_h, &subpic, &half_sb, dmvr_clip);
177 
178  sb_set_lr(&half_sb, pic_width - wrap, sb.r - wrap);
179  emulated_half(lc, dst + (w << ps), dst_stride, *src, *src_stride, ps,
180  pic_width - wrap , top, block_w - w, block_h, &subpic, &half_sb, dmvr_clip);
181  }
182 
183  *src = dst + extra_before * dst_stride + (extra_before << ps);
184  *src_stride = dst_stride;
185 }
186 
187 #define MC_EMULATED_EDGE(dst, src, src_stride, x_off, y_off) \
188  emulated_edge(lc, dst, src, src_stride, ref, x_off, y_off, x_off, y_off, block_w, block_h, wrap_enabled, is_chroma, \
189  is_chroma ? CHROMA_EXTRA_BEFORE : LUMA_EXTRA_BEFORE, is_chroma ? CHROMA_EXTRA_AFTER : LUMA_EXTRA_AFTER)
190 
191 #define MC_EMULATED_EDGE_DMVR(dst, src, src_stride, x_sb, y_sb, x_off, y_off) \
192  emulated_edge(lc, dst, src, src_stride, ref, x_sb, y_sb, x_off, y_off, block_w, block_h, wrap_enabled, is_chroma, \
193  is_chroma ? CHROMA_EXTRA_BEFORE : LUMA_EXTRA_BEFORE, is_chroma ? CHROMA_EXTRA_AFTER : LUMA_EXTRA_AFTER)
194 
195 #define MC_EMULATED_EDGE_BILINEAR(dst, src, src_stride, x_off, y_off) \
196  emulated_edge(lc, dst, src, src_stride, ref, x_off, y_off, x_off, y_off, pred_w, pred_h, wrap_enabled, 0, \
197  BILINEAR_EXTRA_BEFORE, BILINEAR_EXTRA_AFTER)
198 
199 // part of 8.5.6.6 Weighted sample prediction process
200 static int derive_weight_uni(int *denom, int *wx, int *ox,
201  const VVCLocalContext *lc, const MvField *mvf, const int c_idx)
202 {
203  const VVCFrameContext *fc = lc->fc;
204  const VVCPPS *pps = fc->ps.pps;
205  const VVCSH *sh = &lc->sc->sh;
206  const int weight_flag = (IS_P(sh->r) && pps->r->pps_weighted_pred_flag) ||
207  (IS_B(sh->r) && pps->r->pps_weighted_bipred_flag);
208  if (weight_flag) {
209  const int lx = mvf->pred_flag - PF_L0;
210  const PredWeightTable *w = pps->r->pps_wp_info_in_ph_flag ? &fc->ps.ph.pwt : &sh->pwt;
211 
212  *denom = w->log2_denom[c_idx > 0];
213  *wx = w->weight[lx][c_idx][mvf->ref_idx[lx]];
214  *ox = w->offset[lx][c_idx][mvf->ref_idx[lx]];
215  }
216  return weight_flag;
217 }
218 
219 // part of 8.5.6.6 Weighted sample prediction process
220 static int derive_weight(int *denom, int *w0, int *w1, int *o0, int *o1,
221  const VVCLocalContext *lc, const MvField *mvf, const int c_idx, const int dmvr_flag)
222 {
223  const VVCFrameContext *fc = lc->fc;
224  const VVCPPS *pps = fc->ps.pps;
225  const VVCSH *sh = &lc->sc->sh;
226  const int bcw_idx = mvf->bcw_idx;
227  const int weight_flag = (IS_P(sh->r) && pps->r->pps_weighted_pred_flag) ||
228  (IS_B(sh->r) && pps->r->pps_weighted_bipred_flag && !dmvr_flag);
229  if ((!weight_flag && !bcw_idx) || (bcw_idx && lc->cu->ciip_flag))
230  return 0;
231 
232  if (bcw_idx) {
233  *denom = 2;
234  *w1 = bcw_w_lut[bcw_idx];
235  *w0 = 8 - *w1;
236  *o0 = *o1 = 0;
237  } else {
238  const VVCPPS *pps = fc->ps.pps;
239  const PredWeightTable *w = pps->r->pps_wp_info_in_ph_flag ? &fc->ps.ph.pwt : &sh->pwt;
240 
241  *denom = w->log2_denom[c_idx > 0];
242  *w0 = w->weight[L0][c_idx][mvf->ref_idx[L0]];
243  *w1 = w->weight[L1][c_idx][mvf->ref_idx[L1]];
244  *o0 = w->offset[L0][c_idx][mvf->ref_idx[L0]];
245  *o1 = w->offset[L1][c_idx][mvf->ref_idx[L1]];
246  }
247  return 1;
248 }
249 
250 #define INTER_FILTER(t, frac) (is_chroma ? ff_vvc_inter_chroma_filters[t][frac] : ff_vvc_inter_luma_filters[t][frac])
251 
252 static void mc(VVCLocalContext *lc, int16_t *dst, const VVCFrame *ref, const Mv *mv,
253  int x_off, int y_off, const int block_w, const int block_h, const int c_idx)
254 {
255  const VVCFrameContext *fc = lc->fc;
256  const PredictionUnit *pu = &lc->cu->pu;
257  const uint8_t *src = ref->frame->data[c_idx];
258  ptrdiff_t src_stride = ref->frame->linesize[c_idx];
259  const int is_chroma = !!c_idx;
260  const int hs = fc->ps.sps->hshift[c_idx];
261  const int vs = fc->ps.sps->vshift[c_idx];
262  const int idx = av_log2(block_w) - 1;
263  const intptr_t mx = av_zero_extend(mv->x, 4 + hs) << (is_chroma - hs);
264  const intptr_t my = av_zero_extend(mv->y, 4 + vs) << (is_chroma - vs);
265  const int hpel_if_idx = (is_chroma || pu->merge_gpm_flag) ? 0 : pu->mi.hpel_if_idx;
266  const int8_t *hf = INTER_FILTER(hpel_if_idx, mx);
267  const int8_t *vf = INTER_FILTER(hpel_if_idx, my);
268  const int wrap_enabled = fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
269 
270  x_off += mv->x >> (4 + hs);
271  y_off += mv->y >> (4 + vs);
272 
273  MC_EMULATED_EDGE(lc->edge_emu_buffer, &src, &src_stride, x_off, y_off);
274  fc->vvcdsp.inter.put[is_chroma][idx][!!my][!!mx](dst, src, src_stride, block_h, hf, vf, block_w);
275 }
276 
277 static void mc_uni(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride,
278  const VVCFrame *ref, const MvField *mvf, int x_off, int y_off, const int block_w, const int block_h,
279  const int c_idx)
280 {
281  const VVCFrameContext *fc = lc->fc;
282  const PredictionUnit *pu = &lc->cu->pu;
283  const uint8_t *src = ref->frame->data[c_idx];
284  ptrdiff_t src_stride = ref->frame->linesize[c_idx];
285  const int lx = mvf->pred_flag - PF_L0;
286  const int hs = fc->ps.sps->hshift[c_idx];
287  const int vs = fc->ps.sps->vshift[c_idx];
288  const int idx = av_log2(block_w) - 1;
289  const Mv *mv = &mvf->mv[lx];
290  const int is_chroma = !!c_idx;
291  const intptr_t mx = av_zero_extend(mv->x, 4 + hs) << (is_chroma - hs);
292  const intptr_t my = av_zero_extend(mv->y, 4 + vs) << (is_chroma - vs);
293  const int hpel_if_idx = is_chroma ? 0 : pu->mi.hpel_if_idx;
294  const int8_t *hf = INTER_FILTER(hpel_if_idx, mx);
295  const int8_t *vf = INTER_FILTER(hpel_if_idx, my);
296  const int wrap_enabled = fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
297  int denom, wx, ox;
298 
299  x_off += mv->x >> (4 + hs);
300  y_off += mv->y >> (4 + vs);
301 
302  MC_EMULATED_EDGE(lc->edge_emu_buffer, &src, &src_stride, x_off, y_off);
303  if (derive_weight_uni(&denom, &wx, &ox, lc, mvf, c_idx)) {
304  fc->vvcdsp.inter.put_uni_w[is_chroma][idx][!!my][!!mx](dst, dst_stride, src, src_stride,
305  block_h, denom, wx, ox, hf, vf, block_w);
306  } else {
307  fc->vvcdsp.inter.put_uni[is_chroma][idx][!!my][!!mx](dst, dst_stride, src, src_stride,
308  block_h, hf, vf, block_w);
309  }
310 }
311 
312 static void mc_bi(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride,
313  const VVCFrame *ref0, const VVCFrame *ref1, const MvField *mvf, const MvField *orig_mv,
314  const int x_off, const int y_off, const int block_w, const int block_h, const int c_idx,
315  const int sb_bdof_flag)
316 {
317  const VVCFrameContext *fc = lc->fc;
318  const PredictionUnit *pu = &lc->cu->pu;
319  const int hs = fc->ps.sps->hshift[c_idx];
320  const int vs = fc->ps.sps->vshift[c_idx];
321  const int idx = av_log2(block_w) - 1;
322  const VVCFrame *refs[] = { ref0, ref1 };
323  int16_t *tmp[] = { lc->tmp + sb_bdof_flag * PROF_TEMP_OFFSET, lc->tmp1 + sb_bdof_flag * PROF_TEMP_OFFSET };
324  int denom, w0, w1, o0, o1;
325  const int weight_flag = derive_weight(&denom, &w0, &w1, &o0, &o1, lc, mvf, c_idx, pu->dmvr_flag);
326  const int is_chroma = !!c_idx;
327  const int hpel_if_idx = is_chroma ? 0 : pu->mi.hpel_if_idx;
328 
329  for (int i = L0; i <= L1; i++) {
330  const Mv *mv = mvf->mv + i;
331  const int mx = av_zero_extend(mv->x, 4 + hs) << (is_chroma - hs);
332  const int my = av_zero_extend(mv->y, 4 + vs) << (is_chroma - vs);
333  const int ox = x_off + (mv->x >> (4 + hs));
334  const int oy = y_off + (mv->y >> (4 + vs));
335  const VVCFrame *ref = refs[i];
336  ptrdiff_t src_stride = ref->frame->linesize[c_idx];
337  const uint8_t *src = ref->frame->data[c_idx];
338  const int8_t *hf = INTER_FILTER(hpel_if_idx, mx);
339  const int8_t *vf = INTER_FILTER(hpel_if_idx, my);
340  const int wrap_enabled = fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
341 
342  if (pu->dmvr_flag) {
343  const int x_sb = x_off + (orig_mv->mv[i].x >> (4 + hs));
344  const int y_sb = y_off + (orig_mv->mv[i].y >> (4 + vs));
345 
346  MC_EMULATED_EDGE_DMVR(lc->edge_emu_buffer, &src, &src_stride, x_sb, y_sb, ox, oy);
347  } else {
348  MC_EMULATED_EDGE(lc->edge_emu_buffer, &src, &src_stride, ox, oy);
349  }
350  fc->vvcdsp.inter.put[is_chroma][idx][!!my][!!mx](tmp[i], src, src_stride, block_h, hf, vf, block_w);
351  if (sb_bdof_flag)
352  fc->vvcdsp.inter.bdof_fetch_samples(tmp[i], src, src_stride, mx, my, block_w, block_h);
353  }
354  if (sb_bdof_flag)
355  fc->vvcdsp.inter.apply_bdof(dst, dst_stride, tmp[L0], tmp[L1], block_w, block_h);
356  else if (weight_flag)
357  fc->vvcdsp.inter.w_avg(dst, dst_stride, tmp[L0], tmp[L1], block_w, block_h, denom, w0, w1, o0, o1);
358  else
359  fc->vvcdsp.inter.avg(dst, dst_stride, tmp[L0], tmp[L1], block_w, block_h);
360 }
361 
362 static const int8_t* inter_filter_scaled(const int scale, const int is_chroma, const int is_affine)
363 {
364 #define SCALE_THRESHOLD_1 20480
365 #define SCALE_THRESHOLD_2 28672
366 
367  const int i = (scale > SCALE_THRESHOLD_2) + (scale > SCALE_THRESHOLD_1);
368 
369  if (!is_chroma) {
370  if (!is_affine)
371  return &ff_vvc_inter_luma_filters[i + !!i][0][0]; //hpel 1 is not needed for scaled
373  }
374 
375  return &ff_vvc_inter_chroma_filters[i][0][0];
376 }
377 #define INTER_FILTER_SCALED(scale) inter_filter_scaled(scale, is_chroma, is_affine)
378 
379 #define SCALED_CHROMA_ADDIN(scale, collocated_flag) (is_chroma ? (collocated_flag ? 0 : 8 * (scale - (1 << 14))) : 0)
380 #define SCALED_REF_SB(off, scaling_off, ref_mv, scale, add, shift) ((((off - (scaling_off << shift)) << (4 + shift)) + ref_mv) * scale + add)
381 #define SCALED_REF(ref_sb, offset, shift) (FFSIGN(ref_sb) * ((FFABS(ref_sb) + (128 << is_chroma)) >> (8 + is_chroma)) + (offset << (10 - shift)) + (32 >> is_chroma))
382 #define SCALED_STEP(scale) ((scale + 8) >> 4)
383 
384 static void scaled_ref_pos_and_step(const VVCLocalContext *lc, const VVCRefPic *refp, const Mv *mv, const int x_off, const int y_off, const int c_idx,
385  int *x, int *y, int *dx, int *dy)
386 {
387  const VVCFrameContext *fc = lc->fc;
388  const VVCSPS *sps = fc->ps.sps;
389  const int is_chroma = !!c_idx;
390  const int hs = sps->hshift[c_idx];
391  const int vs = sps->vshift[c_idx];
392  const int left_offset = fc->ref->scaling_win.left_offset;
393  const int top_offset = fc->ref->scaling_win.top_offset;
394  const int addx = SCALED_CHROMA_ADDIN(refp->scale[0], sps->r->sps_chroma_horizontal_collocated_flag);
395  const int addy = SCALED_CHROMA_ADDIN(refp->scale[1], sps->r->sps_chroma_vertical_collocated_flag);
396  const int refx_sb = SCALED_REF_SB(x_off, left_offset, mv->x, refp->scale[0], addx, hs);
397  const int refy_sb = SCALED_REF_SB(y_off, top_offset, mv->y, refp->scale[1], addy, vs);
398 
399  *x = SCALED_REF(refx_sb, left_offset, hs);
400  *y = SCALED_REF(refy_sb, top_offset, vs);
401  *dx = SCALED_STEP(refp->scale[0]);
402  *dy = SCALED_STEP(refp->scale[1]);
403 }
404 
405 static void emulated_edge_scaled(VVCLocalContext *lc, const uint8_t **src, ptrdiff_t *src_stride, int *src_height,
406  const VVCFrame *ref, const int x, const int y, const int dx, const int dy, const int w, const int h, const int is_chroma)
407 {
408  const int x_off = SCALED_INT(x);
409  const int y_off = SCALED_INT(y);
410  const int x_end = SCALED_INT(x + w * dx);
411  const int y_end = SCALED_INT(y + h * dy);
412  const int x_last = SCALED_INT(x + (w - 1) * dx);
413  const int y_last = SCALED_INT(y + (h - 1) * dy);
414  const int block_w = x_end - x_off + (x_end == x_last);
415  const int block_h = *src_height = y_end - y_off + (y_end == y_last);
416  const int wrap_enabled = 0;
417 
418  MC_EMULATED_EDGE(lc->edge_emu_buffer, src, src_stride, x_off, y_off);
419 }
420 
421 static void mc_scaled(VVCLocalContext *lc, int16_t *dst, const VVCRefPic *refp, const Mv *mv,
422  int x_off, int y_off, const int block_w, const int block_h, const int c_idx)
423 {
424  const VVCFrameContext *fc = lc->fc;
425  const PredictionUnit *pu = &lc->cu->pu;
426  const uint8_t *src = refp->ref->frame->data[c_idx];
427  ptrdiff_t src_stride = refp->ref->frame->linesize[c_idx];
428  const int is_affine = pu->inter_affine_flag;
429  const int is_chroma = !!c_idx;
430  const int idx = av_log2(block_w) - 1;
431  const int8_t *hf = INTER_FILTER_SCALED(refp->scale[0]);
432  const int8_t *vf = INTER_FILTER_SCALED(refp->scale[1]);
433  int x, y, dx, dy, src_height;
434 
435  scaled_ref_pos_and_step(lc, refp, mv, x_off, y_off, c_idx, &x, &y, &dx, &dy);
436  emulated_edge_scaled(lc, &src, &src_stride, &src_height, refp->ref, x, y, dx, dy, block_w, block_h, is_chroma);
437  fc->vvcdsp.inter.put_scaled[is_chroma][idx](dst, src, src_stride, src_height, x, y, dx, dy, block_h, hf, vf, block_w);
438 }
439 
440 static void mc_uni_scaled(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCRefPic *refp,
441  const MvField *mvf, const int x_off, const int y_off, const int block_w, const int block_h, const int c_idx)
442 {
443  const VVCFrameContext *fc = lc->fc;
444  const PredictionUnit *pu = &lc->cu->pu;
445  const uint8_t *src = refp->ref->frame->data[c_idx];
446  ptrdiff_t src_stride = refp->ref->frame->linesize[c_idx];
447  const int lx = mvf->pred_flag - PF_L0;
448  const Mv *mv = &mvf->mv[lx];
449  const int is_affine = pu->inter_affine_flag;
450  const int is_chroma = !!c_idx;
451  const int idx = av_log2(block_w) - 1;
452  const int8_t *hf = INTER_FILTER_SCALED(refp->scale[0]);
453  const int8_t *vf = INTER_FILTER_SCALED(refp->scale[1]);
454  int denom, wx, ox, x, y, dx, dy, src_height;
455 
456  scaled_ref_pos_and_step(lc, refp, mv, x_off, y_off, c_idx, &x, &y, &dx, &dy);
457  emulated_edge_scaled(lc, &src, &src_stride, &src_height, refp->ref, x, y, dx, dy, block_w, block_h, is_chroma);
458 
459  if (derive_weight_uni(&denom, &wx, &ox, lc, mvf, c_idx)) {
460  fc->vvcdsp.inter.put_uni_w_scaled[is_chroma][idx](dst, dst_stride, src, src_stride, src_height,
461  x, y, dx, dy, block_h, denom, wx, ox, hf, vf, block_w);
462  } else {
463  fc->vvcdsp.inter.put_uni_scaled[is_chroma][idx](dst, dst_stride, src, src_stride, src_height,
464  x, y, dx, dy, block_h, hf, vf, block_w);
465  }
466 }
467 
468 static void mc_bi_scaled(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride,
469  const VVCRefPic *refp0, const VVCRefPic *refp1, const MvField *mvf,
470  const int x_off, const int y_off, const int block_w, const int block_h, const int c_idx)
471 {
472  int denom, w0, w1, o0, o1;
473  const VVCFrameContext *fc = lc->fc;
474  const int weight_flag = derive_weight(&denom, &w0, &w1, &o0, &o1, lc, mvf, c_idx, lc->cu->pu.dmvr_flag);
475  const VVCRefPic *refps[] = { refp0, refp1 };
476  int16_t *tmp[] = { lc->tmp, lc->tmp1 };
477 
478  for (int i = L0; i <= L1; i++) {
479  const Mv *mv = mvf->mv + i;
480  const VVCRefPic *refp = refps[i];
481 
482  if (refp->is_scaled)
483  mc_scaled(lc, tmp[i], refp, mv, x_off, y_off, block_w, block_h, c_idx);
484  else
485  mc(lc, tmp[i], refp->ref, mv, x_off, y_off, block_w, block_h, c_idx);
486  }
487  if (weight_flag)
488  fc->vvcdsp.inter.w_avg(dst, dst_stride, tmp[L0], tmp[L1], block_w, block_h, denom, w0, w1, o0, o1);
489  else
490  fc->vvcdsp.inter.avg(dst, dst_stride, tmp[L0], tmp[L1], block_w, block_h);
491 }
492 
493 static void luma_prof_uni(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride,
494  const VVCFrame *ref, const MvField *mvf, int x_off, int y_off, const int block_w, const int block_h,
495  const int cb_prof_flag, const int16_t *diff_mv_x, const int16_t *diff_mv_y)
496 {
497  const VVCFrameContext *fc = lc->fc;
498  const uint8_t *src = ref->frame->data[LUMA];
499  ptrdiff_t src_stride = ref->frame->linesize[LUMA];
500  uint16_t *prof_tmp = lc->tmp + PROF_TEMP_OFFSET;
501  const int idx = av_log2(block_w) - 1;
502  const int lx = mvf->pred_flag - PF_L0;
503  const Mv *mv = mvf->mv + lx;
504  const int mx = mv->x & 0xf;
505  const int my = mv->y & 0xf;
508  int denom, wx, ox;
509  const int weight_flag = derive_weight_uni(&denom, &wx, &ox, lc, mvf, LUMA);
510  const int wrap_enabled = fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
511  const int is_chroma = 0;
512 
513  x_off += mv->x >> 4;
514  y_off += mv->y >> 4;
515 
516  MC_EMULATED_EDGE(lc->edge_emu_buffer, &src, &src_stride, x_off, y_off);
517  if (cb_prof_flag) {
518  fc->vvcdsp.inter.put[LUMA][idx][!!my][!!mx](prof_tmp, src, src_stride, AFFINE_MIN_BLOCK_SIZE, hf, vf, AFFINE_MIN_BLOCK_SIZE);
519  fc->vvcdsp.inter.fetch_samples(prof_tmp, src, src_stride, mx, my);
520  if (!weight_flag)
521  fc->vvcdsp.inter.apply_prof_uni(dst, dst_stride, prof_tmp, diff_mv_x, diff_mv_y);
522  else
523  fc->vvcdsp.inter.apply_prof_uni_w(dst, dst_stride, prof_tmp, diff_mv_x, diff_mv_y, denom, wx, ox);
524  } else {
525  if (!weight_flag)
526  fc->vvcdsp.inter.put_uni[LUMA][idx][!!my][!!mx](dst, dst_stride, src, src_stride, block_h, hf, vf, block_w);
527  else
528  fc->vvcdsp.inter.put_uni_w[LUMA][idx][!!my][!!mx](dst, dst_stride, src, src_stride, block_h, denom, wx, ox, hf, vf, block_w);
529  }
530 }
531 
532 static void luma_prof(VVCLocalContext *lc, int16_t *dst, const VVCFrame *ref,
533  const Mv *mv , const int x_off, const int y_off, const int block_w, const int block_h, const int lx)
534 {
535  const VVCFrameContext *fc = lc->fc;
536  const PredictionUnit *pu = &lc->cu->pu;
537  const int mx = mv->x & 0xf;
538  const int my = mv->y & 0xf;
539  const int ox = x_off + (mv->x >> 4);
540  const int oy = y_off + (mv->y >> 4);
541  const int idx = av_log2(block_w) - 1;
542  const int is_chroma = 0;
543  uint16_t *prof_tmp = lc->tmp2 + PROF_TEMP_OFFSET;
544  ptrdiff_t src_stride = ref->frame->linesize[LUMA];
545  const uint8_t *src = ref->frame->data[LUMA];
548  const int wrap_enabled = fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
549 
550  MC_EMULATED_EDGE(lc->edge_emu_buffer, &src, &src_stride, ox, oy);
551  if (!pu->cb_prof_flag[lx]) {
552  fc->vvcdsp.inter.put[LUMA][idx][!!my][!!mx](dst, src, src_stride, block_h, hf, vf, block_w);
553  } else {
554  fc->vvcdsp.inter.put[LUMA][idx][!!my][!!mx](prof_tmp, src, src_stride, AFFINE_MIN_BLOCK_SIZE, hf, vf, AFFINE_MIN_BLOCK_SIZE);
555  fc->vvcdsp.inter.fetch_samples(prof_tmp, src, src_stride, mx, my);
556  fc->vvcdsp.inter.apply_prof(dst, prof_tmp, pu->diff_mv_x[lx], pu->diff_mv_y[lx]);
557  }
558 }
559 
560 static void luma_prof_bi(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride,
561  const VVCRefPic *ref0, const VVCRefPic *ref1, const MvField *mvf, const int x_off, const int y_off,
562  const int block_w, const int block_h)
563 {
564  const VVCFrameContext *fc = lc->fc;
565  const VVCRefPic *refps[] = { ref0, ref1 };
566  int16_t *tmp[] = { lc->tmp, lc->tmp1 };
567  int denom, w0, w1, o0, o1;
568  const int weight_flag = derive_weight(&denom, &w0, &w1, &o0, &o1, lc, mvf, LUMA, 0);
569 
570  for (int i = L0; i <= L1; i++) {
571  const VVCRefPic *refp = refps[i];
572  const Mv *mv = mvf->mv + i;
573 
574  if (refp->is_scaled)
575  mc_scaled(lc, tmp[i], refp, mv, x_off, y_off, block_w, block_h, LUMA);
576  else
577  luma_prof(lc, tmp[i], refp->ref, mv, x_off, y_off, block_w, block_h, i);
578  }
579 
580  if (weight_flag)
581  fc->vvcdsp.inter.w_avg(dst, dst_stride, tmp[L0], tmp[L1], block_w, block_h, denom, w0, w1, o0, o1);
582  else
583  fc->vvcdsp.inter.avg(dst, dst_stride, tmp[L0], tmp[L1], block_w, block_h);
584 }
585 
586 static int pred_get_refs(const VVCLocalContext *lc, VVCRefPic *refp[2], const MvField *mv)
587 {
588  RefPicList *rpl = lc->sc->rpl;
589 
590  for (int mask = PF_L0; mask <= PF_L1; mask++) {
591  if (mv->pred_flag & mask) {
592  const int lx = mask - PF_L0;
593  refp[lx] = rpl[lx].refs + mv->ref_idx[lx];
594  if (!refp[lx]->ref)
595  return AVERROR_INVALIDDATA;
596  }
597  }
598  return 0;
599 }
600 
601 #define POS(c_idx, x, y) \
602  &fc->frame->data[c_idx][((y) >> fc->ps.sps->vshift[c_idx]) * fc->frame->linesize[c_idx] + \
603  (((x) >> fc->ps.sps->hshift[c_idx]) << fc->ps.sps->pixel_shift)]
604 
606 {
607  const VVCFrameContext *fc = lc->fc;
608  const CodingUnit *cu = lc->cu;
609  const PredictionUnit *pu = &cu->pu;
610 
611  const uint8_t angle_idx = ff_vvc_gpm_angle_idx[pu->gpm_partition_idx];
612  const uint8_t weights_idx = ff_vvc_gpm_angle_to_weights_idx[angle_idx];
613  const int w = av_log2(cu->cb_width) - 3;
614  const int h = av_log2(cu->cb_height) - 3;
615  const uint8_t off_x = ff_vvc_gpm_weights_offset_x[pu->gpm_partition_idx][h][w];
616  const uint8_t off_y = ff_vvc_gpm_weights_offset_y[pu->gpm_partition_idx][h][w];
617  const uint8_t mirror_type = ff_vvc_gpm_angle_to_mirror[angle_idx];
618  const uint8_t *weights;
619 
620  const int c_end = fc->ps.sps->r->sps_chroma_format_idc ? 3 : 1;
621 
622  int16_t *tmp[2] = {lc->tmp, lc->tmp1};
623 
624  for (int c_idx = 0; c_idx < c_end; c_idx++) {
625  const int hs = fc->ps.sps->hshift[c_idx];
626  const int vs = fc->ps.sps->vshift[c_idx];
627  const int x = lc->cu->x0 >> hs;
628  const int y = lc->cu->y0 >> vs;
629  const int width = cu->cb_width >> hs;
630  const int height = cu->cb_height >> vs;
631  uint8_t *dst = POS(c_idx, lc->cu->x0, lc->cu->y0);
632  ptrdiff_t dst_stride = fc->frame->linesize[c_idx];
633 
634  int step_x = 1 << hs;
635  int step_y = VVC_GPM_WEIGHT_SIZE << vs;
636  if (!mirror_type) {
637  weights = &ff_vvc_gpm_weights[weights_idx][off_y * VVC_GPM_WEIGHT_SIZE + off_x];
638  } else if (mirror_type == 1) {
639  step_x = -step_x;
640  weights = &ff_vvc_gpm_weights[weights_idx][off_y * VVC_GPM_WEIGHT_SIZE + VVC_GPM_WEIGHT_SIZE - 1- off_x];
641  } else {
642  step_y = -step_y;
643  weights = &ff_vvc_gpm_weights[weights_idx][(VVC_GPM_WEIGHT_SIZE - 1 - off_y) * VVC_GPM_WEIGHT_SIZE + off_x];
644  }
645 
646  for (int i = 0; i < 2; i++) {
647  const MvField *mv = pu->gpm_mv + i;
648  const int lx = mv->pred_flag - PF_L0;
649  VVCRefPic *refp = lc->sc->rpl[lx].refs + mv->ref_idx[lx];
650 
651  if (!refp->ref)
652  return;
653  if (refp->is_scaled)
654  mc_scaled(lc, tmp[i], refp, mv->mv + lx, x, y, width, height, c_idx);
655  else
656  mc(lc, tmp[i], refp->ref, mv->mv + lx, x, y, width, height, c_idx);
657  }
658  fc->vvcdsp.inter.put_gpm(dst, dst_stride, width, height, tmp[0], tmp[1], weights, step_x, step_y);
659  }
660  return;
661 }
662 
663 static int ciip_derive_intra_weight(const VVCLocalContext *lc, const int x0, const int y0,
664  const int width, const int height)
665 {
666  const VVCFrameContext *fc = lc->fc;
667  const VVCSPS *sps = fc->ps.sps;
668  const int x0b = av_zero_extend(x0, sps->ctb_log2_size_y);
669  const int y0b = av_zero_extend(y0, sps->ctb_log2_size_y);
670  const int available_l = lc->ctb_left_flag || x0b;
671  const int available_u = lc->ctb_up_flag || y0b;
672  const int min_pu_width = fc->ps.pps->min_pu_width;
673  int w = 1;
674 
675  if (available_u &&fc->tab.mvf[((y0 - 1) >> MIN_PU_LOG2) * min_pu_width + ((x0 - 1 + width)>> MIN_PU_LOG2)].pred_flag == PF_INTRA)
676  w++;
677 
678  if (available_l && fc->tab.mvf[((y0 - 1 + height)>> MIN_PU_LOG2) * min_pu_width + ((x0 - 1) >> MIN_PU_LOG2)].pred_flag == PF_INTRA)
679  w++;
680 
681  return w;
682 }
683 
684 static void pred_regular(VVCLocalContext *lc, const MvField *mvf, const MvField *orig_mvf,
685  const int x0, const int y0, const int sbw, const int sbh, const int sb_bdof_flag, const int c_start)
686 {
687  const VVCFrameContext *fc = lc->fc;
688  const int c_end = fc->ps.sps->r->sps_chroma_format_idc ? CR : LUMA;
689  VVCRefPic *refp[2];
690 
691  if (pred_get_refs(lc, refp, mvf) < 0)
692  return;
693 
694  for (int c_idx = c_start; c_idx <= c_end; c_idx++) {
695  uint8_t *dst = POS(c_idx, x0, y0);
696  const ptrdiff_t dst_stride = fc->frame->linesize[c_idx];
697  const int hs = fc->ps.sps->hshift[c_idx];
698  const int vs = fc->ps.sps->vshift[c_idx];
699  const int x = x0 >> hs;
700  const int y = y0 >> vs;
701  const int w = sbw >> hs;
702  const int h = sbh >> vs;
703  const int is_luma = !c_idx;
704  const int do_ciip = lc->cu->ciip_flag && (is_luma || (w > 2));
705  uint8_t *inter = do_ciip ? (uint8_t *)lc->ciip_tmp : dst;
706  const ptrdiff_t inter_stride = do_ciip ? (MAX_PB_SIZE * sizeof(uint16_t)) : dst_stride;
707  const int do_bdof = is_luma && sb_bdof_flag;
708 
709  if (mvf->pred_flag != PF_BI) {
710  const int lx = mvf->pred_flag - PF_L0;
711 
712  if (refp[lx]->is_scaled) {
713  mc_uni_scaled(lc, inter, inter_stride, refp[lx], mvf,
714  x, y, w, h, c_idx);
715  } else {
716  mc_uni(lc, inter, inter_stride, refp[lx]->ref, mvf,
717  x, y, w, h, c_idx);
718  }
719  } else {
720  if (refp[L0]->is_scaled || refp[L1]->is_scaled) {
721  mc_bi_scaled(lc, inter, inter_stride, refp[L0], refp[L1], mvf,
722  x, y, w, h, c_idx);
723  } else {
724  mc_bi(lc, inter, inter_stride, refp[L0]->ref, refp[L1]->ref, mvf, orig_mvf,
725  x, y, w, h, c_idx, do_bdof);
726  }
727  }
728  if (do_ciip) {
729  const int intra_weight = ciip_derive_intra_weight(lc, x0, y0, sbw, sbh);
730  fc->vvcdsp.intra.intra_pred(lc, x0, y0, sbw, sbh, c_idx);
731  if (!c_idx && lc->sc->sh.r->sh_lmcs_used_flag)
732  fc->vvcdsp.lmcs.filter(inter, inter_stride, w, h, &fc->ps.lmcs.fwd_lut);
733  fc->vvcdsp.inter.put_ciip(dst, dst_stride, w, h, inter, inter_stride, intra_weight);
734  }
735  }
736 }
737 
738 // 8.5.3.5 Parametric motion vector refinement process
739 static int parametric_mv_refine(const int *sad, const int stride)
740 {
741  const int sad_minus = sad[-stride];
742  const int sad_center = sad[0];
743  const int sad_plus = sad[stride];
744  int dmvc;
745  int denom = (( sad_minus + sad_plus) - (sad_center << 1 ) ) << 3;
746  if (!denom)
747  dmvc = 0;
748  else {
749  if (sad_minus == sad_center)
750  dmvc = -8;
751  else if (sad_plus == sad_center)
752  dmvc = 8;
753  else {
754  int num = ( sad_minus - sad_plus ) * (1 << 4);
755  int sign_num = 0;
756  int quotient = 0;
757  int counter = 3;
758  if (num < 0 ) {
759  num = - num;
760  sign_num = 1;
761  }
762  while (counter > 0) {
763  counter = counter - 1;
764  quotient = quotient << 1;
765  if ( num >= denom ) {
766  num = num - denom;
767  quotient = quotient + 1;
768  }
769  denom = (denom >> 1);
770  }
771  if (sign_num == 1 )
772  dmvc = -quotient;
773  else
774  dmvc = quotient;
775  }
776  }
777  return dmvc;
778 }
779 
780 #define SAD_ARRAY_SIZE 5
781 //8.5.3 Decoder-side motion vector refinement process
782 static void dmvr_mv_refine(VVCLocalContext *lc, MvField *mvf, MvField *orig_mv, int *sb_bdof_flag,
783  const VVCFrame *ref0, const VVCFrame *ref1, const int x_off, const int y_off, const int block_w, const int block_h)
784 {
785  const VVCFrameContext *fc = lc->fc;
786  const int sr_range = 2;
787  const VVCFrame *refs[] = { ref0, ref1 };
788  int16_t *tmp[] = { lc->tmp, lc->tmp1 };
789  int sad[SAD_ARRAY_SIZE][SAD_ARRAY_SIZE];
790  int min_dx, min_dy, min_sad, dx, dy;
791 
792  *orig_mv = *mvf;
793  min_dx = min_dy = dx = dy = 2;
794 
795  for (int i = L0; i <= L1; i++) {
796  const int pred_w = block_w + 2 * sr_range;
797  const int pred_h = block_h + 2 * sr_range;
798  const Mv *mv = mvf->mv + i;
799  const int mx = mv->x & 0xf;
800  const int my = mv->y & 0xf;
801  const int ox = x_off + (mv->x >> 4) - sr_range;
802  const int oy = y_off + (mv->y >> 4) - sr_range;
803  const VVCFrame *ref = refs[i];
804  ptrdiff_t src_stride = ref->frame->linesize[LUMA];
805  const uint8_t *src = ref->frame->data[LUMA];
806  const int wrap_enabled = fc->ps.pps->r->pps_ref_wraparound_enabled_flag;
807 
808  MC_EMULATED_EDGE_BILINEAR(lc->edge_emu_buffer, &src, &src_stride, ox, oy);
809  fc->vvcdsp.inter.dmvr[!!my][!!mx](tmp[i], src, src_stride, pred_h, mx, my, pred_w);
810  }
811 
812  min_sad = fc->vvcdsp.inter.sad(tmp[L0], tmp[L1], dx, dy, block_w, block_h);
813  min_sad -= min_sad >> 2;
814  sad[dy][dx] = min_sad;
815 
816  if (min_sad >= block_w * block_h) {
817  int dmv[2];
818  // 8.5.3.4 Array entry selection process
819  for (dy = 0; dy < SAD_ARRAY_SIZE; dy++) {
820  for (dx = 0; dx < SAD_ARRAY_SIZE; dx++) {
821  if (dx != sr_range || dy != sr_range) {
822  sad[dy][dx] = fc->vvcdsp.inter.sad(lc->tmp, lc->tmp1, dx, dy, block_w, block_h);
823  if (sad[dy][dx] < min_sad) {
824  min_sad = sad[dy][dx];
825  min_dx = dx;
826  min_dy = dy;
827  }
828  }
829  }
830  }
831  dmv[0] = (min_dx - sr_range) * (1 << 4);
832  dmv[1] = (min_dy - sr_range) * (1 << 4);
833  if (min_dx != 0 && min_dx != 4 && min_dy != 0 && min_dy != 4) {
834  dmv[0] += parametric_mv_refine(&sad[min_dy][min_dx], 1);
835  dmv[1] += parametric_mv_refine(&sad[min_dy][min_dx], SAD_ARRAY_SIZE);
836  }
837 
838  for (int i = L0; i <= L1; i++) {
839  Mv *mv = mvf->mv + i;
840  mv->x += (1 - 2 * i) * dmv[0];
841  mv->y += (1 - 2 * i) * dmv[1];
843  }
844  }
845  if (min_sad < 2 * block_w * block_h) {
846  *sb_bdof_flag = 0;
847  }
848 }
849 
850 static void set_dmvr_info(VVCFrameContext *fc, const int x0, const int y0,
851  const int width, const int height, const MvField *mvf)
852 
853 {
854  const VVCPPS *pps = fc->ps.pps;
855 
856  for (int y = y0; y < y0 + height; y += MIN_PU_SIZE) {
857  for (int x = x0; x < x0 + width; x += MIN_PU_SIZE) {
858  const int idx = pps->min_pu_width * (y >> MIN_PU_LOG2) + (x >> MIN_PU_LOG2);
859  fc->ref->tab_dmvr_mvf[idx] = *mvf;
860  }
861  }
862 }
863 
864 static void derive_sb_mv(VVCLocalContext *lc, MvField *mv, MvField *orig_mv, int *sb_bdof_flag,
865  const int x0, const int y0, const int sbw, const int sbh)
866 {
867  VVCFrameContext *fc = lc->fc;
868  const PredictionUnit *pu = &lc->cu->pu;
869 
870  *orig_mv = *mv = *ff_vvc_get_mvf(fc, x0, y0);
871  if (pu->bdof_flag)
872  *sb_bdof_flag = 1;
873  if (pu->dmvr_flag) {
874  VVCRefPic *refp[2];
875  if (pred_get_refs(lc, refp, mv) < 0)
876  return;
877  dmvr_mv_refine(lc, mv, orig_mv, sb_bdof_flag, refp[L0]->ref, refp[L1]->ref, x0, y0, sbw, sbh);
878  set_dmvr_info(fc, x0, y0, sbw, sbh, mv);
879  }
880 }
881 
882 static void pred_regular_blk(VVCLocalContext *lc, const int skip_ciip)
883 {
884  const CodingUnit *cu = lc->cu;
885  PredictionUnit *pu = &lc->cu->pu;
886  const MotionInfo *mi = &pu->mi;
887  MvField mv, orig_mv;
888  int sbw, sbh, sb_bdof_flag = 0;
889 
890  if (cu->ciip_flag && skip_ciip)
891  return;
892 
893  sbw = cu->cb_width / mi->num_sb_x;
894  sbh = cu->cb_height / mi->num_sb_y;
895 
896  for (int sby = 0; sby < mi->num_sb_y; sby++) {
897  for (int sbx = 0; sbx < mi->num_sb_x; sbx++) {
898  const int x0 = cu->x0 + sbx * sbw;
899  const int y0 = cu->y0 + sby * sbh;
900 
901  if (cu->ciip_flag)
902  ff_vvc_set_neighbour_available(lc, x0, y0, sbw, sbh);
903 
904  derive_sb_mv(lc, &mv, &orig_mv, &sb_bdof_flag, x0, y0, sbw, sbh);
905  pred_regular(lc, &mv, &orig_mv, x0, y0, sbw, sbh, sb_bdof_flag, LUMA);
906  }
907  }
908 }
909 
910 static void derive_affine_mvc(MvField *mvc, const VVCFrameContext *fc, const MvField *mv,
911  const int x0, const int y0, const int sbw, const int sbh)
912 {
913  const int hs = fc->ps.sps->hshift[1];
914  const int vs = fc->ps.sps->vshift[1];
915  const MvField* mv2 = ff_vvc_get_mvf(fc, x0 + hs * sbw, y0 + vs * sbh);
916  *mvc = *mv;
917 
918  // Due to different pred_flag, one of the motion vectors may have an invalid value.
919  // Cast them to an unsigned type to avoid undefined behavior.
920  mvc->mv[0].x += (unsigned int)mv2->mv[0].x;
921  mvc->mv[0].y += (unsigned int)mv2->mv[0].y;
922  mvc->mv[1].x += (unsigned int)mv2->mv[1].x;
923  mvc->mv[1].y += (unsigned int)mv2->mv[1].y;
924  ff_vvc_round_mv(mvc->mv + 0, 0, 1);
925  ff_vvc_round_mv(mvc->mv + 1, 0, 1);
926 }
927 
929 {
930  const VVCFrameContext *fc = lc->fc;
931  const CodingUnit *cu = lc->cu;
932  const PredictionUnit *pu = &cu->pu;
933  const MotionInfo *mi = &pu->mi;
934  const int x0 = cu->x0;
935  const int y0 = cu->y0;
936  const int sbw = cu->cb_width / mi->num_sb_x;
937  const int sbh = cu->cb_height / mi->num_sb_y;
938  const int hs = fc->ps.sps->hshift[1];
939  const int vs = fc->ps.sps->vshift[1];
940  const int dst_stride = fc->frame->linesize[LUMA];
941 
942  for (int sby = 0; sby < mi->num_sb_y; sby++) {
943  for (int sbx = 0; sbx < mi->num_sb_x; sbx++) {
944  const int x = x0 + sbx * sbw;
945  const int y = y0 + sby * sbh;
946 
947  uint8_t *dst0 = POS(0, x, y);
948  const MvField *mv = ff_vvc_get_mvf(fc, x, y);
949  VVCRefPic *refp[2];
950 
951  if (pred_get_refs(lc, refp, mv) < 0)
952  return;
953 
954  if (mi->pred_flag != PF_BI) {
955  const int lx = mi->pred_flag - PF_L0;
956  if (refp[lx]->is_scaled) {
957  mc_uni_scaled(lc, dst0, dst_stride, refp[lx], mv, x, y, sbw, sbh, LUMA);
958  } else {
959  luma_prof_uni(lc, dst0, dst_stride, refp[lx]->ref,
960  mv, x, y, sbw, sbh, pu->cb_prof_flag[lx],
961  pu->diff_mv_x[lx], pu->diff_mv_y[lx]);
962  }
963  } else {
964  luma_prof_bi(lc, dst0, dst_stride, refp[L0], refp[L1], mv, x, y, sbw, sbh);
965  }
966  if (fc->ps.sps->r->sps_chroma_format_idc) {
967  if (!av_zero_extend(sby, vs) && !av_zero_extend(sbx, hs)) {
968  MvField mvc;
969 
970  derive_affine_mvc(&mvc, fc, mv, x, y, sbw, sbh);
971  pred_regular(lc, &mvc, NULL, x, y, sbw << hs, sbh << vs, 0, CB);
972  }
973  }
974 
975  }
976  }
977 }
978 
980 {
981  const VVCFrameContext *fc = lc->fc;
982  const CodingUnit *cu = lc->cu;
983  const PredictionUnit *pu = &cu->pu;
984 
985  if (pu->merge_gpm_flag)
986  pred_gpm_blk(lc);
987  else if (pu->inter_affine_flag)
988  pred_affine_blk(lc);
989  else
990  pred_regular_blk(lc, 1); //intra block is not ready yet, skip ciip
991 
992  if (lc->sc->sh.r->sh_lmcs_used_flag && !cu->ciip_flag) {
993  uint8_t* dst0 = POS(0, cu->x0, cu->y0);
994  fc->vvcdsp.lmcs.filter(dst0, fc->frame->linesize[LUMA], cu->cb_width, cu->cb_height, &fc->ps.lmcs.fwd_lut);
995  }
996 }
997 
998 static int has_inter_luma(const CodingUnit *cu)
999 {
1000  return (cu->pred_mode == MODE_INTER || cu->pred_mode == MODE_SKIP) && cu->tree_type != DUAL_TREE_CHROMA;
1001 }
1002 
1004 {
1005  const VVCFrameContext *fc = lc->fc;
1006  CodingUnit *cu = fc->tab.cus[rs];
1007 
1008  while (cu) {
1009  lc->cu = cu;
1010  if (has_inter_luma(cu))
1011  predict_inter(lc);
1012  cu = cu->next;
1013  }
1014 
1015  return 0;
1016 }
1017 
1019 {
1020  av_assert0(lc->cu->ciip_flag);
1021 
1022  //todo: refact out ciip from pred_regular_blk
1023  pred_regular_blk(lc, 0);
1024 }
1025 
1026 #undef POS
set_dmvr_info
static void set_dmvr_info(VVCFrameContext *fc, const int x0, const int y0, const int width, const int height, const MvField *mvf)
Definition: inter.c:850
VVCSPS
Definition: ps.h:58
ff_vvc_inter_chroma_filters
const int8_t ff_vvc_inter_chroma_filters[VVC_INTER_CHROMA_FILTER_TYPES][VVC_INTER_CHROMA_FACTS][VVC_INTER_CHROMA_TAPS]
Definition: data.c:1877
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
emulated_edge
static void emulated_edge(const VVCLocalContext *lc, uint8_t *dst, const uint8_t **src, ptrdiff_t *src_stride, const VVCFrame *src_frame, int x_sb, int y_sb, int x_off, int y_off, int block_w, int block_h, const int wrap_enabled, const int is_chroma, const int extra_before, const int extra_after)
Definition: inter.c:118
ff_vvc_gpm_angle_to_mirror
const uint8_t ff_vvc_gpm_angle_to_mirror[VVC_GPM_NUM_ANGLES]
Definition: data.c:2095
VVCPPS
Definition: ps.h:92
r
const char * r
Definition: vf_curves.c:127
LUMA
#define LUMA
Definition: filter.c:31
VVCFrame::pps
const VVCPPS * pps
RefStruct reference.
Definition: dec.h:75
SCALE_THRESHOLD_1
#define SCALE_THRESHOLD_1
luma_prof
static void luma_prof(VVCLocalContext *lc, int16_t *dst, const VVCFrame *ref, const Mv *mv, const int x_off, const int y_off, const int block_w, const int block_h, const int lx)
Definition: inter.c:532
MotionInfo
Definition: ctu.h:242
CB
#define CB
Definition: filter.c:32
CodingUnit
Definition: hevcdec.h:288
mv
static const int8_t mv[256][2]
Definition: 4xm.c:81
PredictionUnit::gpm_partition_idx
uint8_t gpm_partition_idx
Definition: ctu.h:264
VVCLocalContext::tmp
int16_t tmp[MAX_PB_SIZE *MAX_PB_SIZE]
Definition: ctu.h:383
mask
int mask
Definition: mediacodecdec_common.c:154
IS_P
#define IS_P(rsh)
Definition: ps.h:39
ff_vvc_predict_inter
int ff_vvc_predict_inter(VVCLocalContext *lc, const int rs)
Loop entire CTU to predict all inter coding blocks.
Definition: inter.c:1003
data.h
VVCLocalContext::ciip_tmp
uint8_t ciip_tmp[MAX_PB_SIZE *MAX_PB_SIZE *2]
Definition: ctu.h:386
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
VVCRefPic
Definition: dec.h:45
w
uint8_t w
Definition: llviddspenc.c:38
VVCLocalContext::sc
SliceContext * sc
Definition: ctu.h:434
b
#define b
Definition: input.c:41
Mv::y
int16_t y
vertical component of motion vector
Definition: hevcdec.h:303
VVCSH::r
const H266RawSliceHeader * r
RefStruct reference.
Definition: ps.h:239
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:472
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
VVCRect::t
int t
Definition: ctu.h:470
RefPicList
Definition: hevcdec.h:192
derive_sb_mv
static void derive_sb_mv(VVCLocalContext *lc, MvField *mv, MvField *orig_mv, int *sb_bdof_flag, const int x0, const int y0, const int sbw, const int sbh)
Definition: inter.c:864
subpic_get_rect
static void subpic_get_rect(VVCRect *r, const VVCFrame *src_frame, const int subpic_idx, const int is_chroma)
Definition: inter.c:33
PF_INTRA
@ PF_INTRA
Definition: hevcdec.h:116
INTER_FILTER
#define INTER_FILTER(t, frac)
Definition: inter.c:250
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:410
VVCRefPic::ref
struct VVCFrame * ref
Definition: dec.h:46
MODE_SKIP
@ MODE_SKIP
Definition: hevcdec.h:106
MIN_PU_LOG2
#define MIN_PU_LOG2
Definition: dec.h:40
mx
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t mx
Definition: dsp.h:53
MC_EMULATED_EDGE_DMVR
#define MC_EMULATED_EDGE_DMVR(dst, src, src_stride, x_sb, y_sb, x_off, y_off)
Definition: inter.c:191
PredictionUnit::gpm_mv
MvField gpm_mv[2]
Definition: ctu.h:265
VVCLocalContext::fc
VVCFrameContext * fc
Definition: ctu.h:435
VVCSH::pwt
PredWeightTable pwt
Definition: ps.h:247
PredictionUnit
Definition: hevcdec.h:321
wrap
#define wrap(func)
Definition: neontest.h:65
MODE_INTER
@ MODE_INTER
Definition: hevcdec.h:104
IS_B
#define IS_B(rsh)
Definition: ps.h:40
VVCLocalContext::tmp1
int16_t tmp1[MAX_PB_SIZE *MAX_PB_SIZE]
Definition: ctu.h:384
derive_weight_uni
static int derive_weight_uni(int *denom, int *wx, int *ox, const VVCLocalContext *lc, const MvField *mvf, const int c_idx)
Definition: inter.c:200
SCALED_INT
#define SCALED_INT(pos)
Definition: ctu.h:64
SliceContext::rpl
RefPicList * rpl
Definition: dec.h:113
VVCRect
Definition: ctu.h:468
SCALED_REF
#define SCALED_REF(ref_sb, offset, shift)
Definition: inter.c:381
bcw_w_lut
static const int bcw_w_lut[]
Definition: inter.c:31
CodingUnit::cb_width
int cb_width
Definition: ctu.h:284
INTER_FILTER_SCALED
#define INTER_FILTER_SCALED(scale)
Definition: inter.c:377
CodingUnit::pu
PredictionUnit pu
Definition: ctu.h:329
RefPicList::refs
VVCRefPic refs[VVC_MAX_REF_ENTRIES]
Definition: dec.h:56
ff_vvc_clip_mv
void ff_vvc_clip_mv(Mv *mv)
Definition: mvs.c:1883
PROF_TEMP_OFFSET
#define PROF_TEMP_OFFSET
Definition: inter.c:30
SCALED_CHROMA_ADDIN
#define SCALED_CHROMA_ADDIN(scale, collocated_flag)
Definition: inter.c:379
emulated_half
static void emulated_half(const VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src, const ptrdiff_t src_stride, const int ps, int x_off, int y_off, const int block_w, const int block_h, const VVCRect *subpic, const VVCRect *half_sb, const int dmvr_clip)
Definition: inter.c:91
mi
#define mi
Definition: vf_colormatrix.c:106
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
VVCSH
Definition: ps.h:238
VVCLocalContext::edge_emu_buffer
uint8_t edge_emu_buffer[EDGE_EMU_BUFFER_STRIDE *EDGE_EMU_BUFFER_STRIDE *2]
Definition: ctu.h:382
PredWeightTable
Definition: ps.h:137
CodingUnit::tree_type
VVCTreeType tree_type
Definition: ctu.h:281
ff_vvc_gpm_weights_offset_x
const uint8_t ff_vvc_gpm_weights_offset_x[VVC_GPM_NUM_PARTITION][4][4]
Definition: data.c:2106
dmvr_mv_refine
static void dmvr_mv_refine(VVCLocalContext *lc, MvField *mvf, MvField *orig_mv, int *sb_bdof_flag, const VVCFrame *ref0, const VVCFrame *ref1, const int x_off, const int y_off, const int block_w, const int block_h)
Definition: inter.c:782
PredictionUnit::bdof_flag
uint8_t bdof_flag
Definition: ctu.h:273
has_inter_luma
static int has_inter_luma(const CodingUnit *cu)
Definition: inter.c:998
SCALE_THRESHOLD_2
#define SCALE_THRESHOLD_2
sb_set_lr
static void sb_set_lr(VVCRect *sb, const int l, const int r)
Definition: inter.c:107
my
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t my
Definition: dsp.h:53
H266RawSliceHeader::sh_lmcs_used_flag
uint8_t sh_lmcs_used_flag
Definition: cbs_h266.h:794
derive_weight
static int derive_weight(int *denom, int *w0, int *w1, int *o0, int *o1, const VVCLocalContext *lc, const MvField *mvf, const int c_idx, const int dmvr_flag)
Definition: inter.c:220
inter.h
SAD_ARRAY_SIZE
#define SAD_ARRAY_SIZE
Definition: inter.c:780
NULL
#define NULL
Definition: coverity.c:32
mc_scaled
static void mc_scaled(VVCLocalContext *lc, int16_t *dst, const VVCRefPic *refp, const Mv *mv, int x_off, int y_off, const int block_w, const int block_h, const int c_idx)
Definition: inter.c:421
SCALED_STEP
#define SCALED_STEP(scale)
Definition: inter.c:382
derive_affine_mvc
static void derive_affine_mvc(MvField *mvc, const VVCFrameContext *fc, const MvField *mv, const int x0, const int y0, const int sbw, const int sbh)
Definition: inter.c:910
VVCLocalContext
Definition: ctu.h:373
pred_h
static void FUNC() pred_h(uint8_t *_src, const uint8_t *_left, const int w, const int h, const ptrdiff_t stride)
Definition: intra_template.c:877
H266RawSliceHeader::curr_subpic_idx
uint16_t curr_subpic_idx
CurrSubpicIdx.
Definition: cbs_h266.h:837
mc_bi_scaled
static void mc_bi_scaled(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCRefPic *refp0, const VVCRefPic *refp1, const MvField *mvf, const int x_off, const int y_off, const int block_w, const int block_h, const int c_idx)
Definition: inter.c:468
L0
#define L0
Definition: hevcdec.h:58
scaled_ref_pos_and_step
static void scaled_ref_pos_and_step(const VVCLocalContext *lc, const VVCRefPic *refp, const Mv *mv, const int x_off, const int y_off, const int c_idx, int *x, int *y, int *dx, int *dy)
Definition: inter.c:384
MC_EMULATED_EDGE
#define MC_EMULATED_EDGE(dst, src, src_stride, x_off, y_off)
Definition: inter.c:187
ff_vvc_round_mv
void ff_vvc_round_mv(Mv *mv, const int lshift, const int rshift)
Definition: mvs.c:1871
VVCRefPic::is_scaled
int is_scaled
RprConstraintsActiveFlag.
Definition: dec.h:51
Mv::x
int16_t x
horizontal component of motion vector
Definition: hevcdec.h:302
PF_BI
@ PF_BI
Definition: hevcdec.h:119
predict_inter
static void predict_inter(VVCLocalContext *lc)
Definition: inter.c:979
ff_vvc_inter_luma_filters
const int8_t ff_vvc_inter_luma_filters[VVC_INTER_LUMA_FILTER_TYPES][VVC_INTER_LUMA_FACTS][VVC_INTER_LUMA_TAPS]
Definition: data.c:1735
MIN_PU_SIZE
#define MIN_PU_SIZE
Definition: ctu.h:42
clip_to_subpic
static void clip_to_subpic(int *x_off, int *y_off, int *pic_width, int *pic_height, const VVCRect *subpic, const VVCRect *sb, const int dmvr_clip)
Definition: inter.c:47
pred_affine_blk
static void pred_affine_blk(VVCLocalContext *lc)
Definition: inter.c:928
mvs.h
height
#define height
Definition: dsp.h:85
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
MotionInfo::hpel_if_idx
uint8_t hpel_if_idx
hpelIfIdx
Definition: ctu.h:245
PredictionUnit::merge_gpm_flag
uint8_t merge_gpm_flag
Definition: ctu.h:263
PredictionUnit::cb_prof_flag
int cb_prof_flag[2]
Definition: ctu.h:277
VVC_GPM_WEIGHT_SIZE
#define VVC_GPM_WEIGHT_SIZE
Definition: data.h:68
MvField
Definition: hevcdec.h:306
refs.h
frame.h
pred_gpm_blk
static void pred_gpm_blk(VVCLocalContext *lc)
Definition: inter.c:605
PF_L1
@ PF_L1
Definition: hevcdec.h:118
AFFINE_MIN_BLOCK_SIZE
#define AFFINE_MIN_BLOCK_SIZE
Definition: ctu.h:68
VVCLocalContext::ctb_up_flag
uint8_t ctb_up_flag
Definition: ctu.h:375
pred_regular
static void pred_regular(VVCLocalContext *lc, const MvField *mvf, const MvField *orig_mvf, const int x0, const int y0, const int sbw, const int sbh, const int sb_bdof_flag, const int c_start)
Definition: inter.c:684
PredictionUnit::diff_mv_x
int16_t diff_mv_x[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
Definition: ctu.h:275
VVCRect::l
int l
Definition: ctu.h:469
VVCFrame
Definition: dec.h:71
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
ff_vvc_predict_ciip
void ff_vvc_predict_ciip(VVCLocalContext *lc)
CIIP(Combined Inter-Intra Prediction) for a coding block.
Definition: inter.c:1018
av_zero_extend
#define av_zero_extend
Definition: common.h:151
MC_EMULATED_EDGE_BILINEAR
#define MC_EMULATED_EDGE_BILINEAR(dst, src, src_stride, x_off, y_off)
Definition: inter.c:195
MvField::pred_flag
int8_t pred_flag
Definition: hevcdec.h:309
emulated_edge_no_wrap
static void emulated_edge_no_wrap(const VVCLocalContext *lc, uint8_t *dst, const uint8_t **src, ptrdiff_t *src_stride, int x_off, int y_off, const int block_w, const int block_h, const int extra_before, const int extra_after, const VVCRect *subpic, const VVCRect *sb, const int dmvr_clip)
Definition: inter.c:60
emulated_edge_scaled
static void emulated_edge_scaled(VVCLocalContext *lc, const uint8_t **src, ptrdiff_t *src_stride, int *src_height, const VVCFrame *ref, const int x, const int y, const int dx, const int dy, const int w, const int h, const int is_chroma)
Definition: inter.c:405
PredictionUnit::mi
MotionInfo mi
Definition: ctu.h:269
CR
#define CR
Definition: filter.c:33
parametric_mv_refine
static int parametric_mv_refine(const int *sad, const int stride)
Definition: inter.c:739
mc_bi
static void mc_bi(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCFrame *ref0, const VVCFrame *ref1, const MvField *mvf, const MvField *orig_mv, const int x_off, const int y_off, const int block_w, const int block_h, const int c_idx, const int sb_bdof_flag)
Definition: inter.c:312
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ff_vvc_gpm_angle_idx
const uint8_t ff_vvc_gpm_angle_idx[VVC_GPM_NUM_PARTITION]
Definition: data.c:2077
pred_get_refs
static int pred_get_refs(const VVCLocalContext *lc, VVCRefPic *refp[2], const MvField *mv)
Definition: inter.c:586
weights
static const int weights[]
Definition: hevc_pel.c:32
mc_uni_scaled
static void mc_uni_scaled(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCRefPic *refp, const MvField *mvf, const int x_off, const int y_off, const int block_w, const int block_h, const int c_idx)
Definition: inter.c:440
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
PF_L0
@ PF_L0
Definition: hevcdec.h:117
EDGE_EMU_BUFFER_STRIDE
#define EDGE_EMU_BUFFER_STRIDE
Definition: hevcdec.h:68
POS
#define POS(c_idx, x, y)
Definition: inter.c:601
CodingUnit::x0
int x0
Definition: ctu.h:282
hf
uint8_t ptrdiff_t const uint8_t ptrdiff_t int const int8_t * hf
Definition: dsp.h:249
VVCRect::b
int b
Definition: ctu.h:472
VVCLocalContext::cu
CodingUnit * cu
Definition: ctu.h:418
stride
#define stride
Definition: h264pred_template.c:537
MAX_PB_SIZE
#define MAX_PB_SIZE
Definition: dsp.h:32
PredictionUnit::dmvr_flag
uint8_t dmvr_flag
Definition: ctu.h:272
inter_filter_scaled
static const int8_t * inter_filter_scaled(const int scale, const int is_chroma, const int is_affine)
Definition: inter.c:362
VVCFrame::frame
struct AVFrame * frame
Definition: dec.h:72
ff_vvc_gpm_weights
const uint8_t ff_vvc_gpm_weights[6][VVC_GPM_WEIGHT_SIZE *VVC_GPM_WEIGHT_SIZE]
Definition: data.c:2880
sps
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
Definition: cbs_h264_syntax_template.c:260
PredictionUnit::inter_affine_flag
uint8_t inter_affine_flag
Definition: ctu.h:258
ff_vvc_get_mvf
MvField * ff_vvc_get_mvf(const VVCFrameContext *fc, const int x0, const int y0)
Definition: mvs.c:1943
CodingUnit::cb_height
int cb_height
Definition: ctu.h:285
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
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:2519
DUAL_TREE_CHROMA
@ DUAL_TREE_CHROMA
Definition: ctu.h:169
ciip_derive_intra_weight
static int ciip_derive_intra_weight(const VVCLocalContext *lc, const int x0, const int y0, const int width, const int height)
Definition: inter.c:663
CodingUnit::pred_mode
enum PredMode pred_mode
PredMode.
Definition: hevcdec.h:292
VVCRect::r
int r
Definition: ctu.h:471
VVCLocalContext::tmp2
int16_t tmp2[MAX_PB_SIZE *MAX_PB_SIZE]
Definition: ctu.h:385
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:112
pps
uint64_t pps
Definition: dovi_rpuenc.c:35
PredictionUnit::diff_mv_y
int16_t diff_mv_y[2][AFFINE_MIN_BLOCK_SIZE *AFFINE_MIN_BLOCK_SIZE]
diffMvLX
Definition: ctu.h:276
sb_wrap
static void sb_wrap(VVCRect *sb, const int wrap)
Definition: inter.c:113
CodingUnit::next
struct CodingUnit * next
RefStruct reference.
Definition: ctu.h:331
MvField::mv
Mv mv[2]
mvL0, vvL1
Definition: hevcdec.h:307
Mv
Definition: hevcdec.h:301
MvField::ref_idx
int8_t ref_idx[2]
refIdxL0, refIdxL1
Definition: hevcdec.h:308
pred_regular_blk
static void pred_regular_blk(VVCLocalContext *lc, const int skip_ciip)
Definition: inter.c:882
luma_prof_bi
static void luma_prof_bi(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCRefPic *ref0, const VVCRefPic *ref1, const MvField *mvf, const int x_off, const int y_off, const int block_w, const int block_h)
Definition: inter.c:560
scale
static void scale(int *out, const int *in, const int w, const int h, const int shift)
Definition: intra.c:291
ff_vvc_gpm_weights_offset_y
const uint8_t ff_vvc_gpm_weights_offset_y[VVC_GPM_NUM_PARTITION][4][4]
Definition: data.c:2493
SliceContext::sh
VVCSH sh
Definition: dec.h:110
SCALED_REF_SB
#define SCALED_REF_SB(off, scaling_off, ref_mv, scale, add, shift)
Definition: inter.c:380
VVCFrameContext
Definition: dec.h:117
MvField::bcw_idx
uint8_t bcw_idx
bcwIdx
Definition: ctu.h:205
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:434
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
h
h
Definition: vp9dsp_template.c:2070
width
#define width
Definition: dsp.h:85
VVC_INTER_LUMA_FILTER_TYPE_AFFINE
#define VVC_INTER_LUMA_FILTER_TYPE_AFFINE
Definition: data.h:46
vf
uint8_t ptrdiff_t const uint8_t ptrdiff_t int const int8_t const int8_t * vf
Definition: dsp.h:249
CodingUnit::ciip_flag
uint8_t ciip_flag
Definition: ctu.h:305
ff_vvc_gpm_angle_to_weights_idx
const uint8_t ff_vvc_gpm_angle_to_weights_idx[VVC_GPM_NUM_ANGLES]
Definition: data.c:2100
av_log2
int av_log2(unsigned v)
Definition: intmath.c:26
mc_uni
static void mc_uni(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCFrame *ref, const MvField *mvf, int x_off, int y_off, const int block_w, const int block_h, const int c_idx)
Definition: inter.c:277
VVCFrame::sps
const VVCSPS * sps
RefStruct reference.
Definition: dec.h:74
src
#define src
Definition: vp8dsp.c:248
VVCLocalContext::ctb_left_flag
uint8_t ctb_left_flag
Definition: ctu.h:374
luma_prof_uni
static void luma_prof_uni(VVCLocalContext *lc, uint8_t *dst, const ptrdiff_t dst_stride, const VVCFrame *ref, const MvField *mvf, int x_off, int y_off, const int block_w, const int block_h, const int cb_prof_flag, const int16_t *diff_mv_x, const int16_t *diff_mv_y)
Definition: inter.c:493
VVCRefPic::scale
int scale[2]
RefPicScale[].
Definition: dec.h:52
CodingUnit::y0
int y0
Definition: ctu.h:283
mc
static void mc(VVCLocalContext *lc, int16_t *dst, const VVCFrame *ref, const Mv *mv, int x_off, int y_off, const int block_w, const int block_h, const int c_idx)
Definition: inter.c:252