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