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