FFmpeg
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
filter.c
Go to the documentation of this file.
1 /*
2  * VVC filters
3  *
4  * Copyright (C) 2021 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 #include "libavutil/imgutils.h"
24 
25 #include "ctu.h"
26 #include "data.h"
27 #include "filter.h"
28 #include "refs.h"
29 
30 #define LEFT 0
31 #define TOP 1
32 #define RIGHT 2
33 #define BOTTOM 3
34 #define MAX_EDGES 4
35 
36 #define DEFAULT_INTRA_TC_OFFSET 2
37 
38 #define POS(c_idx, x, y) \
39  &fc->frame->data[c_idx][((y) >> fc->ps.sps->vshift[c_idx]) * fc->frame->linesize[c_idx] + \
40  (((x) >> fc->ps.sps->hshift[c_idx]) << fc->ps.sps->pixel_shift)]
41 
42 //Table 43 Derivation of threshold variables beta' and tc' from input Q
43 static const uint16_t tctable[66] = {
44  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45  0, 0, 3, 4, 4, 4, 4, 5, 5, 5, 5, 7, 7, 8, 9, 10,
46  10, 11, 13, 14, 15, 17, 19, 21, 24, 25, 29, 33, 36, 41, 45, 51,
47  57, 64, 71, 80, 89, 100, 112, 125, 141, 157, 177, 198, 222, 250, 280, 314,
48  352, 395,
49 };
50 
51 //Table 43 Derivation of threshold variables beta' and tc' from input Q
52 static const uint8_t betatable[64] = {
53  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54  6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24,
55  26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56,
56  58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88,
57 };
58 
59 // One vertical and one horizontal virtual boundary in a CTU at most. The CTU will be divided into 4 subblocks.
60 #define MAX_VBBS 4
61 
62 static int get_virtual_boundary(const VVCFrameContext *fc, const int ctu_pos, const int vertical)
63 {
64  const VVCSPS *sps = fc->ps.sps;
65  const VVCPH *ph = &fc->ps.ph;
66  const uint16_t *vbs = vertical ? ph->vb_pos_x : ph->vb_pos_y;
67  const uint8_t nb_vbs = vertical ? ph->num_ver_vbs : ph->num_hor_vbs;
68  const int pos = ctu_pos << sps->ctb_log2_size_y;
69 
70  if (sps->r->sps_virtual_boundaries_enabled_flag) {
71  for (int i = 0; i < nb_vbs; i++) {
72  const int o = vbs[i] - pos;
73  if (o >= 0 && o < sps->ctb_size_y)
74  return vbs[i];
75  }
76  }
77  return 0;
78 }
79 
80 static int is_virtual_boundary(const VVCFrameContext *fc, const int pos, const int vertical)
81 {
82  return get_virtual_boundary(fc, pos >> fc->ps.sps->ctb_log2_size_y, vertical) == pos;
83 }
84 
85 static int get_qPc(const VVCFrameContext *fc, const int x0, const int y0, const int chroma)
86 {
87  const int x = x0 >> MIN_TU_LOG2;
88  const int y = y0 >> MIN_TU_LOG2;
89  const int min_tu_width = fc->ps.pps->min_tu_width;
90  return fc->tab.qp[chroma][x + y * min_tu_width];
91 }
92 
93 static void copy_ctb(uint8_t *dst, const uint8_t *src, const int width, const int height,
94  const ptrdiff_t dst_stride, const ptrdiff_t src_stride)
95 {
96  for (int y = 0; y < height; y++) {
97  memcpy(dst, src, width);
98 
99  dst += dst_stride;
100  src += src_stride;
101  }
102 }
103 
104 static void copy_pixel(uint8_t *dst, const uint8_t *src, const int pixel_shift)
105 {
106  if (pixel_shift)
107  *(uint16_t *)dst = *(uint16_t *)src;
108  else
109  *dst = *src;
110 }
111 
112 static void copy_vert(uint8_t *dst, const uint8_t *src, const int pixel_shift, const int height,
113  const ptrdiff_t dst_stride, const ptrdiff_t src_stride)
114 {
115  int i;
116  if (pixel_shift == 0) {
117  for (i = 0; i < height; i++) {
118  *dst = *src;
119  dst += dst_stride;
120  src += src_stride;
121  }
122  } else {
123  for (i = 0; i < height; i++) {
124  *(uint16_t *)dst = *(uint16_t *)src;
125  dst += dst_stride;
126  src += src_stride;
127  }
128  }
129 }
130 
131 static void copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src,
132  const ptrdiff_t src_stride, const int x, const int y, const int width, const int height,
133  const int c_idx, const int rx, const int ry, const int top)
134 {
135  const int ps = fc->ps.sps->pixel_shift;
136  const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
137  const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
138 
139  if (top) {
140  /* top */
141  memcpy(fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * ry) * w + x) << ps),
142  src, width << ps);
143  } else {
144  /* bottom */
145  memcpy(fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * ry + 1) * w + x) << ps),
146  src + src_stride * (height - 1), width << ps);
147 
148  /* copy vertical edges */
149  copy_vert(fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * rx) * h + y) << ps), src, ps, height, 1 << ps, src_stride);
150  copy_vert(fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * rx + 1) * h + y) << ps), src + ((width - 1) << ps), ps, height, 1 << ps, src_stride);
151  }
152 }
153 
154 static void sao_copy_ctb_to_hv(VVCLocalContext *lc, const int rx, const int ry, const int top)
155 {
156  VVCFrameContext *fc = lc->fc;
157  const int ctb_size_y = fc->ps.sps->ctb_size_y;
158  const int x0 = rx << fc->ps.sps->ctb_log2_size_y;
159  const int y0 = ry << fc->ps.sps->ctb_log2_size_y;
160 
161  for (int c_idx = 0; c_idx < (fc->ps.sps->r->sps_chroma_format_idc ? 3 : 1); c_idx++) {
162  const int x = x0 >> fc->ps.sps->hshift[c_idx];
163  const int y = y0 >> fc->ps.sps->vshift[c_idx];
164  const ptrdiff_t src_stride = fc->frame->linesize[c_idx];
165  const int ctb_size_h = ctb_size_y >> fc->ps.sps->hshift[c_idx];
166  const int ctb_size_v = ctb_size_y >> fc->ps.sps->vshift[c_idx];
167  const int width = FFMIN(ctb_size_h, (fc->ps.pps->width >> fc->ps.sps->hshift[c_idx]) - x);
168  const int height = FFMIN(ctb_size_v, (fc->ps.pps->height >> fc->ps.sps->vshift[c_idx]) - y);
169  const uint8_t *src = POS(c_idx, x0, y0);
170  copy_ctb_to_hv(fc, src, src_stride, x, y, width, height, c_idx, rx, ry, top);
171  }
172 }
173 
174 void ff_vvc_sao_copy_ctb_to_hv(VVCLocalContext *lc, const int rx, const int ry, const int last_row)
175 {
176  if (ry)
177  sao_copy_ctb_to_hv(lc, rx, ry - 1, 0);
178 
179  sao_copy_ctb_to_hv(lc, rx, ry, 1);
180 
181  if (last_row)
182  sao_copy_ctb_to_hv(lc, rx, ry, 0);
183 }
184 
185 static int sao_can_cross_slices(const VVCFrameContext *fc, const int rx, const int ry, const int dx, const int dy)
186 {
187  const uint8_t lfase = fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag;
188 
189  return lfase || CTB(fc->tab.slice_idx, rx, ry) == CTB(fc->tab.slice_idx, rx + dx, ry + dy);
190 }
191 
192 static void sao_get_edges(uint8_t vert_edge[2], uint8_t horiz_edge[2], uint8_t diag_edge[4], int *restore,
193  const VVCLocalContext *lc, const int edges[4], const int rx, const int ry)
194 {
195  const VVCFrameContext *fc = lc->fc;
196  const VVCSPS *sps = fc->ps.sps;
197  const H266RawSPS *rsps = sps->r;
198  const VVCPPS *pps = fc->ps.pps;
199  const int subpic_idx = lc->sc->sh.r->curr_subpic_idx;
200  const uint8_t lfase = fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag;
201  const uint8_t no_tile_filter = pps->r->num_tiles_in_pic > 1 && !pps->r->pps_loop_filter_across_tiles_enabled_flag;
202  const uint8_t no_subpic_filter = rsps->sps_num_subpics_minus1 && !rsps->sps_loop_filter_across_subpic_enabled_flag[subpic_idx];
203  uint8_t lf_edge[] = { 0, 0, 0, 0 };
204 
205  *restore = no_subpic_filter || no_tile_filter || !lfase || rsps->sps_virtual_boundaries_enabled_flag;
206 
207  if (!*restore)
208  return;
209 
210  if (!edges[LEFT]) {
211  lf_edge[LEFT] = no_tile_filter && pps->ctb_to_col_bd[rx] == rx;
212  lf_edge[LEFT] |= no_subpic_filter && rsps->sps_subpic_ctu_top_left_x[subpic_idx] == rx;
213  lf_edge[LEFT] |= is_virtual_boundary(fc, rx << sps->ctb_log2_size_y, 1);
214  vert_edge[0] = !sao_can_cross_slices(fc, rx, ry, -1, 0) || lf_edge[LEFT];
215  }
216  if (!edges[RIGHT]) {
217  lf_edge[RIGHT] = no_tile_filter && pps->ctb_to_col_bd[rx] != pps->ctb_to_col_bd[rx + 1];
218  lf_edge[RIGHT] |= no_subpic_filter && rsps->sps_subpic_ctu_top_left_x[subpic_idx] + rsps->sps_subpic_width_minus1[subpic_idx] == rx;
219  lf_edge[RIGHT] |= is_virtual_boundary(fc, (rx + 1) << sps->ctb_log2_size_y, 1);
220  vert_edge[1] = !sao_can_cross_slices(fc, rx, ry, 1, 0) || lf_edge[RIGHT];
221  }
222  if (!edges[TOP]) {
223  lf_edge[TOP] = no_tile_filter && pps->ctb_to_row_bd[ry] == ry;
224  lf_edge[TOP] |= no_subpic_filter && rsps->sps_subpic_ctu_top_left_y[subpic_idx] == ry;
225  lf_edge[TOP] |= is_virtual_boundary(fc, ry << sps->ctb_log2_size_y, 0);
226  horiz_edge[0] = !sao_can_cross_slices(fc, rx, ry, 0, -1) || lf_edge[TOP];
227  }
228  if (!edges[BOTTOM]) {
229  lf_edge[BOTTOM] = no_tile_filter && pps->ctb_to_row_bd[ry] != pps->ctb_to_row_bd[ry + 1];
230  lf_edge[BOTTOM] |= no_subpic_filter && rsps->sps_subpic_ctu_top_left_y[subpic_idx] + rsps->sps_subpic_height_minus1[subpic_idx] == ry;
231  lf_edge[BOTTOM] |= is_virtual_boundary(fc, (ry + 1) << sps->ctb_log2_size_y, 0);
232  horiz_edge[1] = !sao_can_cross_slices(fc, rx, ry, 0, 1) || lf_edge[BOTTOM];
233  }
234 
235  if (!edges[LEFT] && !edges[TOP])
236  diag_edge[0] = !sao_can_cross_slices(fc, rx, ry, -1, -1) || lf_edge[LEFT] || lf_edge[TOP];
237 
238  if (!edges[TOP] && !edges[RIGHT])
239  diag_edge[1] = !sao_can_cross_slices(fc, rx, ry, 1, -1) || lf_edge[RIGHT] || lf_edge[TOP];
240 
241  if (!edges[RIGHT] && !edges[BOTTOM])
242  diag_edge[2] = !sao_can_cross_slices(fc, rx, ry, 1, 1) || lf_edge[RIGHT] || lf_edge[BOTTOM];
243 
244  if (!edges[LEFT] && !edges[BOTTOM])
245  diag_edge[3] = !sao_can_cross_slices(fc, rx, ry, -1, 1) || lf_edge[LEFT] || lf_edge[BOTTOM];
246 }
247 
248 static void sao_copy_hor(uint8_t *dst, const ptrdiff_t dst_stride,
249  const uint8_t *src, const ptrdiff_t src_stride, const int width, const int edges[4], const int ps)
250 {
251  const int left = 1 - edges[LEFT];
252  const int right = 1 - edges[RIGHT];
253  int pos = 0;
254 
255  src -= left << ps;
256  dst -= left << ps;
257 
258  if (left) {
259  copy_pixel(dst, src, ps);
260  pos += (1 << ps);
261  }
262  memcpy(dst + pos, src + pos, width << ps);
263  if (right) {
264  pos += width << ps;
265  copy_pixel(dst + pos, src + pos, ps);
266  }
267 }
268 
269 static void sao_extends_edges(uint8_t *dst, const ptrdiff_t dst_stride,
270  const uint8_t *src, const ptrdiff_t src_stride, const int width, const int height,
271  const VVCFrameContext *fc, const int x0, const int y0, const int rx, const int ry, const int edges[4], const int c_idx)
272 {
273  const uint8_t *sao_h = fc->tab.sao_pixel_buffer_h[c_idx];
274  const uint8_t *sao_v = fc->tab.sao_pixel_buffer_v[c_idx];
275  const int x = x0 >> fc->ps.sps->hshift[c_idx];
276  const int y = y0 >> fc->ps.sps->vshift[c_idx];
277  const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
278  const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
279  const int ps = fc->ps.sps->pixel_shift;
280 
281  if (!edges[TOP])
282  sao_copy_hor(dst - dst_stride, dst_stride, sao_h + (((2 * ry - 1) * w + x) << ps), src_stride, width, edges, ps);
283 
284  if (!edges[BOTTOM])
285  sao_copy_hor(dst + height * dst_stride, dst_stride, sao_h + (((2 * ry + 2) * w + x) << ps), src_stride, width, edges, ps);
286 
287  if (!edges[LEFT])
288  copy_vert(dst - (1 << ps), sao_v + (((2 * rx - 1) * h + y) << ps), ps, height, dst_stride, 1 << ps);
289 
290  if (!edges[RIGHT])
291  copy_vert(dst + (width << ps), sao_v + (((2 * rx + 2) * h + y) << ps), ps, height, dst_stride, 1 << ps);
292 
293  copy_ctb(dst, src, width << ps, height, dst_stride, src_stride);
294 }
295 
296 static void sao_restore_vb(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *src, ptrdiff_t src_stride,
297  const int width, const int height, const int vb_pos, const int ps, const int vertical)
298 {
299  int w = 2;
300  int h = (vertical ? height : width);
301  int dx = vb_pos - 1;
302  int dy = 0;
303 
304  if (!vertical) {
305  FFSWAP(int, w, h);
306  FFSWAP(int, dx, dy);
307  }
308  dst += dy * dst_stride +(dx << ps);
309  src += dy * src_stride +(dx << ps);
310 
311  av_image_copy_plane(dst, dst_stride, src, src_stride, w << ps, h);
312 }
313 
314 void ff_vvc_sao_filter(VVCLocalContext *lc, int x0, int y0)
315 {
316  VVCFrameContext *fc = lc->fc;
317  const VVCSPS *sps = fc->ps.sps;
318  const int rx = x0 >> sps->ctb_log2_size_y;
319  const int ry = y0 >> sps->ctb_log2_size_y;
320  const int edges[4] = { !rx, !ry, rx == fc->ps.pps->ctb_width - 1, ry == fc->ps.pps->ctb_height - 1 };
321  const SAOParams *sao = &CTB(fc->tab.sao, rx, ry);
322  // flags indicating unfilterable edges
323  uint8_t vert_edge[] = { 0, 0 };
324  uint8_t horiz_edge[] = { 0, 0 };
325  uint8_t diag_edge[] = { 0, 0, 0, 0 };
326  int restore, vb_x = 0, vb_y = 0;;
327 
328  if (sps->r->sps_virtual_boundaries_enabled_flag) {
329  vb_x = get_virtual_boundary(fc, rx, 1);
330  vb_y = get_virtual_boundary(fc, ry, 0);
331  }
332 
333  sao_get_edges(vert_edge, horiz_edge, diag_edge, &restore, lc, edges, rx, ry);
334 
335  for (int c_idx = 0; c_idx < (sps->r->sps_chroma_format_idc ? 3 : 1); c_idx++) {
336  static const uint8_t sao_tab[16] = { 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8 };
337  const ptrdiff_t src_stride = fc->frame->linesize[c_idx];
338  uint8_t *src = POS(c_idx, x0, y0);
339  const int hs = sps->hshift[c_idx];
340  const int vs = sps->vshift[c_idx];
341  const int ps = sps->pixel_shift;
342  const int width = FFMIN(sps->ctb_size_y, fc->ps.pps->width - x0) >> hs;
343  const int height = FFMIN(sps->ctb_size_y, fc->ps.pps->height - y0) >> vs;
344  const int tab = sao_tab[(FFALIGN(width, 8) >> 3) - 1];
345  const int sao_eo_class = sao->eo_class[c_idx];
346 
347  switch (sao->type_idx[c_idx]) {
348  case SAO_BAND:
349  fc->vvcdsp.sao.band_filter[tab](src, src, src_stride, src_stride,
350  sao->offset_val[c_idx], sao->band_position[c_idx], width, height);
351  break;
352  case SAO_EDGE:
353  {
354  const ptrdiff_t dst_stride = 2 * MAX_PB_SIZE + AV_INPUT_BUFFER_PADDING_SIZE;
355  uint8_t *dst = lc->sao_buffer + dst_stride + AV_INPUT_BUFFER_PADDING_SIZE;
356 
357  sao_extends_edges(dst, dst_stride, src, src_stride, width, height, fc, x0, y0, rx, ry, edges, c_idx);
358 
359  fc->vvcdsp.sao.edge_filter[tab](src, dst, src_stride, sao->offset_val[c_idx],
360  sao->eo_class[c_idx], width, height);
361  fc->vvcdsp.sao.edge_restore[restore](src, dst, src_stride, dst_stride,
362  sao, edges, width, height, c_idx, vert_edge, horiz_edge, diag_edge);
363 
364  if (vb_x > x0 && sao_eo_class != SAO_EO_VERT)
365  sao_restore_vb(src, src_stride, dst, dst_stride, width, height, (vb_x - x0) >> hs, ps, 1);
366  if (vb_y > y0 && sao_eo_class != SAO_EO_HORIZ)
367  sao_restore_vb(src, src_stride, dst, dst_stride, width, height, (vb_y - y0) >> vs, ps, 0);
368 
369  break;
370  }
371  }
372  }
373 }
374 
375 #define TAB_BS(t, x, y) (t)[((y) >> MIN_TU_LOG2) * (fc->ps.pps->min_tu_width) + ((x) >> MIN_TU_LOG2)]
376 #define TAB_MAX_LEN(t, x, y) (t)[((y) >> MIN_TU_LOG2) * (fc->ps.pps->min_tu_width) + ((x) >> MIN_TU_LOG2)]
377 
378 //8 samples a time
379 #define DEBLOCK_STEP 8
380 #define LUMA_GRID 4
381 #define CHROMA_GRID 8
382 
383 static int boundary_strength(const VVCLocalContext *lc, const MvField *curr, const MvField *neigh,
384  const RefPicList *neigh_rpl)
385 {
386  RefPicList *rpl = lc->sc->rpl;
387 
388  if (curr->pred_flag == PF_PLT)
389  return 0;
390 
391  if (curr->pred_flag == PF_IBC)
392  return FFABS(neigh->mv[0].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 8;
393 
394  if (curr->pred_flag == PF_BI && neigh->pred_flag == PF_BI) {
395  // same L0 and L1
396  if (rpl[L0].refs[curr->ref_idx[L0]].poc == neigh_rpl[L0].refs[neigh->ref_idx[L0]].poc &&
397  rpl[L0].refs[curr->ref_idx[L0]].poc == rpl[L1].refs[curr->ref_idx[L1]].poc &&
398  neigh_rpl[L0].refs[neigh->ref_idx[L0]].poc == neigh_rpl[L1].refs[neigh->ref_idx[L1]].poc) {
399  if ((FFABS(neigh->mv[0].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 8 ||
400  FFABS(neigh->mv[1].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 8) &&
401  (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 8 ||
402  FFABS(neigh->mv[0].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 8))
403  return 1;
404  else
405  return 0;
406  } else if (neigh_rpl[L0].refs[neigh->ref_idx[L0]].poc == rpl[L0].refs[curr->ref_idx[L0]].poc &&
407  neigh_rpl[L1].refs[neigh->ref_idx[L1]].poc == rpl[L1].refs[curr->ref_idx[L1]].poc) {
408  if (FFABS(neigh->mv[0].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 8 ||
409  FFABS(neigh->mv[1].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 8)
410  return 1;
411  else
412  return 0;
413  } else if (neigh_rpl[L1].refs[neigh->ref_idx[L1]].poc == rpl[L0].refs[curr->ref_idx[L0]].poc &&
414  neigh_rpl[L0].refs[neigh->ref_idx[L0]].poc == rpl[L1].refs[curr->ref_idx[L1]].poc) {
415  if (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 8 ||
416  FFABS(neigh->mv[0].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 8)
417  return 1;
418  else
419  return 0;
420  } else {
421  return 1;
422  }
423  } else if ((curr->pred_flag != PF_BI) && (neigh->pred_flag != PF_BI)){ // 1 MV
424  Mv A, B;
425  int ref_A, ref_B;
426 
427  if (curr->pred_flag & 1) {
428  A = curr->mv[0];
429  ref_A = rpl[L0].refs[curr->ref_idx[L0]].poc;
430  } else {
431  A = curr->mv[1];
432  ref_A = rpl[L1].refs[curr->ref_idx[L1]].poc;
433  }
434 
435  if (neigh->pred_flag & 1) {
436  B = neigh->mv[0];
437  ref_B = neigh_rpl[L0].refs[neigh->ref_idx[L0]].poc;
438  } else {
439  B = neigh->mv[1];
440  ref_B = neigh_rpl[L1].refs[neigh->ref_idx[L1]].poc;
441  }
442 
443  if (ref_A == ref_B) {
444  if (FFABS(A.x - B.x) >= 8 || FFABS(A.y - B.y) >= 8)
445  return 1;
446  else
447  return 0;
448  } else
449  return 1;
450  }
451 
452  return 1;
453 }
454 
455 //part of 8.8.3.3 Derivation process of transform block boundary
456 static void derive_max_filter_length_luma(const VVCFrameContext *fc, const int qx, const int qy,
457  const int size_q, const int has_subblock, const int vertical, uint8_t *max_len_p, uint8_t *max_len_q)
458 {
459  const int px = vertical ? qx - 1 : qx;
460  const int py = !vertical ? qy - 1 : qy;
461  const uint8_t *tb_size = vertical ? fc->tab.tb_width[LUMA] : fc->tab.tb_height[LUMA];
462  const int size_p = tb_size[(py >> MIN_TU_LOG2) * fc->ps.pps->min_tu_width + (px >> MIN_TU_LOG2)];
463  const int min_cb_log2 = fc->ps.sps->min_cb_log2_size_y;
464  const int off_p = (py >> min_cb_log2) * fc->ps.pps->min_cb_width + (px >> min_cb_log2);
465 
466  if (size_p <= 4 || size_q <= 4) {
467  *max_len_p = *max_len_q = 1;
468  } else {
469  *max_len_p = *max_len_q = 3;
470  if (size_p >= 32)
471  *max_len_p = 7;
472  if (size_q >= 32)
473  *max_len_q = 7;
474  }
475  if (has_subblock)
476  *max_len_q = FFMIN(5, *max_len_q);
477  if (fc->tab.msf[off_p] || fc->tab.iaf[off_p])
478  *max_len_p = FFMIN(5, *max_len_p);
479 }
480 
482  const int cb, int x0, int y0, int width, int height, const int vertical)
483 {
484  const VVCFrameContext *fc = lc->fc;
485  const MvField *tab_mvf = fc->tab.mvf;
486  const RefPicList *rpl = lc->sc->rpl;
487  int stridea = fc->ps.pps->min_pu_width;
488  int strideb = 1;
489  const int log2_min_pu_size = MIN_PU_LOG2;
490 
491  if (!vertical) {
492  FFSWAP(int, x0, y0);
493  FFSWAP(int, width, height);
494  FFSWAP(int, stridea, strideb);
495  }
496 
497  // bs for TU internal vertical PU boundaries
498  for (int i = 8 - ((x0 - cb) % 8); i < width; i += 8) {
499  const int is_vb = is_virtual_boundary(fc, x0 + i, vertical);
500  const int xp_pu = (x0 + i - 1) >> log2_min_pu_size;
501  const int xq_pu = (x0 + i) >> log2_min_pu_size;
502 
503  for (int j = 0; j < height; j += 4) {
504  const int y_pu = (y0 + j) >> log2_min_pu_size;
505  const MvField *mvf_p = &tab_mvf[y_pu * stridea + xp_pu * strideb];
506  const MvField *mvf_q = &tab_mvf[y_pu * stridea + xq_pu * strideb];
507  const int bs = is_vb ? 0 : boundary_strength(lc, mvf_q, mvf_p, rpl);
508  int x = x0 + i;
509  int y = y0 + j;
510  uint8_t max_len_p = 0, max_len_q = 0;
511 
512  if (!vertical)
513  FFSWAP(int, x, y);
514 
515  TAB_BS(fc->tab.bs[vertical][LUMA], x, y) = bs;
516 
517  if (i == 4 || i == width - 4)
518  max_len_p = max_len_q = 1;
519  else if (i == 8 || i == width - 8)
520  max_len_p = max_len_q = 2;
521  else
522  max_len_p = max_len_q = 3;
523 
524  TAB_MAX_LEN(fc->tab.max_len_p[vertical], x, y) = max_len_p;
525  TAB_MAX_LEN(fc->tab.max_len_q[vertical], x, y) = max_len_q;
526  }
527  }
528 }
529 
531  const int x_p, const int y_p, const int x_q, const int y_q, const CodingUnit *cu, const TransformUnit *tu,
532  const RefPicList *rpl_p, const int c_idx, const int off_to_cb, const uint8_t has_sub_block)
533 {
534  const VVCFrameContext *fc = lc->fc;
535  const MvField *tab_mvf = fc->tab.mvf;
536  const int log2_min_pu_size = MIN_PU_LOG2;
537  const int log2_min_tu_size = MIN_TU_LOG2;
538  const int log2_min_cb_size = fc->ps.sps->min_cb_log2_size_y;
539  const int min_pu_width = fc->ps.pps->min_pu_width;
540  const int min_tu_width = fc->ps.pps->min_tu_width;
541  const int min_cb_width = fc->ps.pps->min_cb_width;
542  const int pu_p = (y_p >> log2_min_pu_size) * min_pu_width + (x_p >> log2_min_pu_size);
543  const int pu_q = (y_q >> log2_min_pu_size) * min_pu_width + (x_q >> log2_min_pu_size);
544  const MvField *mvf_p = &tab_mvf[pu_p];
545  const MvField *mvf_q = &tab_mvf[pu_q];
546  const uint8_t chroma = !!c_idx;
547  const int tu_p = (y_p >> log2_min_tu_size) * min_tu_width + (x_p >> log2_min_tu_size);
548  const int cb_p = (y_p >> log2_min_cb_size) * min_cb_width + (x_p >> log2_min_cb_size);
549  const uint8_t pcmf = fc->tab.pcmf[chroma][cb_p] && cu->bdpcm_flag[chroma];
550  const uint8_t intra = fc->tab.cpm[chroma][cb_p] == MODE_INTRA || cu->pred_mode == MODE_INTRA;
551  const uint8_t same_mode = fc->tab.cpm[chroma][cb_p] == cu->pred_mode;
552 
553  if (pcmf)
554  return 0;
555 
556  if (intra || mvf_p->ciip_flag || mvf_q->ciip_flag)
557  return 2;
558 
559  if (chroma) {
560  return fc->tab.tu_coded_flag[c_idx][tu_p] ||
561  fc->tab.tu_joint_cbcr_residual_flag[tu_p] ||
562  tu->coded_flag[c_idx] ||
564  }
565 
566  if (fc->tab.tu_coded_flag[LUMA][tu_p] || tu->coded_flag[LUMA])
567  return 1;
568 
569  if ((off_to_cb && ((off_to_cb % 8) || !has_sub_block)))
570  return 0; // inside a cu, not aligned to 8 or with no subblocks
571 
572  if (!same_mode)
573  return 1;
574 
575  return boundary_strength(lc, mvf_q, mvf_p, rpl_p);
576 }
577 
578 static int deblock_is_boundary(const VVCLocalContext *lc, const int boundary,
579  const int pos, const int rs, const int vertical)
580 {
581  const VVCFrameContext *fc = lc->fc;
582  const H266RawSPS *rsps = fc->ps.sps->r;
583  const H266RawPPS *rpps = fc->ps.pps->r;
584  int flag;
585  if (boundary && (pos % fc->ps.sps->ctb_size_y) == 0) {
587  if (lc->boundary_flags & flag &&
589  return 0;
590 
592  if (lc->boundary_flags & flag &&
594  return 0;
595 
597  if (lc->boundary_flags & flag) {
598  const int q_rs = rs - (vertical ? 1 : fc->ps.pps->ctb_width);
599  const SliceContext *q_slice = lc->fc->slices[lc->fc->tab.slice_idx[q_rs]];
600 
601  if (!rsps->sps_loop_filter_across_subpic_enabled_flag[q_slice->sh.r->curr_subpic_idx] ||
603  return 0;
604  }
605  }
606  return boundary;
607 }
608 
609 static void vvc_deblock_bs_luma(const VVCLocalContext *lc,
610  const int x0, const int y0, const int width, const int height,
611  const CodingUnit *cu, const TransformUnit *tu, int rs, const int vertical)
612 {
613  const VVCFrameContext *fc = lc->fc;
614  const PredictionUnit *pu = &cu->pu;
615  const int mask = LUMA_GRID - 1;
616  const int pos = vertical ? x0 : y0;
617  const int cb = vertical ? cu->x0 : cu->y0;
618  const int is_intra = cu->pred_mode == MODE_INTRA;
619  const int cb_size = vertical ? cu->cb_width : cu->cb_height;
620  const int has_sb = !is_intra && (pu->merge_subblock_flag || pu->inter_affine_flag) && cb_size > 8;
621 
622  if (deblock_is_boundary(lc, pos > 0 && !(pos & mask), pos, rs, vertical)) {
623  const int is_vb = is_virtual_boundary(fc, pos, vertical);
624  const int size = vertical ? height : width;
625  const int size_q = vertical ? width : height;
626  const int off = cb - pos;
627  const int flag = vertical ? BOUNDARY_LEFT_SLICE : BOUNDARY_UPPER_SLICE;
628  const RefPicList *rpl_p =
629  (lc->boundary_flags & flag) ? ff_vvc_get_ref_list(fc, fc->ref, x0 - vertical, y0 - !vertical) : lc->sc->rpl;
630 
631  for (int i = 0; i < size; i += 4) {
632  const int x = x0 + i * !vertical;
633  const int y = y0 + i * vertical;
634  uint8_t max_len_p, max_len_q;
635  const int bs = is_vb ? 0 : deblock_bs(lc, x - vertical, y - !vertical, x, y, cu, tu, rpl_p, LUMA, off, has_sb);
636 
637  TAB_BS(fc->tab.bs[vertical][LUMA], x, y) = bs;
638 
639  derive_max_filter_length_luma(fc, x, y, size_q, has_sb, vertical, &max_len_p, &max_len_q);
640  TAB_MAX_LEN(fc->tab.max_len_p[vertical], x, y) = max_len_p;
641  TAB_MAX_LEN(fc->tab.max_len_q[vertical], x, y) = max_len_q;
642  }
643  }
644 
645  if (has_sb)
646  vvc_deblock_subblock_bs(lc, cb, x0, y0, width, height, vertical);
647 }
648 
650  const int x0, const int y0, const int width, const int height,
651  const CodingUnit *cu, const TransformUnit *tu, const int rs, const int vertical)
652 {
653  const VVCFrameContext *fc = lc->fc;
654  const int shift = (vertical ? fc->ps.sps->hshift : fc->ps.sps->vshift)[CHROMA];
655  const int mask = (CHROMA_GRID << shift) - 1;
656  const int pos = vertical ? x0 : y0;
657 
658  if (deblock_is_boundary(lc, pos > 0 && !(pos & mask), pos, rs, vertical)) {
659  const int is_vb = is_virtual_boundary(fc, pos, vertical);
660  const int size = vertical ? height : width;
661 
662  for (int c_idx = CB; c_idx <= CR; c_idx++) {
663  for (int i = 0; i < size; i += 2) {
664  const int x = x0 + i * !vertical;
665  const int y = y0 + i * vertical;
666  const int bs = is_vb ? 0 : deblock_bs(lc, x - vertical, y - !vertical, x, y, cu, tu, NULL, c_idx, 0, 0);
667 
668  TAB_BS(fc->tab.bs[vertical][c_idx], x, y) = bs;
669  }
670  }
671  }
672 }
673 
674 typedef void (*deblock_bs_fn)(const VVCLocalContext *lc, const int x0, const int y0,
675  const int width, const int height, const int rs, const int vertical);
676 
677 void ff_vvc_deblock_bs(VVCLocalContext *lc, const int rx, const int ry, const int rs)
678 {
679  const VVCFrameContext *fc = lc->fc;
680  const VVCSPS *sps = fc->ps.sps;
681  const int x0 = rx << sps->ctb_log2_size_y;
682  const int y0 = ry << sps->ctb_log2_size_y;
683 
684  ff_vvc_decode_neighbour(lc, x0, y0, rx, ry, rs);
685  for (const CodingUnit *cu = fc->tab.cus[rs]; cu; cu = cu->next) {
686  for (const TransformUnit *tu = cu->tus.head; tu; tu = tu->next) {
687  for (int vertical = 0; vertical <= 1; vertical++) {
688  if (tu->avail[LUMA])
689  vvc_deblock_bs_luma(lc, tu->x0, tu->y0, tu->width, tu->height, cu, tu, rs, vertical);
690  if (tu->avail[CHROMA]) {
691  if (cu->isp_split_type != ISP_NO_SPLIT && cu->tree_type == SINGLE_TREE)
692  vvc_deblock_bs_chroma(lc, cu->x0, cu->y0, cu->cb_width, cu->cb_height, cu, tu, rs, vertical);
693  else
694  vvc_deblock_bs_chroma(lc, tu->x0, tu->y0, tu->width, tu->height, cu, tu, rs, vertical);
695  }
696  }
697  }
698  }
699 }
700 
701 //part of 8.8.3.3 Derivation process of transform block boundary
702 static void max_filter_length_luma(const VVCFrameContext *fc, const int qx, const int qy,
703  const int vertical, uint8_t *max_len_p, uint8_t *max_len_q)
704 {
705  *max_len_p = TAB_MAX_LEN(fc->tab.max_len_p[vertical], qx, qy);
706  *max_len_q = TAB_MAX_LEN(fc->tab.max_len_q[vertical], qx, qy);
707 }
708 
709 //part of 8.8.3.3 Derivation process of transform block boundary
710 static void max_filter_length_chroma(const VVCFrameContext *fc, const int qx, const int qy,
711  const int vertical, const int horizontal_ctu_edge, const int bs, uint8_t *max_len_p, uint8_t *max_len_q)
712 {
713  const int px = vertical ? qx - 1 : qx;
714  const int py = !vertical ? qy - 1 : qy;
715  const uint8_t *tb_size = vertical ? fc->tab.tb_width[CHROMA] : fc->tab.tb_height[CHROMA];
716 
717  const int size_p = tb_size[(py >> MIN_TU_LOG2) * fc->ps.pps->min_tu_width + (px >> MIN_TU_LOG2)];
718  const int size_q = tb_size[(qy >> MIN_TU_LOG2) * fc->ps.pps->min_tu_width + (qx >> MIN_TU_LOG2)];
719  if (size_p >= 8 && size_q >= 8) {
720  *max_len_p = *max_len_q = 3;
721  if (horizontal_ctu_edge)
722  *max_len_p = 1;
723  } else {
724  //part of 8.8.3.6.4 Decision process for chroma block edges
725  *max_len_p = *max_len_q = (bs == 2);
726  }
727 }
728 
729 static void max_filter_length(const VVCFrameContext *fc, const int qx, const int qy,
730  const int c_idx, const int vertical, const int horizontal_ctu_edge, const int bs, uint8_t *max_len_p, uint8_t *max_len_q)
731 {
732  if (!c_idx)
733  max_filter_length_luma(fc, qx, qy, vertical, max_len_p, max_len_q);
734  else
735  max_filter_length_chroma(fc, qx, qy, vertical, horizontal_ctu_edge, bs, max_len_p, max_len_q);
736 }
737 
738 #define TC_CALC(qp, bs) \
739  tctable[av_clip((qp) + DEFAULT_INTRA_TC_OFFSET * ((bs) - 1) + \
740  (tc_offset & -2), \
741  0, MAX_QP + DEFAULT_INTRA_TC_OFFSET)]
742 
743 // part of 8.8.3.6.2 Decision process for luma block edges
744 static int get_qp_y(const VVCFrameContext *fc, const uint8_t *src, const int x, const int y, const int vertical)
745 {
746  const VVCSPS *sps = fc->ps.sps;
747  const int qp = (ff_vvc_get_qPy(fc, x - vertical, y - !vertical) + ff_vvc_get_qPy(fc, x, y) + 1) >> 1;
748  int qp_offset = 0;
749  int level;
750 
751  if (!sps->r->sps_ladf_enabled_flag)
752  return qp;
753 
754  level = fc->vvcdsp.lf.ladf_level[vertical](src, fc->frame->linesize[LUMA]);
755  qp_offset = sps->r->sps_ladf_lowest_interval_qp_offset;
756  for (int i = 0; i < sps->num_ladf_intervals - 1 && level > sps->ladf_interval_lower_bound[i + 1]; i++)
757  qp_offset = sps->r->sps_ladf_qp_offset[i];
758 
759  return qp + qp_offset;
760 }
761 
762 // part of 8.8.3.6.2 Decision process for luma block edges
763 static int get_qp_c(const VVCFrameContext *fc, const int x, const int y, const int c_idx, const int vertical)
764 {
765  const VVCSPS *sps = fc->ps.sps;
766  return (get_qPc(fc, x - vertical, y - !vertical, c_idx) + get_qPc(fc, x, y, c_idx) - 2 * sps->qp_bd_offset + 1) >> 1;
767 }
768 
769 static int get_qp(const VVCFrameContext *fc, const uint8_t *src, const int x, const int y, const int c_idx, const int vertical)
770 {
771  if (!c_idx)
772  return get_qp_y(fc, src, x, y, vertical);
773  return get_qp_c(fc, x, y, c_idx, vertical);
774 }
775 
776 static void vvc_deblock(const VVCLocalContext *lc, int x0, int y0, const int rs, const int vertical)
777 {
778  VVCFrameContext *fc = lc->fc;
779  const VVCSPS *sps = fc->ps.sps;
780  const int c_end = sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1;
781  const int ctb_size = fc->ps.sps->ctb_size_y;
782  const DBParams *params = fc->tab.deblock + rs;
783  int x_end = FFMIN(x0 + ctb_size, fc->ps.pps->width);
784  int y_end = FFMIN(y0 + ctb_size, fc->ps.pps->height);
785  const int log2_min_cb_size = fc->ps.sps->min_cb_log2_size_y;
786  const int min_cb_width = fc->ps.pps->min_cb_width;
787 
788  if (!vertical) {
789  FFSWAP(int, x_end, y_end);
790  FFSWAP(int, x0, y0);
791  }
792 
793  for (int c_idx = 0; c_idx < c_end; c_idx++) {
794  const int hs = (vertical ? sps->hshift : sps->vshift)[c_idx];
795  const int vs = (vertical ? sps->vshift : sps->hshift)[c_idx];
796  const int grid = c_idx ? (CHROMA_GRID << hs) : LUMA_GRID;
797  const int tc_offset = params->tc_offset[c_idx];
798  const int beta_offset = params->beta_offset[c_idx];
799  const int src_stride = fc->frame->linesize[c_idx];
800 
801  for (int y = y0; y < y_end; y += (DEBLOCK_STEP << vs)) {
802  for (int x = x0 ? x0 : grid; x < x_end; x += grid) {
803  const uint8_t horizontal_ctu_edge = !vertical && !(x % ctb_size);
804  int32_t bs[4], beta[4], tc[4] = { 0 }, all_zero_bs = 1;
805  uint8_t max_len_p[4], max_len_q[4];
806  uint8_t no_p[4] = { 0 };
807  uint8_t no_q[4] = { 0 };
808 
809  for (int i = 0; i < DEBLOCK_STEP >> (2 - vs); i++) {
810  int tx = x;
811  int ty = y + (i << 2);
812  const int end = ty >= y_end;
813 
814  if (!vertical)
815  FFSWAP(int, tx, ty);
816 
817  bs[i] = end ? 0 : TAB_BS(fc->tab.bs[vertical][c_idx], tx, ty);
818  if (bs[i]) {
819  const int qp = get_qp(fc, POS(c_idx, tx, ty), tx, ty, c_idx, vertical);
820  beta[i] = betatable[av_clip(qp + beta_offset, 0, MAX_QP)];
821  tc[i] = TC_CALC(qp, bs[i]) ;
822  max_filter_length(fc, tx, ty, c_idx, vertical, horizontal_ctu_edge, bs[i], &max_len_p[i], &max_len_q[i]);
823  all_zero_bs = 0;
824 
825  if (sps->r->sps_palette_enabled_flag) {
826  const int cu_q = (ty >> log2_min_cb_size) * min_cb_width + (tx >> log2_min_cb_size);
827  const int cu_p = (ty - !vertical >> log2_min_cb_size) * min_cb_width + (tx - vertical >> log2_min_cb_size);
828  no_q[i] = fc->tab.cpm[!!c_idx][cu_q] == MODE_PLT;
829  no_p[i] = cu_p >= 0 && fc->tab.cpm[!!c_idx][cu_p] == MODE_PLT;
830  }
831  }
832  }
833 
834  if (!all_zero_bs) {
835  uint8_t *src = vertical ? POS(c_idx, x, y) : POS(c_idx, y, x);
836  if (!c_idx)
837  fc->vvcdsp.lf.filter_luma[vertical](src, src_stride, beta, tc, no_p, no_q, max_len_p, max_len_q, horizontal_ctu_edge);
838  else
839  fc->vvcdsp.lf.filter_chroma[vertical](src, src_stride, beta, tc, no_p, no_q, max_len_p, max_len_q, vs);
840  }
841  }
842  }
843  }
844 }
845 
846 void ff_vvc_deblock_vertical(const VVCLocalContext *lc, const int x0, const int y0, const int rs)
847 {
848  vvc_deblock(lc, x0, y0, rs, 1);
849 }
850 
851 void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, const int x0, const int y0, const int rs)
852 {
853  vvc_deblock(lc, x0, y0, rs, 0);
854 }
855 
856 static void alf_copy_border(uint8_t *dst, const uint8_t *src,
857  const int pixel_shift, int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride)
858 {
859  width <<= pixel_shift;
860  for (int i = 0; i < height; i++) {
861  memcpy(dst, src, width);
862  dst += dst_stride;
863  src += src_stride;
864  }
865 }
866 
867 static void alf_extend_vert(uint8_t *_dst, const uint8_t *_src,
868  const int pixel_shift, const int width, const int height, ptrdiff_t stride)
869 {
870  if (pixel_shift == 0) {
871  for (int i = 0; i < height; i++) {
872  memset(_dst, *_src, width);
873  _src += stride;
874  _dst += stride;
875  }
876  } else {
877  const uint16_t *src = (const uint16_t *)_src;
878  uint16_t *dst = (uint16_t *)_dst;
879  stride >>= pixel_shift;
880 
881  for (int i = 0; i < height; i++) {
882  for (int j = 0; j < width; j++)
883  dst[j] = *src;
884  src += stride;
885  dst += stride;
886  }
887  }
888 }
889 
890 static void alf_extend_horz(uint8_t *dst, const uint8_t *src,
891  const int pixel_shift, int width, const int height, const ptrdiff_t stride)
892 {
893  width <<= pixel_shift;
894  for (int i = 0; i < height; i++) {
895  memcpy(dst, src, width);
896  dst += stride;
897  }
898 }
899 
900 static void alf_copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src, const ptrdiff_t src_stride,
901  const int x, const int y, const int width, const int height, const int rx, const int ry, const int c_idx)
902 {
903  const int ps = fc->ps.sps->pixel_shift;
904  const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
905  const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
906  const int border_pixels = (c_idx == 0) ? ALF_BORDER_LUMA : ALF_BORDER_CHROMA;
907  const int offset_h[] = { 0, height - border_pixels };
908  const int offset_v[] = { 0, width - border_pixels };
909 
910  /* copy horizontal edges */
911  for (int i = 0; i < FF_ARRAY_ELEMS(offset_h); i++) {
912  alf_copy_border(fc->tab.alf_pixel_buffer_h[c_idx][i] + ((border_pixels * ry * w + x)<< ps),
913  src + offset_h[i] * src_stride, ps, width, border_pixels, w << ps, src_stride);
914  }
915  /* copy vertical edges */
916  for (int i = 0; i < FF_ARRAY_ELEMS(offset_v); i++) {
917  alf_copy_border(fc->tab.alf_pixel_buffer_v[c_idx][i] + ((h * rx + y) * (border_pixels << ps)),
918  src + (offset_v[i] << ps), ps, border_pixels, height, border_pixels << ps, src_stride);
919  }
920 }
921 
922 static void alf_fill_border_h(uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src, const ptrdiff_t src_stride,
923  const uint8_t *border, const int width, const int border_pixels, const int ps, const int edge)
924 {
925  if (edge)
926  alf_extend_horz(dst, border, ps, width, border_pixels, dst_stride);
927  else
928  alf_copy_border(dst, src, ps, width, border_pixels, dst_stride, src_stride);
929 }
930 
931 static void alf_fill_border_v(uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src,
932  const uint8_t *border, const int border_pixels, const int height, const int pixel_shift, const int *edges, const int edge)
933 {
934  const ptrdiff_t src_stride = (border_pixels << pixel_shift);
935 
936  if (edge) {
937  alf_extend_vert(dst, border, pixel_shift, border_pixels, height + 2 * border_pixels, dst_stride);
938  return;
939  }
940 
941  //left/right
942  alf_copy_border(dst + dst_stride * border_pixels * edges[TOP], src + src_stride * border_pixels * edges[TOP],
943  pixel_shift, border_pixels, height + (!edges[TOP] + !edges[BOTTOM]) * border_pixels, dst_stride, src_stride);
944 
945  //top left/right
946  if (edges[TOP])
947  alf_extend_horz(dst, dst + dst_stride * border_pixels, pixel_shift, border_pixels, border_pixels, dst_stride);
948 
949  //bottom left/right
950  if (edges[BOTTOM]) {
951  dst += dst_stride * (border_pixels + height);
952  alf_extend_horz(dst, dst - dst_stride, pixel_shift, border_pixels, border_pixels, dst_stride);
953  }
954 }
955 
956 static void alf_prepare_buffer(VVCFrameContext *fc, uint8_t *_dst, const uint8_t *_src, const int x, const int y,
957  const int rx, const int ry, const int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride,
958  const int c_idx, const int *edges)
959 {
960  const int ps = fc->ps.sps->pixel_shift;
961  const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
962  const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
963  const int border_pixels = c_idx == 0 ? ALF_BORDER_LUMA : ALF_BORDER_CHROMA;
964  uint8_t *dst, *src;
965 
966  copy_ctb(_dst, _src, width << ps, height, dst_stride, src_stride);
967 
968  //top
969  src = fc->tab.alf_pixel_buffer_h[c_idx][1] + (((border_pixels * w) << ps) * (ry - 1) + (x << ps));
970  dst = _dst - border_pixels * dst_stride;
971  alf_fill_border_h(dst, dst_stride, src, w << ps, _dst, width, border_pixels, ps, edges[TOP]);
972 
973  //bottom
974  src = fc->tab.alf_pixel_buffer_h[c_idx][0] + (((border_pixels * w) << ps) * (ry + 1) + (x << ps));
975  dst = _dst + height * dst_stride;
976  alf_fill_border_h(dst, dst_stride, src, w << ps, _dst + (height - 1) * dst_stride, width, border_pixels, ps, edges[BOTTOM]);
977 
978 
979  //left
980  src = fc->tab.alf_pixel_buffer_v[c_idx][1] + (h * (rx - 1) + y - border_pixels) * (border_pixels << ps);
981  dst = _dst - (border_pixels << ps) - border_pixels * dst_stride;
982  alf_fill_border_v(dst, dst_stride, src, dst + (border_pixels << ps), border_pixels, height, ps, edges, edges[LEFT]);
983 
984  //right
985  src = fc->tab.alf_pixel_buffer_v[c_idx][0] + (h * (rx + 1) + y - border_pixels) * (border_pixels << ps);
986  dst = _dst + (width << ps) - border_pixels * dst_stride;
987  alf_fill_border_v(dst, dst_stride, src, dst - (1 << ps), border_pixels, height, ps, edges, edges[RIGHT]);
988 }
989 
990 #define ALF_MAX_BLOCKS_IN_CTU (MAX_CTU_SIZE * MAX_CTU_SIZE / ALF_BLOCK_SIZE / ALF_BLOCK_SIZE)
991 #define ALF_MAX_FILTER_SIZE (ALF_MAX_BLOCKS_IN_CTU * ALF_NUM_COEFF_LUMA)
992 
993 static void alf_get_coeff_and_clip(VVCLocalContext *lc, int16_t *coeff, int16_t *clip,
994  const uint8_t *src, ptrdiff_t src_stride, int width, int height, int vb_pos, const ALFParams *alf)
995 {
996  const VVCFrameContext *fc = lc->fc;
997  const H266RawSliceHeader *rsh = lc->sc->sh.r;
998  uint8_t fixed_clip_set[ALF_NUM_FILTERS_LUMA][ALF_NUM_COEFF_LUMA] = { 0 };
999  const int16_t *coeff_set;
1000  const uint8_t *clip_idx_set;
1001  const uint8_t *class_to_filt;
1002  const int size = width * height / ALF_BLOCK_SIZE / ALF_BLOCK_SIZE;
1003  int class_idx[ALF_MAX_BLOCKS_IN_CTU];
1004  int transpose_idx[ALF_MAX_BLOCKS_IN_CTU];
1005 
1006  if (alf->ctb_filt_set_idx_y < 16) {
1007  coeff_set = &ff_vvc_alf_fix_filt_coeff[0][0];
1008  clip_idx_set = &fixed_clip_set[0][0];
1009  class_to_filt = ff_vvc_alf_class_to_filt_map[alf->ctb_filt_set_idx_y];
1010  } else {
1011  const int id = rsh->sh_alf_aps_id_luma[alf->ctb_filt_set_idx_y - 16];
1012  const VVCALF *aps = fc->ps.alf_list[id];
1013  coeff_set = &aps->luma_coeff[0][0];
1014  clip_idx_set = &aps->luma_clip_idx[0][0];
1015  class_to_filt = ff_vvc_alf_aps_class_to_filt_map;
1016  }
1017  fc->vvcdsp.alf.classify(class_idx, transpose_idx, src, src_stride, width, height,
1018  vb_pos, lc->alf_gradient_tmp);
1019  fc->vvcdsp.alf.recon_coeff_and_clip(coeff, clip, class_idx, transpose_idx, size,
1020  coeff_set, clip_idx_set, class_to_filt);
1021 }
1022 
1023 static void alf_filter_luma(VVCLocalContext *lc, uint8_t *dst, const uint8_t *src,
1024  const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int x0, const int y0,
1025  const int width, const int height, const int _vb_pos, const ALFParams *alf)
1026 {
1027  const VVCFrameContext *fc = lc->fc;
1028  int vb_pos = _vb_pos - y0;
1029  int16_t *coeff = (int16_t*)lc->tmp;
1030  int16_t *clip = (int16_t *)lc->tmp1;
1031 
1032  av_assert0(ALF_MAX_FILTER_SIZE <= sizeof(lc->tmp));
1033  av_assert0(ALF_MAX_FILTER_SIZE * sizeof(int16_t) <= sizeof(lc->tmp1));
1034 
1035  alf_get_coeff_and_clip(lc, coeff, clip, src, src_stride, width, height, vb_pos, alf);
1036  fc->vvcdsp.alf.filter[LUMA](dst, dst_stride, src, src_stride, width, height, coeff, clip, vb_pos);
1037 }
1038 
1039 static int alf_clip_from_idx(const VVCFrameContext *fc, const int idx)
1040 {
1041  const VVCSPS *sps = fc->ps.sps;
1042  const int offset[] = {0, 3, 5, 7};
1043 
1044  return 1 << (sps->bit_depth - offset[idx]);
1045 }
1046 
1047 static void alf_filter_chroma(VVCLocalContext *lc, uint8_t *dst, const uint8_t *src,
1048  const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int c_idx,
1049  const int width, const int height, const int vb_pos, const ALFParams *alf)
1050 {
1051  VVCFrameContext *fc = lc->fc;
1052  const H266RawSliceHeader *rsh = lc->sc->sh.r;
1053  const VVCALF *aps = fc->ps.alf_list[rsh->sh_alf_aps_id_chroma];
1054  const int idx = alf->alf_ctb_filter_alt_idx[c_idx - 1];
1055  const int16_t *coeff = aps->chroma_coeff[idx];
1056  int16_t clip[ALF_NUM_COEFF_CHROMA];
1057 
1058  for (int i = 0; i < ALF_NUM_COEFF_CHROMA; i++)
1059  clip[i] = alf_clip_from_idx(fc, aps->chroma_clip_idx[idx][i]);
1060 
1061  fc->vvcdsp.alf.filter[CHROMA](dst, dst_stride, src, src_stride, width, height, coeff, clip, vb_pos);
1062 }
1063 
1064 static void alf_filter_cc(VVCLocalContext *lc, uint8_t *dst, const uint8_t *luma,
1065  const ptrdiff_t dst_stride, const ptrdiff_t luma_stride, const int c_idx,
1066  const int width, const int height, const int hs, const int vs, const int vb_pos, const ALFParams *alf)
1067 {
1068  const VVCFrameContext *fc = lc->fc;
1069  const H266RawSliceHeader *rsh = lc->sc->sh.r;
1070  const int idx = c_idx - 1;
1071  const int cc_aps_id = c_idx == CB ? rsh->sh_alf_cc_cb_aps_id : rsh->sh_alf_cc_cr_aps_id;
1072  const VVCALF *aps = fc->ps.alf_list[cc_aps_id];
1073 
1074  if (aps) {
1075  const int16_t *coeff = aps->cc_coeff[idx][alf->ctb_cc_idc[idx] - 1];
1076 
1077  fc->vvcdsp.alf.filter_cc(dst, dst_stride, luma, luma_stride, width, height, hs, vs, coeff, vb_pos);
1078  }
1079 }
1080 
1081 void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext* lc, const int x0, const int y0)
1082 {
1083  VVCFrameContext *fc = lc->fc;
1084  const int rx = x0 >> fc->ps.sps->ctb_log2_size_y;
1085  const int ry = y0 >> fc->ps.sps->ctb_log2_size_y;
1086  const int ctb_size_y = fc->ps.sps->ctb_size_y;
1087  const int c_end = fc->ps.sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1;
1088 
1089  for (int c_idx = 0; c_idx < c_end; c_idx++) {
1090  const int hs = fc->ps.sps->hshift[c_idx];
1091  const int vs = fc->ps.sps->vshift[c_idx];
1092  const int x = x0 >> hs;
1093  const int y = y0 >> vs;
1094  const int width = FFMIN(fc->ps.pps->width - x0, ctb_size_y) >> hs;
1095  const int height = FFMIN(fc->ps.pps->height - y0, ctb_size_y) >> vs;
1096 
1097  const int src_stride = fc->frame->linesize[c_idx];
1098  uint8_t *src = POS(c_idx, x0, y0);
1099 
1100  alf_copy_ctb_to_hv(fc, src, src_stride, x, y, width, height, rx, ry, c_idx);
1101  }
1102 }
1103 
1104 static void alf_get_edges(const VVCLocalContext *lc, int edges[MAX_EDGES], const int rx, const int ry)
1105 {
1106  VVCFrameContext *fc = lc->fc;
1107  const VVCSPS *sps = fc->ps.sps;
1108  const VVCPPS *pps = fc->ps.pps;
1109  const int subpic_idx = lc->sc->sh.r->curr_subpic_idx;
1110 
1111  // we can't use |= instead of || in this function; |= is not a shortcut operator
1112 
1113  if (!pps->r->pps_loop_filter_across_tiles_enabled_flag) {
1114  edges[LEFT] = edges[LEFT] || (lc->boundary_flags & BOUNDARY_LEFT_TILE);
1115  edges[TOP] = edges[TOP] || (lc->boundary_flags & BOUNDARY_UPPER_TILE);
1116  edges[RIGHT] = edges[RIGHT] || pps->ctb_to_col_bd[rx] != pps->ctb_to_col_bd[rx + 1];
1117  edges[BOTTOM] = edges[BOTTOM] || pps->ctb_to_row_bd[ry] != pps->ctb_to_row_bd[ry + 1];
1118  }
1119 
1120  if (!pps->r->pps_loop_filter_across_slices_enabled_flag) {
1121  edges[LEFT] = edges[LEFT] || (lc->boundary_flags & BOUNDARY_LEFT_SLICE);
1122  edges[TOP] = edges[TOP] || (lc->boundary_flags & BOUNDARY_UPPER_SLICE);
1123  edges[RIGHT] = edges[RIGHT] || CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx + 1, ry);
1124  edges[BOTTOM] = edges[BOTTOM] || CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx, ry + 1);
1125  }
1126 
1127  if (!sps->r->sps_loop_filter_across_subpic_enabled_flag[subpic_idx]) {
1128  edges[LEFT] = edges[LEFT] || (lc->boundary_flags & BOUNDARY_LEFT_SUBPIC);
1129  edges[TOP] = edges[TOP] || (lc->boundary_flags & BOUNDARY_UPPER_SUBPIC);
1130  edges[RIGHT] = edges[RIGHT] || fc->ps.sps->r->sps_subpic_ctu_top_left_x[subpic_idx] + fc->ps.sps->r->sps_subpic_width_minus1[subpic_idx] == rx;
1131  edges[BOTTOM] = edges[BOTTOM] || fc->ps.sps->r->sps_subpic_ctu_top_left_y[subpic_idx] + fc->ps.sps->r->sps_subpic_height_minus1[subpic_idx] == ry;
1132  }
1133 
1134  if (sps->r->sps_virtual_boundaries_enabled_flag) {
1135  edges[LEFT] = edges[LEFT] || is_virtual_boundary(fc, rx << sps->ctb_log2_size_y, 1);
1136  edges[TOP] = edges[TOP] || is_virtual_boundary(fc, ry << sps->ctb_log2_size_y, 0);
1137  edges[RIGHT] = edges[RIGHT] || is_virtual_boundary(fc, (rx + 1) << sps->ctb_log2_size_y, 1);
1138  edges[BOTTOM] = edges[BOTTOM] || is_virtual_boundary(fc, (ry + 1) << sps->ctb_log2_size_y, 0);
1139  }
1140 }
1141 
1142 static void alf_init_subblock(VVCRect *sb, int sb_edges[MAX_EDGES], const VVCRect *b, const int edges[MAX_EDGES])
1143 {
1144  *sb = *b;
1145  memcpy(sb_edges, edges, sizeof(int) * MAX_EDGES);
1146 }
1147 
1148 static void alf_get_subblock(VVCRect *sb, int edges[MAX_EDGES], const int bx, const int by, const int vb_pos[2], const int has_vb[2])
1149 {
1150  int *pos[] = { &sb->l, &sb->t, &sb->r, &sb->b };
1151 
1152  for (int vertical = 0; vertical <= 1; vertical++) {
1153  if (has_vb[vertical]) {
1154  const int c = vertical ? (bx ? LEFT : RIGHT) : (by ? TOP : BOTTOM);
1155  *pos[c] = vb_pos[vertical];
1156  edges[c] = 1;
1157  }
1158  }
1159 }
1160 
1161 static void alf_get_subblocks(const VVCLocalContext *lc, VVCRect sbs[MAX_VBBS], int sb_edges[MAX_VBBS][MAX_EDGES], int *nb_sbs,
1162  const int x0, const int y0, const int rx, const int ry)
1163 {
1164  VVCFrameContext *fc = lc->fc;
1165  const VVCSPS *sps = fc->ps.sps;
1166  const VVCPPS *pps = fc->ps.pps;
1167  const int ctu_size_y = sps->ctb_size_y;
1168  const int vb_pos[] = { get_virtual_boundary(fc, ry, 0), get_virtual_boundary(fc, rx, 1) };
1169  const int has_vb[] = { vb_pos[0] > y0, vb_pos[1] > x0 };
1170  const VVCRect b = { x0, y0, FFMIN(x0 + ctu_size_y, pps->width), FFMIN(y0 + ctu_size_y, pps->height) };
1171  int edges[MAX_EDGES] = { !rx, !ry, rx == pps->ctb_width - 1, ry == pps->ctb_height - 1 };
1172  int i = 0;
1173 
1174  alf_get_edges(lc, edges, rx, ry);
1175 
1176  for (int by = 0; by <= has_vb[0]; by++) {
1177  for (int bx = 0; bx <= has_vb[1]; bx++, i++) {
1178  alf_init_subblock(sbs + i, sb_edges[i], &b, edges);
1179  alf_get_subblock(sbs + i, sb_edges[i], bx, by, vb_pos, has_vb);
1180  }
1181  }
1182  *nb_sbs = i;
1183 }
1184 
1185 void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0)
1186 {
1187  VVCFrameContext *fc = lc->fc;
1188  const VVCSPS *sps = fc->ps.sps;
1189  const int rx = x0 >> sps->ctb_log2_size_y;
1190  const int ry = y0 >> sps->ctb_log2_size_y;
1191  const int ps = sps->pixel_shift;
1192  const int padded_stride = EDGE_EMU_BUFFER_STRIDE << ps;
1193  const int padded_offset = padded_stride * ALF_PADDING_SIZE + (ALF_PADDING_SIZE << ps);
1194  const int c_end = sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1;
1195  const int has_chroma = !!sps->r->sps_chroma_format_idc;
1196  const int ctu_end = y0 + sps->ctb_size_y;
1197  const ALFParams *alf = &CTB(fc->tab.alf, rx, ry);
1198  int sb_edges[MAX_VBBS][MAX_EDGES], nb_sbs;
1199  VVCRect sbs[MAX_VBBS];
1200 
1201  alf_get_subblocks(lc, sbs, sb_edges, &nb_sbs, x0, y0, rx, ry);
1202 
1203  for (int i = 0; i < nb_sbs; i++) {
1204  const VVCRect *sb = sbs + i;
1205  for (int c_idx = 0; c_idx < c_end; c_idx++) {
1206  const int hs = fc->ps.sps->hshift[c_idx];
1207  const int vs = fc->ps.sps->vshift[c_idx];
1208  const int x = sb->l >> hs;
1209  const int y = sb->t >> vs;
1210  const int width = (sb->r - sb->l) >> hs;
1211  const int height = (sb->b - sb->t) >> vs;
1212  const int src_stride = fc->frame->linesize[c_idx];
1213  uint8_t *src = POS(c_idx, sb->l, sb->t);
1214  uint8_t *padded;
1215 
1216  if (alf->ctb_flag[c_idx] || (!c_idx && has_chroma && (alf->ctb_cc_idc[0] || alf->ctb_cc_idc[1]))) {
1217  padded = (c_idx ? lc->alf_buffer_chroma : lc->alf_buffer_luma) + padded_offset;
1218  alf_prepare_buffer(fc, padded, src, x, y, rx, ry, width, height,
1219  padded_stride, src_stride, c_idx, sb_edges[i]);
1220  }
1221  if (alf->ctb_flag[c_idx]) {
1222  if (!c_idx) {
1223  alf_filter_luma(lc, src, padded, src_stride, padded_stride, x, y,
1224  width, height, ctu_end - ALF_VB_POS_ABOVE_LUMA, alf);
1225  } else {
1226  alf_filter_chroma(lc, src, padded, src_stride, padded_stride, c_idx,
1227  width, height, ((ctu_end - sb->t) >> vs) - ALF_VB_POS_ABOVE_CHROMA, alf);
1228  }
1229  }
1230  if (c_idx && alf->ctb_cc_idc[c_idx - 1]) {
1231  padded = lc->alf_buffer_luma + padded_offset;
1232  alf_filter_cc(lc, src, padded, src_stride, padded_stride, c_idx,
1233  width, height, hs, vs, ctu_end - sb->t - ALF_VB_POS_ABOVE_LUMA, alf);
1234  }
1235  }
1236  }
1237 }
1238 
1239 
1240 void ff_vvc_lmcs_filter(const VVCLocalContext *lc, const int x, const int y)
1241 {
1242  const SliceContext *sc = lc->sc;
1243  const VVCFrameContext *fc = lc->fc;
1244  const int ctb_size = fc->ps.sps->ctb_size_y;
1245  const int width = FFMIN(fc->ps.pps->width - x, ctb_size);
1246  const int height = FFMIN(fc->ps.pps->height - y, ctb_size);
1247  uint8_t *data = POS(LUMA, x, y);
1248  if (sc->sh.r->sh_lmcs_used_flag)
1249  fc->vvcdsp.lmcs.filter(data, fc->frame->linesize[LUMA], width, height, &fc->ps.lmcs.inv_lut);
1250 }
sao_restore_vb
static void sao_restore_vb(uint8_t *dst, ptrdiff_t dst_stride, const uint8_t *src, ptrdiff_t src_stride, const int width, const int height, const int vb_pos, const int ps, const int vertical)
Definition: filter.c:296
A
#define A(x)
Definition: vpx_arith.h:28
VVCSPS
Definition: ps.h:58
_dst
uint8_t * _dst
Definition: dsp.h:56
DBParams
Definition: hevcdec.h:351
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
H266RawSPS::sps_subpic_height_minus1
uint16_t sps_subpic_height_minus1[VVC_MAX_SLICES]
Definition: cbs_h266.h:338
ALF_BORDER_LUMA
#define ALF_BORDER_LUMA
Definition: ctu.h:79
TAB_BS
#define TAB_BS(t, x, y)
Definition: filter.c:375
VVCPH
Definition: ps.h:147
level
uint8_t level
Definition: svq3.c:208
derive_max_filter_length_luma
static void derive_max_filter_length_luma(const VVCFrameContext *fc, const int qx, const int qy, const int size_q, const int has_subblock, const int vertical, uint8_t *max_len_p, uint8_t *max_len_q)
Definition: filter.c:456
VVCPPS
Definition: ps.h:92
av_clip
#define av_clip
Definition: common.h:100
ff_vvc_sao_filter
void ff_vvc_sao_filter(VVCLocalContext *lc, int x0, int y0)
sao filter for the CTU
Definition: filter.c:314
H266RawPPS::pps_loop_filter_across_tiles_enabled_flag
uint8_t pps_loop_filter_across_tiles_enabled_flag
Definition: cbs_h266.h:531
LUMA
#define LUMA
Definition: filter.c:31
filter.h
POS
#define POS(c_idx, x, y)
Definition: filter.c:38
cb
static double cb(void *priv, double x, double y)
Definition: vf_geq.c:247
SAO_BAND
@ SAO_BAND
Definition: hevcdec.h:166
ALF_VB_POS_ABOVE_LUMA
#define ALF_VB_POS_ABOVE_LUMA
Definition: ctu.h:82
CB
#define CB
Definition: filter.c:32
vvc_deblock
static void vvc_deblock(const VVCLocalContext *lc, int x0, int y0, const int rs, const int vertical)
Definition: filter.c:776
alf_init_subblock
static void alf_init_subblock(VVCRect *sb, int sb_edges[MAX_EDGES], const VVCRect *b, const int edges[MAX_EDGES])
Definition: filter.c:1142
deblock_is_boundary
static int deblock_is_boundary(const VVCLocalContext *lc, const int boundary, const int pos, const int rs, const int vertical)
Definition: filter.c:578
PF_IBC
@ PF_IBC
Definition: ctu.h:227
alf_prepare_buffer
static void alf_prepare_buffer(VVCFrameContext *fc, uint8_t *_dst, const uint8_t *_src, const int x, const int y, const int rx, const int ry, const int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int c_idx, const int *edges)
Definition: filter.c:956
CodingUnit
Definition: hevcdec.h:292
VVCLocalContext::alf_buffer_chroma
uint8_t alf_buffer_chroma[(MAX_CTU_SIZE+2 *ALF_PADDING_SIZE) *EDGE_EMU_BUFFER_STRIDE *2]
Definition: ctu.h:400
H266RawSPS::sps_loop_filter_across_subpic_enabled_flag
uint8_t sps_loop_filter_across_subpic_enabled_flag[VVC_MAX_SLICES]
Definition: cbs_h266.h:340
VVCLocalContext::tmp
int16_t tmp[MAX_PB_SIZE *MAX_PB_SIZE]
Definition: ctu.h:394
alf_extend_horz
static void alf_extend_horz(uint8_t *dst, const uint8_t *src, const int pixel_shift, int width, const int height, const ptrdiff_t stride)
Definition: filter.c:890
CodingUnit::bdpcm_flag
int bdpcm_flag[VVC_MAX_SAMPLE_ARRAYS]
BdpcmFlag.
Definition: ctu.h:325
mask
int mask
Definition: mediacodecdec_common.c:154
data.h
max_filter_length
static void max_filter_length(const VVCFrameContext *fc, const int qx, const int qy, const int c_idx, const int vertical, const int horizontal_ctu_edge, const int bs, uint8_t *max_len_p, uint8_t *max_len_q)
Definition: filter.c:729
is_virtual_boundary
static int is_virtual_boundary(const VVCFrameContext *fc, const int pos, const int vertical)
Definition: filter.c:80
ph
static int FUNC() ph(CodedBitstreamContext *ctx, RWContext *rw, H266RawPH *current)
Definition: cbs_h266_syntax_template.c:3043
w
uint8_t w
Definition: llviddspenc.c:38
H266RawSPS::sps_subpic_ctu_top_left_y
uint16_t sps_subpic_ctu_top_left_y[VVC_MAX_SLICES]
Definition: cbs_h266.h:336
ff_vvc_deblock_vertical
void ff_vvc_deblock_vertical(const VVCLocalContext *lc, const int x0, const int y0, const int rs)
vertical deblock filter for the CTU
Definition: filter.c:846
VVCLocalContext::sc
SliceContext * sc
Definition: ctu.h:445
alf_get_coeff_and_clip
static void alf_get_coeff_and_clip(VVCLocalContext *lc, int16_t *coeff, int16_t *clip, const uint8_t *src, ptrdiff_t src_stride, int width, int height, int vb_pos, const ALFParams *alf)
Definition: filter.c:993
ff_vvc_alf_copy_ctu_to_hv
void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext *lc, const int x0, const int y0)
Definition: filter.c:1081
b
#define b
Definition: input.c:42
chroma
static av_always_inline void chroma(WaveformContext *s, AVFrame *in, AVFrame *out, int component, int intensity, int offset_y, int offset_x, int column, int mirror, int jobnr, int nb_jobs)
Definition: vf_waveform.c:1639
data
const char data[16]
Definition: mxf.c:149
Mv::y
int16_t y
vertical component of motion vector
Definition: hevcdec.h:307
deblock_bs
static av_always_inline int deblock_bs(const VVCLocalContext *lc, const int x_p, const int y_p, const int x_q, const int y_q, const CodingUnit *cu, const TransformUnit *tu, const RefPicList *rpl_p, const int c_idx, const int off_to_cb, const uint8_t has_sub_block)
Definition: filter.c:530
SAO_EDGE
@ SAO_EDGE
Definition: hevcdec.h:167
get_qPc
static int get_qPc(const VVCFrameContext *fc, const int x0, const int y0, const int chroma)
Definition: filter.c:85
VVCSH::r
const H266RawSliceHeader * r
RefStruct reference.
Definition: ps.h:239
vvc_deblock_bs_chroma
static void vvc_deblock_bs_chroma(const VVCLocalContext *lc, const int x0, const int y0, const int width, const int height, const CodingUnit *cu, const TransformUnit *tu, const int rs, const int vertical)
Definition: filter.c:649
get_qp_y
static int get_qp_y(const VVCFrameContext *fc, const uint8_t *src, const int x, const int y, const int vertical)
Definition: filter.c:744
VVCRect::t
int t
Definition: ctu.h:481
ff_vvc_deblock_horizontal
void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, const int x0, const int y0, const int rs)
horizontal deblock filter for the CTU
Definition: filter.c:851
RefPicList
Definition: hevcdec.h:196
_src
uint8_t ptrdiff_t const uint8_t * _src
Definition: dsp.h:56
av_image_copy_plane
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:374
VVCFrameContext::slices
SliceContext ** slices
Definition: dec.h:134
BOUNDARY_LEFT_TILE
#define BOUNDARY_LEFT_TILE
Definition: hevcdec.h:442
MIN_PU_LOG2
#define MIN_PU_LOG2
Definition: dec.h:42
H266RawSliceHeader::sh_alf_cc_cr_aps_id
uint8_t sh_alf_cc_cr_aps_id
Definition: cbs_h266.h:792
ALF_NUM_COEFF_CHROMA
#define ALF_NUM_COEFF_CHROMA
Definition: ps.h:168
VVCLocalContext::sao_buffer
uint8_t sao_buffer[(MAX_CTU_SIZE+2 *SAO_PADDING_SIZE) *EDGE_EMU_BUFFER_STRIDE *2]
Definition: ctu.h:398
VVCLocalContext::fc
VVCFrameContext * fc
Definition: ctu.h:446
TAB_MAX_LEN
#define TAB_MAX_LEN(t, x, y)
Definition: filter.c:376
PredictionUnit
Definition: hevcdec.h:325
H266RawSPS::sps_subpic_width_minus1
uint16_t sps_subpic_width_minus1[VVC_MAX_SLICES]
Definition: cbs_h266.h:337
BOTTOM
#define BOTTOM
Definition: filter.c:33
VVCLocalContext::tmp1
int16_t tmp1[MAX_PB_SIZE *MAX_PB_SIZE]
Definition: ctu.h:395
tab
static const struct twinvq_data tab
Definition: twinvq_data.h:10345
sao_copy_ctb_to_hv
static void sao_copy_ctb_to_hv(VVCLocalContext *lc, const int rx, const int ry, const int top)
Definition: filter.c:154
SliceContext::rpl
RefPicList * rpl
Definition: dec.h:118
VVCRect
Definition: ctu.h:479
VVCALF
Definition: ps.h:171
ALF_MAX_FILTER_SIZE
#define ALF_MAX_FILTER_SIZE
Definition: filter.c:991
CodingUnit::cb_width
int cb_width
Definition: ctu.h:291
H266RawPPS::pps_loop_filter_across_slices_enabled_flag
uint8_t pps_loop_filter_across_slices_enabled_flag
Definition: cbs_h266.h:543
CHROMA_GRID
#define CHROMA_GRID
Definition: filter.c:381
CodingUnit::pu
PredictionUnit pu
Definition: ctu.h:338
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
RefPicList::refs
VVCRefPic refs[VVC_MAX_REF_ENTRIES]
Definition: dec.h:58
DBParams::beta_offset
int beta_offset
Definition: hevcdec.h:352
clip
clip
Definition: af_crystalizer.c:122
DBParams::tc_offset
int tc_offset
Definition: hevcdec.h:353
alf_get_subblocks
static void alf_get_subblocks(const VVCLocalContext *lc, VVCRect sbs[MAX_VBBS], int sb_edges[MAX_VBBS][MAX_EDGES], int *nb_sbs, const int x0, const int y0, const int rx, const int ry)
Definition: filter.c:1161
ff_vvc_alf_class_to_filt_map
const uint8_t ff_vvc_alf_class_to_filt_map[16][25]
Definition: data.c:1712
TransformUnit::next
struct TransformUnit * next
RefStruct reference.
Definition: ctu.h:186
max_filter_length_luma
static void max_filter_length_luma(const VVCFrameContext *fc, const int qx, const int qy, const int vertical, uint8_t *max_len_p, uint8_t *max_len_q)
Definition: filter.c:702
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:493
LEFT
#define LEFT
Definition: filter.c:30
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:41
B
#define B
Definition: huffyuv.h:42
TransformUnit::coded_flag
uint8_t coded_flag[VVC_MAX_SAMPLE_ARRAYS]
tu_y_coded_flag, tu_cb_coded_flag, tu_cr_coded_flag
Definition: ctu.h:182
VVCFrameContext::slice_idx
int16_t * slice_idx
Definition: dec.h:154
VVCLocalContext::alf_gradient_tmp
int32_t alf_gradient_tmp[ALF_GRADIENT_SIZE *ALF_GRADIENT_SIZE *ALF_NUM_DIR]
Definition: ctu.h:401
MAX_EDGES
#define MAX_EDGES
Definition: filter.c:34
H266RawSliceHeader::sh_lmcs_used_flag
uint8_t sh_lmcs_used_flag
Definition: cbs_h266.h:794
copy_pixel
static void copy_pixel(uint8_t *dst, const uint8_t *src, const int pixel_shift)
Definition: filter.c:104
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:74
H266RawSPS
Definition: cbs_h266.h:308
H266RawPPS
Definition: cbs_h266.h:496
aps
static int FUNC() aps(CodedBitstreamContext *ctx, RWContext *rw, H266RawAPS *current, int prefix)
Definition: cbs_h266_syntax_template.c:2501
VVCLocalContext::alf_buffer_luma
uint8_t alf_buffer_luma[(MAX_CTU_SIZE+2 *ALF_PADDING_SIZE) *EDGE_EMU_BUFFER_STRIDE *2]
Definition: ctu.h:399
get_virtual_boundary
static int get_virtual_boundary(const VVCFrameContext *fc, const int ctu_pos, const int vertical)
Definition: filter.c:62
betatable
static const uint8_t betatable[64]
Definition: filter.c:52
NULL
#define NULL
Definition: coverity.c:32
VVCLocalContext
Definition: ctu.h:384
H266RawSliceHeader::curr_subpic_idx
uint16_t curr_subpic_idx
CurrSubpicIdx.
Definition: cbs_h266.h:837
get_qp
static int get_qp(const VVCFrameContext *fc, const uint8_t *src, const int x, const int y, const int c_idx, const int vertical)
Definition: filter.c:769
sao_extends_edges
static void sao_extends_edges(uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src, const ptrdiff_t src_stride, const int width, const int height, const VVCFrameContext *fc, const int x0, const int y0, const int rx, const int ry, const int edges[4], const int c_idx)
Definition: filter.c:269
alf_filter_chroma
static void alf_filter_chroma(VVCLocalContext *lc, uint8_t *dst, const uint8_t *src, const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int c_idx, const int width, const int height, const int vb_pos, const ALFParams *alf)
Definition: filter.c:1047
L0
#define L0
Definition: hevcdec.h:58
ALF_MAX_BLOCKS_IN_CTU
#define ALF_MAX_BLOCKS_IN_CTU
Definition: filter.c:990
tctable
static const uint16_t tctable[66]
Definition: filter.c:43
BOUNDARY_UPPER_TILE
#define BOUNDARY_UPPER_TILE
Definition: hevcdec.h:444
MvField::ciip_flag
uint8_t ciip_flag
ciip_flag
Definition: ctu.h:208
Mv::x
int16_t x
horizontal component of motion vector
Definition: hevcdec.h:306
CTB
#define CTB(tab, x, y)
Definition: filter.c:267
PF_BI
@ PF_BI
Definition: hevcdec.h:123
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
TransformUnit
Definition: hevcdec.h:335
sao_copy_hor
static void sao_copy_hor(uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src, const ptrdiff_t src_stride, const int width, const int edges[4], const int ps)
Definition: filter.c:248
ff_vvc_alf_filter
void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0)
alf filter for the CTU
Definition: filter.c:1185
SliceContext
Definition: mss12.h:70
SAOParams::offset_val
int16_t offset_val[3][5]
SaoOffsetVal.
Definition: dsp.h:42
LUMA_GRID
#define LUMA_GRID
Definition: filter.c:380
ff_vvc_decode_neighbour
void ff_vvc_decode_neighbour(VVCLocalContext *lc, const int x_ctb, const int y_ctb, const int rx, const int ry, const int rs)
Definition: ctu.c:2816
H266RawSPS::sps_subpic_ctu_top_left_x
uint16_t sps_subpic_ctu_top_left_x[VVC_MAX_SLICES]
Definition: cbs_h266.h:335
alf_clip_from_idx
static int alf_clip_from_idx(const VVCFrameContext *fc, const int idx)
Definition: filter.c:1039
VVCFrameContext::tab
struct VVCFrameContext::@324 tab
alf_fill_border_v
static void alf_fill_border_v(uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src, const uint8_t *border, const int border_pixels, const int height, const int pixel_shift, const int *edges, const int edge)
Definition: filter.c:931
BOUNDARY_UPPER_SLICE
#define BOUNDARY_UPPER_SLICE
Definition: hevcdec.h:443
height
#define height
Definition: dsp.h:89
get_qp_c
static int get_qp_c(const VVCFrameContext *fc, const int x, const int y, const int c_idx, const int vertical)
Definition: filter.c:763
ALF_PADDING_SIZE
#define ALF_PADDING_SIZE
Definition: ctu.h:76
max_filter_length_chroma
static void max_filter_length_chroma(const VVCFrameContext *fc, const int qx, const int qy, const int vertical, const int horizontal_ctu_edge, const int bs, uint8_t *max_len_p, uint8_t *max_len_q)
Definition: filter.c:710
ff_vvc_lmcs_filter
void ff_vvc_lmcs_filter(const VVCLocalContext *lc, const int x, const int y)
lmcs filter for the CTU
Definition: filter.c:1240
shift
static int shift(int a, int b)
Definition: bonk.c:261
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
ff_vvc_deblock_bs
void ff_vvc_deblock_bs(VVCLocalContext *lc, const int rx, const int ry, const int rs)
derive boundary strength for the CTU
Definition: filter.c:677
size
int size
Definition: twinvq_data.h:10344
sao_can_cross_slices
static int sao_can_cross_slices(const VVCFrameContext *fc, const int rx, const int ry, const int dx, const int dy)
Definition: filter.c:185
ALF_BLOCK_SIZE
#define ALF_BLOCK_SIZE
Definition: ctu.h:77
VVCRefPic::poc
int poc
Definition: dec.h:49
H266RawSliceHeader::sh_alf_aps_id_chroma
uint8_t sh_alf_aps_id_chroma
Definition: cbs_h266.h:788
MvField
Definition: hevcdec.h:310
refs.h
frame.h
VVCRect::l
int l
Definition: ctu.h:480
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
alf_fill_border_h
static void alf_fill_border_h(uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src, const ptrdiff_t src_stride, const uint8_t *border, const int width, const int border_pixels, const int ps, const int edge)
Definition: filter.c:922
RIGHT
#define RIGHT
Definition: filter.c:32
MvField::pred_flag
int8_t pred_flag
Definition: hevcdec.h:313
SAOParams::eo_class
int eo_class[3]
sao_eo_class
Definition: dsp.h:40
ALFParams::ctb_cc_idc
uint8_t ctb_cc_idc[2]
alf_ctb_cc_cb_idc, alf_ctb_cc_cr_idc
Definition: ctu.h:476
H266RawSliceHeader
Definition: cbs_h266.h:771
VVCLocalContext::boundary_flags
int boundary_flags
Definition: ctu.h:443
MODE_INTRA
#define MODE_INTRA
Definition: vp3.c:84
CR
#define CR
Definition: filter.c:33
ff_vvc_alf_aps_class_to_filt_map
const uint8_t ff_vvc_alf_aps_class_to_filt_map[25]
Definition: data.c:1731
alf_extend_vert
static void alf_extend_vert(uint8_t *_dst, const uint8_t *_src, const int pixel_shift, const int width, const int height, ptrdiff_t stride)
Definition: filter.c:867
MODE_PLT
@ MODE_PLT
Definition: ctu.h:193
BOUNDARY_LEFT_SUBPIC
#define BOUNDARY_LEFT_SUBPIC
Definition: ctu.h:437
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ISP_NO_SPLIT
@ ISP_NO_SPLIT
Definition: ctu.h:120
H266RawSliceHeader::sh_alf_aps_id_luma
uint8_t sh_alf_aps_id_luma[8]
Definition: cbs_h266.h:785
ff_vvc_alf_fix_filt_coeff
const int16_t ff_vvc_alf_fix_filt_coeff[64][12]
Definition: data.c:1644
sao_get_edges
static void sao_get_edges(uint8_t vert_edge[2], uint8_t horiz_edge[2], uint8_t diag_edge[4], int *restore, const VVCLocalContext *lc, const int edges[4], const int rx, const int ry)
Definition: filter.c:192
av_always_inline
#define av_always_inline
Definition: attributes.h:49
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
EDGE_EMU_BUFFER_STRIDE
#define EDGE_EMU_BUFFER_STRIDE
Definition: hevcdec.h:68
CodingUnit::x0
int x0
Definition: ctu.h:289
VVCRect::b
int b
Definition: ctu.h:483
SAO_EO_HORIZ
@ SAO_EO_HORIZ
Definition: hevcdec.h:172
VVC_MAX_SAMPLE_ARRAYS
@ VVC_MAX_SAMPLE_ARRAYS
Definition: vvc.h:77
H266RawSliceHeader::sh_alf_cc_cb_aps_id
uint8_t sh_alf_cc_cb_aps_id
Definition: cbs_h266.h:790
SAOParams
Definition: dsp.h:34
vvc_deblock_subblock_bs
static void vvc_deblock_subblock_bs(const VVCLocalContext *lc, const int cb, int x0, int y0, int width, int height, const int vertical)
Definition: filter.c:481
ff_vvc_get_qPy
int ff_vvc_get_qPy(const VVCFrameContext *fc, const int xc, const int yc)
Definition: ctu.c:2883
stride
#define stride
Definition: h264pred_template.c:536
MAX_PB_SIZE
#define MAX_PB_SIZE
Definition: dsp.h:32
BOUNDARY_UPPER_SUBPIC
#define BOUNDARY_UPPER_SUBPIC
Definition: ctu.h:440
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
ALF_NUM_COEFF_LUMA
#define ALF_NUM_COEFF_LUMA
Definition: ps.h:167
CHROMA
@ CHROMA
Definition: vf_waveform.c:49
sps
static int FUNC() sps(CodedBitstreamContext *ctx, RWContext *rw, H264RawSPS *current)
Definition: cbs_h264_syntax_template.c:260
alf_copy_border
static void alf_copy_border(uint8_t *dst, const uint8_t *src, const int pixel_shift, int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride)
Definition: filter.c:856
pos
unsigned int pos
Definition: spdifenc.c:414
ALFParams::alf_ctb_filter_alt_idx
uint8_t alf_ctb_filter_alt_idx[2]
alf_ctb_filter_alt_idx[]
Definition: ctu.h:475
vvc_deblock_bs_luma
static void vvc_deblock_bs_luma(const VVCLocalContext *lc, const int x0, const int y0, const int width, const int height, const CodingUnit *cu, const TransformUnit *tu, int rs, const int vertical)
Definition: filter.c:609
PredictionUnit::inter_affine_flag
uint8_t inter_affine_flag
Definition: ctu.h:260
flag
#define flag(name)
Definition: cbs_av1.c:495
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
id
enum AVCodecID id
Definition: dts2pts.c:367
CodingUnit::cb_height
int cb_height
Definition: ctu.h:292
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
H266RawSPS::sps_virtual_boundaries_enabled_flag
uint8_t sps_virtual_boundaries_enabled_flag
Definition: cbs_h266.h:464
boundary_strength
static int boundary_strength(const VVCLocalContext *lc, const MvField *curr, const MvField *neigh, const RefPicList *neigh_rpl)
Definition: filter.c:383
CodingUnit::pred_mode
enum PredMode pred_mode
PredMode.
Definition: hevcdec.h:296
H266RawSPS::sps_num_subpics_minus1
uint16_t sps_num_subpics_minus1
Definition: cbs_h266.h:332
VVCRect::r
int r
Definition: ctu.h:482
ALFParams::ctb_filt_set_idx_y
uint8_t ctb_filt_set_idx_y
AlfCtbFiltSetIdxY.
Definition: ctu.h:474
MAX_VBBS
#define MAX_VBBS
Definition: filter.c:60
pps
uint64_t pps
Definition: dovi_rpuenc.c:36
SAOParams::type_idx
uint8_t type_idx[3]
sao_type_idx
Definition: dsp.h:44
SAO_EO_VERT
@ SAO_EO_VERT
Definition: hevcdec.h:173
ALF_BORDER_CHROMA
#define ALF_BORDER_CHROMA
Definition: ctu.h:80
ff_vvc_get_ref_list
const RefPicList * ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
Definition: refs.c:76
MAX_QP
#define MAX_QP
Definition: hevcdec.h:50
MvField::mv
Mv mv[2]
mvL0, vvL1
Definition: hevcdec.h:311
ALFParams
Definition: ctu.h:472
Mv
Definition: hevcdec.h:305
MvField::ref_idx
int8_t ref_idx[2]
refIdxL0, refIdxL1
Definition: hevcdec.h:312
PF_PLT
@ PF_PLT
Definition: ctu.h:228
SINGLE_TREE
@ SINGLE_TREE
Definition: ctu.h:168
alf_filter_cc
static void alf_filter_cc(VVCLocalContext *lc, uint8_t *dst, const uint8_t *luma, const ptrdiff_t dst_stride, const ptrdiff_t luma_stride, const int c_idx, const int width, const int height, const int hs, const int vs, const int vb_pos, const ALFParams *alf)
Definition: filter.c:1064
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
SliceContext::sh
VVCSH sh
Definition: dec.h:115
VVCFrameContext
Definition: dec.h:122
ALFParams::ctb_flag
uint8_t ctb_flag[3]
alf_ctb_flag[]
Definition: ctu.h:473
ALF_NUM_FILTERS_LUMA
#define ALF_NUM_FILTERS_LUMA
Definition: ps.h:163
int32_t
int32_t
Definition: audioconvert.c:56
imgutils.h
coeff
static const double coeff[2][5]
Definition: vf_owdenoise.c:80
copy_ctb
static void copy_ctb(uint8_t *dst, const uint8_t *src, const int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride)
Definition: filter.c:93
TOP
#define TOP
Definition: filter.c:31
TransformUnit::joint_cbcr_residual_flag
uint8_t joint_cbcr_residual_flag
tu_joint_cbcr_residual_flag
Definition: ctu.h:180
ff_vvc_sao_copy_ctb_to_hv
void ff_vvc_sao_copy_ctb_to_hv(VVCLocalContext *lc, const int rx, const int ry, const int last_row)
Definition: filter.c:174
h
h
Definition: vp9dsp_template.c:2070
ctu.h
BOUNDARY_LEFT_SLICE
#define BOUNDARY_LEFT_SLICE
Definition: hevcdec.h:441
ALF_VB_POS_ABOVE_CHROMA
#define ALF_VB_POS_ABOVE_CHROMA
Definition: ctu.h:83
SAOParams::band_position
uint8_t band_position[3]
sao_band_position
Definition: dsp.h:38
DEBLOCK_STEP
#define DEBLOCK_STEP
Definition: filter.c:379
width
#define width
Definition: dsp.h:89
alf_copy_ctb_to_hv
static void alf_copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src, const ptrdiff_t src_stride, const int x, const int y, const int width, const int height, const int rx, const int ry, const int c_idx)
Definition: filter.c:900
deblock_bs_fn
void(* deblock_bs_fn)(const VVCLocalContext *lc, const int x0, const int y0, const int width, const int height, const int rs, const int vertical)
Definition: filter.c:674
alf_get_subblock
static void alf_get_subblock(VVCRect *sb, int edges[MAX_EDGES], const int bx, const int by, const int vb_pos[2], const int has_vb[2])
Definition: filter.c:1148
PredictionUnit::merge_subblock_flag
uint8_t merge_subblock_flag
Definition: ctu.h:263
copy_ctb_to_hv
static void copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src, const ptrdiff_t src_stride, const int x, const int y, const int width, const int height, const int c_idx, const int rx, const int ry, const int top)
Definition: filter.c:131
src
#define src
Definition: vp8dsp.c:248
MIN_TU_LOG2
#define MIN_TU_LOG2
MinTbLog2SizeY.
Definition: dec.h:41
alf_get_edges
static void alf_get_edges(const VVCLocalContext *lc, int edges[MAX_EDGES], const int rx, const int ry)
Definition: filter.c:1104
copy_vert
static void copy_vert(uint8_t *dst, const uint8_t *src, const int pixel_shift, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride)
Definition: filter.c:112
alf_filter_luma
static void alf_filter_luma(VVCLocalContext *lc, uint8_t *dst, const uint8_t *src, const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int x0, const int y0, const int width, const int height, const int _vb_pos, const ALFParams *alf)
Definition: filter.c:1023
CodingUnit::y0
int y0
Definition: ctu.h:290
TC_CALC
#define TC_CALC(qp, bs)
Definition: filter.c:738