FFmpeg
vvc_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 
24 #include "vvc_ctu.h"
25 #include "vvc_data.h"
26 #include "vvc_filter.h"
27 #include "vvc_refs.h"
28 
29 #define LEFT 0
30 #define TOP 1
31 #define RIGHT 2
32 #define BOTTOM 3
33 #define MAX_EDGES 4
34 
35 #define DEFAULT_INTRA_TC_OFFSET 2
36 
37 //Table 43 Derivation of threshold variables beta' and tc' from input Q
38 static const uint16_t tctable[66] = {
39  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40  0, 0, 3, 4, 4, 4, 4, 5, 5, 5, 5, 7, 7, 8, 9, 10,
41  10, 11, 13, 14, 15, 17, 19, 21, 24, 25, 29, 33, 36, 41, 45, 51,
42  57, 64, 71, 80, 89, 100, 112, 125, 141, 157, 177, 198, 222, 250, 280, 314,
43  352, 395,
44 };
45 
46 //Table 43 Derivation of threshold variables beta' and tc' from input Q
47 static const uint8_t betatable[64] = {
48  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
49  6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 22, 24,
50  26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56,
51  58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88,
52 };
53 
54 static int get_qPc(const VVCFrameContext *fc, const int x0, const int y0, const int chroma)
55 {
56  const int x = x0 >> MIN_TU_LOG2;
57  const int y = y0 >> MIN_TU_LOG2;
58  const int min_tu_width = fc->ps.pps->min_tu_width;
59  return fc->tab.qp[chroma][x + y * min_tu_width];
60 }
61 
62 static void copy_ctb(uint8_t *dst, const uint8_t *src, const int width, const int height,
63  const ptrdiff_t dst_stride, const ptrdiff_t src_stride)
64 {
65  for (int y = 0; y < height; y++) {
66  memcpy(dst, src, width);
67 
68  dst += dst_stride;
69  src += src_stride;
70  }
71 }
72 
73 static void copy_pixel(uint8_t *dst, const uint8_t *src, const int pixel_shift)
74 {
75  if (pixel_shift)
76  *(uint16_t *)dst = *(uint16_t *)src;
77  else
78  *dst = *src;
79 }
80 
81 static void copy_vert(uint8_t *dst, const uint8_t *src, const int pixel_shift, const int height,
82  const ptrdiff_t dst_stride, const ptrdiff_t src_stride)
83 {
84  int i;
85  if (pixel_shift == 0) {
86  for (i = 0; i < height; i++) {
87  *dst = *src;
88  dst += dst_stride;
89  src += src_stride;
90  }
91  } else {
92  for (i = 0; i < height; i++) {
93  *(uint16_t *)dst = *(uint16_t *)src;
94  dst += dst_stride;
95  src += src_stride;
96  }
97  }
98 }
99 
100 static void copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src,
101  const ptrdiff_t src_stride, const int x, const int y, const int width, const int height,
102  const int c_idx, const int x_ctb, const int y_ctb, const int top)
103 {
104  const int ps = fc->ps.sps->pixel_shift;
105  const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
106  const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
107 
108  if (top) {
109  /* top */
110  memcpy(fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * y_ctb) * w + x) << ps),
111  src, width << ps);
112  } else {
113  /* bottom */
114  memcpy(fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 1) * w + x) << ps),
115  src + src_stride * (height - 1), width << ps);
116 
117  /* copy vertical edges */
118  copy_vert(fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * x_ctb) * h + y) << ps), src, ps, height, 1 << ps, src_stride);
119  copy_vert(fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 1) * h + y) << ps), src + ((width - 1) << ps), ps, height, 1 << ps, src_stride);
120  }
121 }
122 
123 static void sao_copy_ctb_to_hv(VVCLocalContext *lc, const int rx, const int ry, const int top)
124 {
125  VVCFrameContext *fc = lc->fc;
126  const int ctb_size_y = fc->ps.sps->ctb_size_y;
127  const int x0 = rx << fc->ps.sps->ctb_log2_size_y;
128  const int y0 = ry << fc->ps.sps->ctb_log2_size_y;
129 
130  for (int c_idx = 0; c_idx < (fc->ps.sps->r->sps_chroma_format_idc ? 3 : 1); c_idx++) {
131  const int x = x0 >> fc->ps.sps->hshift[c_idx];
132  const int y = y0 >> fc->ps.sps->vshift[c_idx];
133  const ptrdiff_t src_stride = fc->frame->linesize[c_idx];
134  const int ctb_size_h = ctb_size_y >> fc->ps.sps->hshift[c_idx];
135  const int ctb_size_v = ctb_size_y >> fc->ps.sps->vshift[c_idx];
136  const int width = FFMIN(ctb_size_h, (fc->ps.pps->width >> fc->ps.sps->hshift[c_idx]) - x);
137  const int height = FFMIN(ctb_size_v, (fc->ps.pps->height >> fc->ps.sps->vshift[c_idx]) - y);
138  const uint8_t *src = &fc->frame->data[c_idx][y * src_stride + (x << fc->ps.sps->pixel_shift)];
139  copy_ctb_to_hv(fc, src, src_stride, x, y, width, height, c_idx, rx, ry, top);
140  }
141 }
142 
143 void ff_vvc_sao_copy_ctb_to_hv(VVCLocalContext *lc, const int rx, const int ry, const int last_row)
144 {
145  if (ry)
146  sao_copy_ctb_to_hv(lc, rx, ry - 1, 0);
147 
148  sao_copy_ctb_to_hv(lc, rx, ry, 1);
149 
150  if (last_row)
151  sao_copy_ctb_to_hv(lc, rx, ry, 0);
152 }
153 
154 void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
155 {
156  VVCFrameContext *fc = lc->fc;
157  const int ctb_size_y = fc->ps.sps->ctb_size_y;
158  static const uint8_t sao_tab[16] = { 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8 };
159  int c_idx;
160  int edges[4]; // 0 left 1 top 2 right 3 bottom
161  const int x_ctb = x >> fc->ps.sps->ctb_log2_size_y;
162  const int y_ctb = y >> fc->ps.sps->ctb_log2_size_y;
163  const SAOParams *sao = &CTB(fc->tab.sao, x_ctb, y_ctb);
164  // flags indicating unfilterable edges
165  uint8_t vert_edge[] = { 0, 0 };
166  uint8_t horiz_edge[] = { 0, 0 };
167  uint8_t diag_edge[] = { 0, 0, 0, 0 };
168  const uint8_t lfase = fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag;
169  const uint8_t no_tile_filter = fc->ps.pps->r->num_tiles_in_pic > 1 &&
170  !fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag;
171  const uint8_t restore = no_tile_filter || !lfase;
172  uint8_t left_tile_edge = 0;
173  uint8_t right_tile_edge = 0;
174  uint8_t up_tile_edge = 0;
175  uint8_t bottom_tile_edge = 0;
176 
177  edges[LEFT] = x_ctb == 0;
178  edges[TOP] = y_ctb == 0;
179  edges[RIGHT] = x_ctb == fc->ps.pps->ctb_width - 1;
180  edges[BOTTOM] = y_ctb == fc->ps.pps->ctb_height - 1;
181 
182  if (restore) {
183  if (!edges[LEFT]) {
184  left_tile_edge = no_tile_filter && fc->ps.pps->ctb_to_col_bd[x_ctb] == x_ctb;
185  vert_edge[0] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb - 1, y_ctb)) || left_tile_edge;
186  }
187  if (!edges[RIGHT]) {
188  right_tile_edge = no_tile_filter && fc->ps.pps->ctb_to_col_bd[x_ctb] != fc->ps.pps->ctb_to_col_bd[x_ctb + 1];
189  vert_edge[1] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb + 1, y_ctb)) || right_tile_edge;
190  }
191  if (!edges[TOP]) {
192  up_tile_edge = no_tile_filter && fc->ps.pps->ctb_to_row_bd[y_ctb] == y_ctb;
193  horiz_edge[0] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb, y_ctb - 1)) || up_tile_edge;
194  }
195  if (!edges[BOTTOM]) {
196  bottom_tile_edge = no_tile_filter && fc->ps.pps->ctb_to_row_bd[y_ctb] != fc->ps.pps->ctb_to_row_bd[y_ctb + 1];
197  horiz_edge[1] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb, y_ctb + 1)) || bottom_tile_edge;
198  }
199  if (!edges[LEFT] && !edges[TOP]) {
200  diag_edge[0] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb - 1, y_ctb - 1)) || left_tile_edge || up_tile_edge;
201  }
202  if (!edges[TOP] && !edges[RIGHT]) {
203  diag_edge[1] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb + 1, y_ctb - 1)) || right_tile_edge || up_tile_edge;
204  }
205  if (!edges[RIGHT] && !edges[BOTTOM]) {
206  diag_edge[2] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb + 1, y_ctb + 1)) || right_tile_edge || bottom_tile_edge;
207  }
208  if (!edges[LEFT] && !edges[BOTTOM]) {
209  diag_edge[3] = (!lfase && CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb - 1, y_ctb + 1)) || left_tile_edge || bottom_tile_edge;
210  }
211  }
212 
213  for (c_idx = 0; c_idx < (fc->ps.sps->r->sps_chroma_format_idc ? 3 : 1); c_idx++) {
214  int x0 = x >> fc->ps.sps->hshift[c_idx];
215  int y0 = y >> fc->ps.sps->vshift[c_idx];
216  ptrdiff_t src_stride = fc->frame->linesize[c_idx];
217  int ctb_size_h = ctb_size_y >> fc->ps.sps->hshift[c_idx];
218  int ctb_size_v = ctb_size_y >> fc->ps.sps->vshift[c_idx];
219  int width = FFMIN(ctb_size_h, (fc->ps.pps->width >> fc->ps.sps->hshift[c_idx]) - x0);
220  int height = FFMIN(ctb_size_v, (fc->ps.pps->height >> fc->ps.sps->vshift[c_idx]) - y0);
221  int tab = sao_tab[(FFALIGN(width, 8) >> 3) - 1];
222  uint8_t *src = &fc->frame->data[c_idx][y0 * src_stride + (x0 << fc->ps.sps->pixel_shift)];
223  ptrdiff_t dst_stride;
224  uint8_t *dst;
225 
226  switch (sao->type_idx[c_idx]) {
227  case SAO_BAND:
228  fc->vvcdsp.sao.band_filter[tab](src, src, src_stride, src_stride,
229  sao->offset_val[c_idx], sao->band_position[c_idx], width, height);
230  break;
231  case SAO_EDGE:
232  {
233  const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
234  const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
235  const int sh = fc->ps.sps->pixel_shift;
236 
237  dst_stride = 2*MAX_PB_SIZE + AV_INPUT_BUFFER_PADDING_SIZE;
238  dst = lc->sao_buffer + dst_stride + AV_INPUT_BUFFER_PADDING_SIZE;
239 
240  if (!edges[TOP]) {
241  const int left = 1 - edges[LEFT];
242  const int right = 1 - edges[RIGHT];
243  const uint8_t *src1;
244  uint8_t *dst1;
245  int pos = 0;
246 
247  dst1 = dst - dst_stride - (left << sh);
248  src1 = fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * y_ctb - 1) * w + x0 - left) << sh);
249  if (left) {
250  copy_pixel(dst1, src1, sh);
251  pos += (1 << sh);
252  }
253  memcpy(dst1 + pos, src1 + pos, width << sh);
254  if (right) {
255  pos += width << sh;
256  copy_pixel(dst1 + pos, src1 + pos, sh);
257  }
258  }
259  if (!edges[BOTTOM]) {
260  const int left = 1 - edges[LEFT];
261  const int right = 1 - edges[RIGHT];
262  const uint8_t *src1;
263  uint8_t *dst1;
264  int pos = 0;
265 
266  dst1 = dst + height * dst_stride - (left << sh);
267  src1 = fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * y_ctb + 2) * w + x0 - left) << sh);
268  if (left) {
269  copy_pixel(dst1, src1, sh);
270  pos += (1 << sh);
271  }
272  memcpy(dst1 + pos, src1 + pos, width << sh);
273  if (right) {
274  pos += width << sh;
275  copy_pixel(dst1 + pos, src1 + pos, sh);
276  }
277  }
278  if (!edges[LEFT]) {
279  copy_vert(dst - (1 << sh),
280  fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * x_ctb - 1) * h + y0) << sh),
281  sh, height, dst_stride, 1 << sh);
282  }
283  if (!edges[RIGHT]) {
284  copy_vert(dst + (width << sh),
285  fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * x_ctb + 2) * h + y0) << sh),
286  sh, height, dst_stride, 1 << sh);
287  }
288 
289  copy_ctb(dst, src, width << sh, height, dst_stride, src_stride);
290  fc->vvcdsp.sao.edge_filter[tab](src, dst, src_stride, sao->offset_val[c_idx],
291  sao->eo_class[c_idx], width, height);
292  fc->vvcdsp.sao.edge_restore[restore](src, dst, src_stride, dst_stride,
293  sao, edges, width, height, c_idx, vert_edge, horiz_edge, diag_edge);
294  break;
295  }
296  }
297  }
298 }
299 
300 #define TAB_BS(t, x, y) (t)[((y) >> 2) * (fc->tab.sz.bs_width) + ((x) >> 2)]
301 #define TAB_MAX_LEN(t, x, y) (t)[((y) >> 2) * (fc->tab.sz.bs_width) + ((x) >> 2)]
302 
303 //8 samples a time
304 #define DEBLOCK_STEP 8
305 #define LUMA_GRID 4
306 #define CHROMA_GRID 8
307 
308 static int boundary_strength(const VVCLocalContext *lc, const MvField *curr, const MvField *neigh,
309  const RefPicList *neigh_rpl)
310 {
311  RefPicList *rpl = lc->sc->rpl;
312 
313  if (curr->pred_flag == PF_IBC)
314  return FFABS(neigh->mv[0].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 8;
315 
316  if (curr->pred_flag == PF_BI && neigh->pred_flag == PF_BI) {
317  // same L0 and L1
318  if (rpl[0].list[curr->ref_idx[0]] == neigh_rpl[0].list[neigh->ref_idx[0]] &&
319  rpl[0].list[curr->ref_idx[0]] == rpl[1].list[curr->ref_idx[1]] &&
320  neigh_rpl[0].list[neigh->ref_idx[0]] == neigh_rpl[1].list[neigh->ref_idx[1]]) {
321  if ((FFABS(neigh->mv[0].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 8 ||
322  FFABS(neigh->mv[1].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 8) &&
323  (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 8 ||
324  FFABS(neigh->mv[0].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 8))
325  return 1;
326  else
327  return 0;
328  } else if (neigh_rpl[0].list[neigh->ref_idx[0]] == rpl[0].list[curr->ref_idx[0]] &&
329  neigh_rpl[1].list[neigh->ref_idx[1]] == rpl[1].list[curr->ref_idx[1]]) {
330  if (FFABS(neigh->mv[0].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 8 ||
331  FFABS(neigh->mv[1].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 8)
332  return 1;
333  else
334  return 0;
335  } else if (neigh_rpl[1].list[neigh->ref_idx[1]] == rpl[0].list[curr->ref_idx[0]] &&
336  neigh_rpl[0].list[neigh->ref_idx[0]] == rpl[1].list[curr->ref_idx[1]]) {
337  if (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 8 ||
338  FFABS(neigh->mv[0].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 8)
339  return 1;
340  else
341  return 0;
342  } else {
343  return 1;
344  }
345  } else if ((curr->pred_flag != PF_BI) && (neigh->pred_flag != PF_BI)){ // 1 MV
346  Mv A, B;
347  int ref_A, ref_B;
348 
349  if (curr->pred_flag & 1) {
350  A = curr->mv[0];
351  ref_A = rpl[0].list[curr->ref_idx[0]];
352  } else {
353  A = curr->mv[1];
354  ref_A = rpl[1].list[curr->ref_idx[1]];
355  }
356 
357  if (neigh->pred_flag & 1) {
358  B = neigh->mv[0];
359  ref_B = neigh_rpl[0].list[neigh->ref_idx[0]];
360  } else {
361  B = neigh->mv[1];
362  ref_B = neigh_rpl[1].list[neigh->ref_idx[1]];
363  }
364 
365  if (ref_A == ref_B) {
366  if (FFABS(A.x - B.x) >= 8 || FFABS(A.y - B.y) >= 8)
367  return 1;
368  else
369  return 0;
370  } else
371  return 1;
372  }
373 
374  return 1;
375 }
376 
377 //part of 8.8.3.3 Derivation process of transform block boundary
378 static void derive_max_filter_length_luma(const VVCFrameContext *fc, const int qx, const int qy,
379  const int is_intra, const int has_subblock, const int vertical, uint8_t *max_len_p, uint8_t *max_len_q)
380 {
381  const int px = vertical ? qx - 1 : qx;
382  const int py = !vertical ? qy - 1 : qy;
383  const uint8_t *tb_size = vertical ? fc->tab.tb_width[LUMA] : fc->tab.tb_height[LUMA];
384  const int size_p = tb_size[(py >> MIN_TU_LOG2) * fc->ps.pps->min_tu_width + (px >> MIN_TU_LOG2)];
385  const int size_q = tb_size[(qy >> MIN_TU_LOG2) * fc->ps.pps->min_tu_width + (qx >> MIN_TU_LOG2)];
386  const int min_cb_log2 = fc->ps.sps->min_cb_log2_size_y;
387  const int off_p = (py >> min_cb_log2) * fc->ps.pps->min_cb_width + (px >> min_cb_log2);
388  if (size_p <= 4 || size_q <= 4) {
389  *max_len_p = *max_len_q = 1;
390  } else {
391  *max_len_p = *max_len_q = 3;
392  if (size_p >= 32)
393  *max_len_p = 7;
394  if (size_q >= 32)
395  *max_len_q = 7;
396  }
397  if (has_subblock)
398  *max_len_q = FFMIN(5, *max_len_q);
399  if (fc->tab.msf[off_p] || fc->tab.iaf[off_p])
400  *max_len_p = FFMIN(5, *max_len_p);
401 }
402 
404  const int cb_x, const int cb_y, const int x0, const int y0, const int width, const int height)
405 {
406  const VVCFrameContext *fc = lc->fc;
407  const MvField *tab_mvf = fc->tab.mvf;
408  const RefPicList *rpl = lc->sc->rpl;
409  const int min_pu_width = fc->ps.pps->min_pu_width;
410  const int log2_min_pu_size = MIN_PU_LOG2;
411 
412  // bs for TU internal vertical PU boundaries
413  for (int j = 0; j < height; j += 4) {
414  const int y_pu = (y0 + j) >> log2_min_pu_size;
415 
416  for (int i = 8 - ((x0 - cb_x) % 8); i < width; i += 8) {
417  const int xp_pu = (x0 + i - 1) >> log2_min_pu_size;
418  const int xq_pu = (x0 + i) >> log2_min_pu_size;
419  const MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu];
420  const MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu];
421  const int x = x0 + i;
422  const int y = y0 + j;
423  const int bs = boundary_strength(lc, curr, left, rpl);
424  uint8_t max_len_p = 0, max_len_q = 0;
425 
426  TAB_BS(fc->tab.vertical_bs[LUMA], x, y) = bs;
427 
428  if (i == 4 || i == width - 4)
429  max_len_p = max_len_q = 1;
430  else if (i == 8 || i == width - 8)
431  max_len_p = max_len_q = 2;
432  else
433  max_len_p = max_len_q = 3;
434 
435  TAB_MAX_LEN(fc->tab.vertical_p, x, y) = max_len_p;
436  TAB_MAX_LEN(fc->tab.vertical_q, x, y) = max_len_q;
437  }
438  }
439 }
440 
442  const int cb_x, const int cb_y, const int x0, const int y0, const int width, const int height)
443 {
444  const VVCFrameContext *fc = lc->fc;
445  const MvField* tab_mvf = fc->tab.mvf;
446  const RefPicList* rpl = lc->sc->rpl;
447  const int min_pu_width = fc->ps.pps->min_pu_width;
448  const int log2_min_pu_size = MIN_PU_LOG2;
449 
450  // bs for TU internal horizontal PU boundaries
451  for (int j = 8 - ((y0 - cb_y) % 8); j < height; j += 8) {
452  int yp_pu = (y0 + j - 1) >> log2_min_pu_size;
453  int yq_pu = (y0 + j) >> log2_min_pu_size;
454 
455  for (int i = 0; i < width; i += 4) {
456  const int x_pu = (x0 + i) >> log2_min_pu_size;
457  const MvField *top = &tab_mvf[yp_pu * min_pu_width + x_pu];
458  const MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu];
459  const int x = x0 + i;
460  const int y = y0 + j;
461  const int bs = boundary_strength(lc, curr, top, rpl);
462  uint8_t max_len_p = 0, max_len_q = 0;
463 
464  TAB_BS(fc->tab.horizontal_bs[LUMA], x, y) = bs;
465 
466  //fixme:
467  //edgeTbFlags[ x − sbW ][ y ] is equal to 1
468  //edgeTbFlags[ x + sbW ][ y ] is equal to 1
469  if (j == 4 || j == height - 4)
470  max_len_p = max_len_q = 1;
471  else if (j == 8 || j == height - 8)
472  max_len_p = max_len_q = 2;
473  else
474  max_len_p = max_len_q = 3;
475  TAB_MAX_LEN(fc->tab.horizontal_p, x, y) = max_len_p;
476  TAB_MAX_LEN(fc->tab.horizontal_q, x, y) = max_len_q;
477  }
478  }
479 }
480 
482  const int x_p, const int y_p, const int x_q, const int y_q,
483  const RefPicList *rpl_p, const int c_idx, const int off_to_cb, const uint8_t has_sub_block)
484 {
485  const VVCFrameContext *fc = lc->fc;
486  const MvField *tab_mvf = fc->tab.mvf;
487  const int log2_min_pu_size = MIN_PU_LOG2;
488  const int log2_min_tu_size = MIN_TU_LOG2;
489  const int log2_min_cb_size = fc->ps.sps->min_cb_log2_size_y;
490  const int min_pu_width = fc->ps.pps->min_pu_width;
491  const int min_tu_width = fc->ps.pps->min_tu_width;
492  const int min_cb_width = fc->ps.pps->min_cb_width;
493  const int pu_p = (y_p >> log2_min_pu_size) * min_pu_width + (x_p >> log2_min_pu_size);
494  const int pu_q = (y_q >> log2_min_pu_size) * min_pu_width + (x_q >> log2_min_pu_size);
495  const MvField *mvf_p = &tab_mvf[pu_p];
496  const MvField *mvf_q = &tab_mvf[pu_q];
497  const uint8_t chroma = !!c_idx;
498  const int tu_p = (y_p >> log2_min_tu_size) * min_tu_width + (x_p >> log2_min_tu_size);
499  const int tu_q = (y_q >> log2_min_tu_size) * min_tu_width + (x_q >> log2_min_tu_size);
500  const uint8_t pcmf = fc->tab.pcmf[chroma][tu_p] && fc->tab.pcmf[chroma][tu_q];
501  const int cb_p = (y_p >> log2_min_cb_size) * min_cb_width + (x_p >> log2_min_cb_size);
502  const int cb_q = (y_q >> log2_min_cb_size) * min_cb_width + (x_q >> log2_min_cb_size);
503  const uint8_t intra = fc->tab.cpm[chroma][cb_p] == MODE_INTRA || fc->tab.cpm[chroma][cb_q] == MODE_INTRA;
504  const uint8_t same_mode = fc->tab.cpm[chroma][cb_p] == fc->tab.cpm[chroma][cb_q];
505 
506  if (pcmf)
507  return 0;
508 
509  if (intra || mvf_p->ciip_flag || mvf_q->ciip_flag)
510  return 2;
511 
512  if (chroma) {
513  return fc->tab.tu_coded_flag[c_idx][tu_p] ||
514  fc->tab.tu_coded_flag[c_idx][tu_q] ||
515  fc->tab.tu_joint_cbcr_residual_flag[tu_p] ||
516  fc->tab.tu_joint_cbcr_residual_flag[tu_q];
517  }
518 
519  if (fc->tab.tu_coded_flag[LUMA][tu_p] || fc->tab.tu_coded_flag[LUMA][tu_q])
520  return 1;
521 
522  if ((off_to_cb && ((off_to_cb % 8) || !has_sub_block)))
523  return 0; // inside a cu, not aligned to 8 or with no subblocks
524 
525  if (!same_mode)
526  return 1;
527 
528  return boundary_strength(lc, mvf_q, mvf_p, rpl_p);
529 }
530 
532  const int x0, const int y0, const int width, const int height)
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 min_pu_width = fc->ps.pps->min_pu_width;
538  const int min_cb_log2 = fc->ps.sps->min_cb_log2_size_y;
539  const int min_cb_width = fc->ps.pps->min_cb_width;
540  const int is_intra = tab_mvf[(y0 >> log2_min_pu_size) * min_pu_width +
541  (x0 >> log2_min_pu_size)].pred_flag == PF_INTRA;
542  int boundary_left;
543  int has_vertical_sb = 0;
544 
545  const int off_q = (y0 >> min_cb_log2) * min_cb_width + (x0 >> min_cb_log2);
546  const int cb_x = fc->tab.cb_pos_x[LUMA][off_q];
547  const int cb_y = fc->tab.cb_pos_y[LUMA][off_q];
548  const int cb_width = fc->tab.cb_width[LUMA][off_q];
549  const int off_x = cb_x - x0;
550 
551  if (!is_intra) {
552  if (fc->tab.msf[off_q] || fc->tab.iaf[off_q])
553  has_vertical_sb = cb_width > 8;
554  }
555 
556  // bs for vertical TU boundaries
557  boundary_left = x0 > 0 && !(x0 & 3);
558  if (boundary_left &&
559  ((!fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag &&
561  (x0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0) ||
562  (!fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag &&
564  (x0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0)))
565  boundary_left = 0;
566 
567  if (boundary_left) {
568  const RefPicList *rpl_left =
569  (lc->boundary_flags & BOUNDARY_LEFT_SLICE) ? ff_vvc_get_ref_list(fc, fc->ref, x0 - 1, y0) : lc->sc->rpl;
570  for (int i = 0; i < height; i += 4) {
571  uint8_t max_len_p, max_len_q;
572  const int bs = deblock_bs(lc, x0 - 1, y0 + i, x0, y0 + i, rpl_left, 0, off_x, has_vertical_sb);
573 
574  TAB_BS(fc->tab.vertical_bs[LUMA], x0, (y0 + i)) = bs;
575 
576  derive_max_filter_length_luma(fc, x0, y0 + i, is_intra, has_vertical_sb, 1, &max_len_p, &max_len_q);
577  TAB_MAX_LEN(fc->tab.vertical_p, x0, y0 + i) = max_len_p;
578  TAB_MAX_LEN(fc->tab.vertical_q, x0, y0 + i) = max_len_q;
579  }
580  }
581 
582  if (!is_intra) {
583  if (fc->tab.msf[off_q] || fc->tab.iaf[off_q])
584  vvc_deblock_subblock_bs_vertical(lc, cb_x, cb_y, x0, y0, width, height);
585  }
586 }
587 
589  const int x0, const int y0, const int width, const int height)
590 {
591  const VVCFrameContext *fc = lc->fc;
592  const MvField *tab_mvf = fc->tab.mvf;
593  const int log2_min_pu_size = MIN_PU_LOG2;
594  const int min_pu_width = fc->ps.pps->min_pu_width;
595  const int min_cb_log2 = fc->ps.sps->min_cb_log2_size_y;
596  const int min_cb_width = fc->ps.pps->min_cb_width;
597  const int is_intra = tab_mvf[(y0 >> log2_min_pu_size) * min_pu_width +
598  (x0 >> log2_min_pu_size)].pred_flag == PF_INTRA;
599  int boundary_upper;
600  int has_horizontal_sb = 0;
601 
602  const int off_q = (y0 >> min_cb_log2) * min_cb_width + (x0 >> min_cb_log2);
603  const int cb_x = fc->tab.cb_pos_x[LUMA][off_q];
604  const int cb_y = fc->tab.cb_pos_y[LUMA][off_q];
605  const int cb_height = fc->tab.cb_height[LUMA][off_q];
606  const int off_y = y0 - cb_y;
607 
608  if (!is_intra) {
609  if (fc->tab.msf[off_q] || fc->tab.iaf[off_q])
610  has_horizontal_sb = cb_height > 8;
611  }
612 
613  boundary_upper = y0 > 0 && !(y0 & 3);
614  if (boundary_upper &&
615  ((!fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag &&
617  (y0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0) ||
618  (!fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag &&
620  (y0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0)))
621  boundary_upper = 0;
622 
623  if (boundary_upper) {
624  const RefPicList *rpl_top =
625  (lc->boundary_flags & BOUNDARY_UPPER_SLICE) ? ff_vvc_get_ref_list(fc, fc->ref, x0, y0 - 1) : lc->sc->rpl;
626 
627  for (int i = 0; i < width; i += 4) {
628  uint8_t max_len_p, max_len_q;
629  const int bs = deblock_bs(lc, x0 + i, y0 - 1, x0 + i, y0, rpl_top, 0, off_y, has_horizontal_sb);
630 
631  TAB_BS(fc->tab.horizontal_bs[LUMA], x0 + i, y0) = bs;
632 
633  derive_max_filter_length_luma(fc, x0 + i, y0, is_intra, has_horizontal_sb, 0, &max_len_p, &max_len_q);
634  TAB_MAX_LEN(fc->tab.horizontal_p, x0 + i, y0) = max_len_p;
635  TAB_MAX_LEN(fc->tab.horizontal_q, x0 + i, y0) = max_len_q;
636  }
637  }
638 
639  if (!is_intra) {
640  if (fc->tab.msf[off_q] || fc->tab.iaf[off_q])
641  vvc_deblock_subblock_bs_horizontal(lc, cb_x, cb_y, x0, y0, width, height);
642  }
643 }
644 
646  const int x0, const int y0, const int width, const int height)
647 {
648  const VVCFrameContext *fc = lc->fc;
649  int boundary_left;
650 
651  // bs for vertical TU boundaries
652  boundary_left = x0 > 0 && !(x0 & ((CHROMA_GRID << fc->ps.sps->hshift[1]) - 1));
653  if (boundary_left &&
654  ((!fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag &&
656  (x0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0) ||
657  (!fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag &&
659  (x0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0)))
660  boundary_left = 0;
661 
662  if (boundary_left) {
663  for (int i = 0; i < height; i += 2) {
664  for (int c_idx = CB; c_idx <= CR; c_idx++) {
665  const int bs = deblock_bs(lc, x0 - 1, y0 + i, x0, y0 + i, NULL, c_idx, 0, 0);
666 
667  TAB_BS(fc->tab.vertical_bs[c_idx], x0, (y0 + i)) = bs;
668  }
669  }
670  }
671 }
672 
674  const int x0, const int y0, const int width, const int height)
675 {
676  const VVCFrameContext *fc = lc->fc;
677  int boundary_upper;
678 
679  boundary_upper = y0 > 0 && !(y0 & ((CHROMA_GRID << fc->ps.sps->vshift[1]) - 1));
680  if (boundary_upper &&
681  ((!fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag &&
683  (y0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0) ||
684  (!fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag &&
686  (y0 % (1 << fc->ps.sps->ctb_log2_size_y)) == 0)))
687  boundary_upper = 0;
688 
689  if (boundary_upper) {
690  for (int i = 0; i < width; i += 2) {
691  for (int c_idx = CB; c_idx <= CR; c_idx++) {
692  const int bs = deblock_bs(lc, x0 + i, y0 - 1, x0 + i, y0, NULL, c_idx, 0, 0);
693 
694  TAB_BS(fc->tab.horizontal_bs[c_idx], x0 + i, y0) = bs;
695  }
696  }
697  }
698 }
699 
700 typedef void (*deblock_bs_fn)(const VVCLocalContext *lc, const int x0, const int y0,
701  const int width, const int height);
702 
703 static void vvc_deblock_bs(const VVCLocalContext *lc, const int x0, const int y0, const int vertical)
704 {
705  const VVCFrameContext *fc = lc->fc;
706  const VVCSPS *sps = fc->ps.sps;
707  const VVCPPS *pps = fc->ps.pps;
708  const int ctb_size = sps->ctb_size_y;
709  const int x_end = FFMIN(x0 + ctb_size, pps->width) >> MIN_TU_LOG2;
710  const int y_end = FFMIN(y0 + ctb_size, pps->height) >> MIN_TU_LOG2;
711  deblock_bs_fn deblock_bs[2][2] = {
714  };
715 
716  for (int is_chroma = 0; is_chroma <= 1; is_chroma++) {
717  const int hs = sps->hshift[is_chroma];
718  const int vs = sps->vshift[is_chroma];
719  for (int y = y0 >> MIN_TU_LOG2; y < y_end; y++) {
720  for (int x = x0 >> MIN_TU_LOG2; x < x_end; x++) {
721  const int off = y * fc->ps.pps->min_tu_width + x;
722  if ((fc->tab.tb_pos_x0[is_chroma][off] >> MIN_TU_LOG2) == x && (fc->tab.tb_pos_y0[is_chroma][off] >> MIN_TU_LOG2) == y) {
723  deblock_bs[vertical][is_chroma](lc, x << MIN_TU_LOG2, y << MIN_TU_LOG2,
724  fc->tab.tb_width[is_chroma][off] << hs, fc->tab.tb_height[is_chroma][off] << vs);
725  }
726  }
727  }
728  }
729 }
730 
731 //part of 8.8.3.3 Derivation process of transform block boundary
732 static void max_filter_length_luma(const VVCFrameContext *fc, const int qx, const int qy,
733  const int vertical, uint8_t *max_len_p, uint8_t *max_len_q)
734 {
735  const uint8_t *tab_len_p = vertical ? fc->tab.vertical_p : fc->tab.horizontal_p;
736  const uint8_t *tab_len_q = vertical ? fc->tab.vertical_q : fc->tab.horizontal_q;
737  *max_len_p = TAB_MAX_LEN(tab_len_p, qx, qy);
738  *max_len_q = TAB_MAX_LEN(tab_len_q, qx, qy);
739 }
740 
741 //part of 8.8.3.3 Derivation process of transform block boundary
742 static void max_filter_length_chroma(const VVCFrameContext *fc, const int qx, const int qy,
743  const int vertical, const int horizontal_ctu_edge, const int bs, uint8_t *max_len_p, uint8_t *max_len_q)
744 {
745  const int px = vertical ? qx - 1 : qx;
746  const int py = !vertical ? qy - 1 : qy;
747  const uint8_t *tb_size = vertical ? fc->tab.tb_width[CHROMA] : fc->tab.tb_height[CHROMA];
748 
749  const int size_p = tb_size[(py >> MIN_TU_LOG2) * fc->ps.pps->min_tu_width + (px >> MIN_TU_LOG2)];
750  const int size_q = tb_size[(qy >> MIN_TU_LOG2) * fc->ps.pps->min_tu_width + (qx >> MIN_TU_LOG2)];
751  if (size_p >= 8 && size_q >= 8) {
752  *max_len_p = *max_len_q = 3;
753  if (horizontal_ctu_edge)
754  *max_len_p = 1;
755  } else {
756  //part of 8.8.3.6.4 Decision process for chroma block edges
757  *max_len_p = *max_len_q = (bs == 2);
758  }
759 }
760 
761 static void max_filter_length(const VVCFrameContext *fc, const int qx, const int qy,
762  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)
763 {
764  if (!c_idx)
765  max_filter_length_luma(fc, qx, qy, vertical, max_len_p, max_len_q);
766  else
767  max_filter_length_chroma(fc, qx, qy, vertical, horizontal_ctu_edge, bs, max_len_p, max_len_q);
768 }
769 
770 #define TC_CALC(qp, bs) \
771  tctable[av_clip((qp) + DEFAULT_INTRA_TC_OFFSET * ((bs) - 1) + \
772  (tc_offset & -2), \
773  0, MAX_QP + DEFAULT_INTRA_TC_OFFSET)]
774 
775 // part of 8.8.3.6.2 Decision process for luma block edges
776 static int get_qp_y(const VVCFrameContext *fc, const uint8_t *src, const int x, const int y, const int vertical)
777 {
778  const VVCSPS *sps = fc->ps.sps;
779  const int qp = (ff_vvc_get_qPy(fc, x - vertical, y - !vertical) + ff_vvc_get_qPy(fc, x, y) + 1) >> 1;
780  int qp_offset = 0;
781  int level;
782 
783  if (!sps->r->sps_ladf_enabled_flag)
784  return qp;
785 
786  level = fc->vvcdsp.lf.ladf_level[vertical](src, fc->frame->linesize[LUMA]);
787  qp_offset = sps->r->sps_ladf_lowest_interval_qp_offset;
788  for (int i = 0; i < sps->num_ladf_intervals - 1 && level > sps->ladf_interval_lower_bound[i + 1]; i++)
789  qp_offset = sps->r->sps_ladf_qp_offset[i];
790 
791  return qp + qp_offset;
792 }
793 
794 // part of 8.8.3.6.2 Decision process for luma block edges
795 static int get_qp_c(const VVCFrameContext *fc, const int x, const int y, const int c_idx, const int vertical)
796 {
797  const VVCSPS *sps = fc->ps.sps;
798  return (get_qPc(fc, x - vertical, y - !vertical, c_idx) + get_qPc(fc, x, y, c_idx) - 2 * sps->qp_bd_offset + 1) >> 1;
799 }
800 
801 static int get_qp(const VVCFrameContext *fc, const uint8_t *src, const int x, const int y, const int c_idx, const int vertical)
802 {
803  if (!c_idx)
804  return get_qp_y(fc, src, x, y, vertical);
805  return get_qp_c(fc, x, y, c_idx, vertical);
806 }
807 
808 void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0)
809 {
810  VVCFrameContext *fc = lc->fc;
811  const VVCSPS *sps = fc->ps.sps;
812  const int c_end = sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1;
813  uint8_t *src;
814  int x, y, qp;
815 
816  //not use this yet, may needed by plt.
817  const uint8_t no_p[4] = { 0 };
818  const uint8_t no_q[4] = { 0 } ;
819 
820  const int ctb_log2_size_y = fc->ps.sps->ctb_log2_size_y;
821  int x_end, y_end;
822  const int ctb_size = 1 << ctb_log2_size_y;
823  const int ctb = (x0 >> ctb_log2_size_y) +
824  (y0 >> ctb_log2_size_y) * fc->ps.pps->ctb_width;
825  const DBParams *params = fc->tab.deblock + ctb;
826 
827  vvc_deblock_bs(lc, x0, y0, 1);
828 
829  x_end = x0 + ctb_size;
830  if (x_end > fc->ps.pps->width)
831  x_end = fc->ps.pps->width;
832  y_end = y0 + ctb_size;
833  if (y_end > fc->ps.pps->height)
834  y_end = fc->ps.pps->height;
835 
836  for (int c_idx = 0; c_idx < c_end; c_idx++) {
837  const int hs = sps->hshift[c_idx];
838  const int vs = sps->vshift[c_idx];
839  const int grid = c_idx ? (CHROMA_GRID << hs) : LUMA_GRID;
840  const int tc_offset = params->tc_offset[c_idx];
841  const int beta_offset = params->beta_offset[c_idx];
842 
843  for (y = y0; y < y_end; y += (DEBLOCK_STEP << vs)) {
844  for (x = x0 ? x0 : grid; x < x_end; x += grid) {
845  int32_t bs[4], beta[4], tc[4], all_zero_bs = 1;
846  uint8_t max_len_p[4], max_len_q[4];
847 
848  for (int i = 0; i < DEBLOCK_STEP >> (2 - vs); i++) {
849  const int dy = i << 2;
850  bs[i] = (y + dy < y_end) ? TAB_BS(fc->tab.vertical_bs[c_idx], x, y + dy) : 0;
851  if (bs[i]) {
852  src = &fc->frame->data[c_idx][((y + dy) >> vs) * fc->frame->linesize[c_idx] + ((x >> hs) << fc->ps.sps->pixel_shift)];
853  qp = get_qp(fc, src, x, y + dy, c_idx, 1);
854 
855  beta[i] = betatable[av_clip(qp + beta_offset, 0, MAX_QP)];
856 
857  max_filter_length(fc, x, y + dy, c_idx, 1, 0, bs[i], &max_len_p[i], &max_len_q[i]);
858  all_zero_bs = 0;
859  }
860  tc[i] = bs[i] ? TC_CALC(qp, bs[i]) : 0;
861  }
862 
863  if (!all_zero_bs) {
864  src = &fc->frame->data[c_idx][(y >> vs) * fc->frame->linesize[c_idx] + ((x >> hs) << fc->ps.sps->pixel_shift)];
865  if (!c_idx) {
866  fc->vvcdsp.lf.filter_luma[1](src, fc->frame->linesize[c_idx],
867  beta, tc, no_p, no_q, max_len_p, max_len_q, 0);
868  } else {
869  fc->vvcdsp.lf.filter_chroma[1](src, fc->frame->linesize[c_idx],
870  beta, tc, no_p, no_q, max_len_p, max_len_q, vs);
871  }
872  }
873  }
874  }
875  }
876 }
877 
878 void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, int x0, int y0)
879 {
880  VVCFrameContext *fc = lc->fc;
881  const VVCSPS *sps = fc->ps.sps;
882  const int c_end = fc->ps.sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1;
883  uint8_t* src;
884  int x, y, qp;
885 
886  //not use this yet, may needed by plt.
887  const uint8_t no_p[4] = { 0 };
888  const uint8_t no_q[4] = { 0 } ;
889 
890  const int ctb_log2_size_y = fc->ps.sps->ctb_log2_size_y;
891  int x_end, y_end;
892  const int ctb_size = 1 << ctb_log2_size_y;
893  const int ctb = (x0 >> ctb_log2_size_y) +
894  (y0 >> ctb_log2_size_y) * fc->ps.pps->ctb_width;
895  const DBParams *params = fc->tab.deblock + ctb;
896 
897  vvc_deblock_bs(lc, x0, y0, 0);
898 
899  x_end = x0 + ctb_size;
900  if (x_end > fc->ps.pps->width)
901  x_end = fc->ps.pps->width;
902  y_end = y0 + ctb_size;
903  if (y_end > fc->ps.pps->height)
904  y_end = fc->ps.pps->height;
905 
906  for (int c_idx = 0; c_idx < c_end; c_idx++) {
907  const int hs = sps->hshift[c_idx];
908  const int vs = sps->vshift[c_idx];
909  const int grid = c_idx ? (CHROMA_GRID << vs) : LUMA_GRID;
910  const int beta_offset = params->beta_offset[c_idx];
911  const int tc_offset = params->tc_offset[c_idx];
912 
913  for (y = y0; y < y_end; y += grid) {
914  const uint8_t horizontal_ctu_edge = !(y % fc->ps.sps->ctb_size_y);
915  if (!y)
916  continue;
917 
918  for (x = x0 ? x0: 0; x < x_end; x += (DEBLOCK_STEP << hs)) {
919  int32_t bs[4], beta[4], tc[4], all_zero_bs = 1;
920  uint8_t max_len_p[4], max_len_q[4];
921 
922  for (int i = 0; i < DEBLOCK_STEP >> (2 - hs); i++) {
923  const int dx = i << 2;
924 
925  bs[i] = (x + dx < x_end) ? TAB_BS(fc->tab.horizontal_bs[c_idx], x + dx, y) : 0;
926  if (bs[i]) {
927  src = &fc->frame->data[c_idx][(y >> vs) * fc->frame->linesize[c_idx] + (((x + dx)>> hs) << fc->ps.sps->pixel_shift)];
928  qp = get_qp(fc, src, x + dx, y, c_idx, 0);
929 
930  beta[i] = betatable[av_clip(qp + beta_offset, 0, MAX_QP)];
931 
932  max_filter_length(fc, x + dx, y, c_idx, 0, horizontal_ctu_edge, bs[i], &max_len_p[i], &max_len_q[i]);
933  all_zero_bs = 0;
934  }
935  tc[i] = bs[i] ? TC_CALC(qp, bs[i]) : 0;
936  }
937  if (!all_zero_bs) {
938  src = &fc->frame->data[c_idx][(y >> vs) * fc->frame->linesize[c_idx] + ((x >> hs) << fc->ps.sps->pixel_shift)];
939  if (!c_idx) {
940  fc->vvcdsp.lf.filter_luma[0](src, fc->frame->linesize[c_idx],
941  beta, tc, no_p, no_q, max_len_p, max_len_q, horizontal_ctu_edge);
942  } else {
943  fc->vvcdsp.lf.filter_chroma[0](src, fc->frame->linesize[c_idx],
944  beta, tc, no_p, no_q, max_len_p, max_len_q, hs);
945  }
946  }
947  }
948  }
949  }
950 }
951 
952 static void alf_copy_border(uint8_t *dst, const uint8_t *src,
953  const int pixel_shift, int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride)
954 {
955  width <<= pixel_shift;
956  for (int i = 0; i < height; i++) {
957  memcpy(dst, src, width);
958  dst += dst_stride;
959  src += src_stride;
960  }
961 }
962 
963 static void alf_extend_vert(uint8_t *_dst, const uint8_t *_src,
964  const int pixel_shift, const int width, const int height, ptrdiff_t stride)
965 {
966  if (pixel_shift == 0) {
967  for (int i = 0; i < height; i++) {
968  memset(_dst, *_src, width);
969  _src += stride;
970  _dst += stride;
971  }
972  } else {
973  const uint16_t *src = (const uint16_t *)_src;
974  uint16_t *dst = (uint16_t *)_dst;
975  stride >>= pixel_shift;
976 
977  for (int i = 0; i < height; i++) {
978  for (int j = 0; j < width; j++)
979  dst[j] = *src;
980  src += stride;
981  dst += stride;
982  }
983  }
984 }
985 
986 static void alf_extend_horz(uint8_t *dst, const uint8_t *src,
987  const int pixel_shift, int width, const int height, const ptrdiff_t stride)
988 {
989  width <<= pixel_shift;
990  for (int i = 0; i < height; i++) {
991  memcpy(dst, src, width);
992  dst += stride;
993  }
994 }
995 
996 static void alf_copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src, const ptrdiff_t src_stride,
997  const int x, const int y, const int width, const int height, const int x_ctb, const int y_ctb, const int c_idx)
998 {
999  const int ps = fc->ps.sps->pixel_shift;
1000  const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
1001  const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
1002  const int border_pixels = (c_idx == 0) ? ALF_BORDER_LUMA : ALF_BORDER_CHROMA;
1003  const int offset_h[] = { 0, height - border_pixels };
1004  const int offset_v[] = { 0, width - border_pixels };
1005 
1006  /* copy horizontal edges */
1007  for (int i = 0; i < FF_ARRAY_ELEMS(offset_h); i++) {
1008  alf_copy_border(fc->tab.alf_pixel_buffer_h[c_idx][i] + ((border_pixels * y_ctb * w + x)<< ps),
1009  src + offset_h[i] * src_stride, ps, width, border_pixels, w << ps, src_stride);
1010  }
1011  /* copy vertical edges */
1012  for (int i = 0; i < FF_ARRAY_ELEMS(offset_v); i++) {
1013  alf_copy_border(fc->tab.alf_pixel_buffer_v[c_idx][i] + ((h * x_ctb + y) * (border_pixels << ps)),
1014  src + (offset_v[i] << ps), ps, border_pixels, height, border_pixels << ps, src_stride);
1015  }
1016 }
1017 
1018 static void alf_fill_border_h(uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src, const ptrdiff_t src_stride,
1019  const uint8_t *border, const int width, const int border_pixels, const int ps, const int edge)
1020 {
1021  if (edge)
1022  alf_extend_horz(dst, border, ps, width, border_pixels, dst_stride);
1023  else
1024  alf_copy_border(dst, src, ps, width, border_pixels, dst_stride, src_stride);
1025 }
1026 
1027 static void alf_fill_border_v(uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src,
1028  const uint8_t *border, const int border_pixels, const int height, const int pixel_shift, const int *edges, const int edge)
1029 {
1030  const ptrdiff_t src_stride = (border_pixels << pixel_shift);
1031 
1032  if (edge) {
1033  alf_extend_vert(dst, border, pixel_shift, border_pixels, height + 2 * border_pixels, dst_stride);
1034  return;
1035  }
1036 
1037  //left/right
1038  alf_copy_border(dst + dst_stride * border_pixels * edges[TOP], src + src_stride * border_pixels * edges[TOP],
1039  pixel_shift, border_pixels, height + (!edges[TOP] + !edges[BOTTOM]) * border_pixels, dst_stride, src_stride);
1040 
1041  //top left/right
1042  if (edges[TOP])
1043  alf_extend_horz(dst, dst + dst_stride * border_pixels, pixel_shift, border_pixels, border_pixels, dst_stride);
1044 
1045  //bottom left/right
1046  if (edges[BOTTOM]) {
1047  dst += dst_stride * (border_pixels + height);
1048  alf_extend_horz(dst, dst - dst_stride, pixel_shift, border_pixels, border_pixels, dst_stride);
1049  }
1050 }
1051 
1052 static void alf_prepare_buffer(VVCFrameContext *fc, uint8_t *_dst, const uint8_t *_src, const int x, const int y,
1053  const int x_ctb, const int y_ctb, const int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride,
1054  const int c_idx, const int *edges)
1055 {
1056  const int ps = fc->ps.sps->pixel_shift;
1057  const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
1058  const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
1059  const int border_pixels = c_idx == 0 ? ALF_BORDER_LUMA : ALF_BORDER_CHROMA;
1060  uint8_t *dst, *src;
1061 
1062  copy_ctb(_dst, _src, width << ps, height, dst_stride, src_stride);
1063 
1064  //top
1065  src = fc->tab.alf_pixel_buffer_h[c_idx][1] + (((border_pixels * w) << ps) * (y_ctb - 1) + (x << ps));
1066  dst = _dst - border_pixels * dst_stride;
1067  alf_fill_border_h(dst, dst_stride, src, w << ps, _dst, width, border_pixels, ps, edges[TOP]);
1068 
1069  //bottom
1070  src = fc->tab.alf_pixel_buffer_h[c_idx][0] + (((border_pixels * w) << ps) * (y_ctb + 1) + (x << ps));
1071  dst = _dst + height * dst_stride;
1072  alf_fill_border_h(dst, dst_stride, src, w << ps, _dst + (height - 1) * dst_stride, width, border_pixels, ps, edges[BOTTOM]);
1073 
1074 
1075  //left
1076  src = fc->tab.alf_pixel_buffer_v[c_idx][1] + (h * (x_ctb - 1) + y - border_pixels) * (border_pixels << ps);
1077  dst = _dst - (border_pixels << ps) - border_pixels * dst_stride;
1078  alf_fill_border_v(dst, dst_stride, src, dst + (border_pixels << ps), border_pixels, height, ps, edges, edges[LEFT]);
1079 
1080  //right
1081  src = fc->tab.alf_pixel_buffer_v[c_idx][0] + (h * (x_ctb + 1) + y - border_pixels) * (border_pixels << ps);
1082  dst = _dst + (width << ps) - border_pixels * dst_stride;
1083  alf_fill_border_v(dst, dst_stride, src, dst - (1 << ps), border_pixels, height, ps, edges, edges[RIGHT]);
1084 }
1085 
1086 #define ALF_MAX_BLOCKS_IN_CTU (MAX_CTU_SIZE * MAX_CTU_SIZE / ALF_BLOCK_SIZE / ALF_BLOCK_SIZE)
1087 #define ALF_MAX_FILTER_SIZE (ALF_MAX_BLOCKS_IN_CTU * ALF_NUM_COEFF_LUMA)
1088 
1089 static void alf_get_coeff_and_clip(VVCLocalContext *lc, int16_t *coeff, int16_t *clip,
1090  const uint8_t *src, ptrdiff_t src_stride, int width, int height, int vb_pos, ALFParams *alf)
1091 {
1092  const VVCFrameContext *fc = lc->fc;
1093  const H266RawSliceHeader *rsh = lc->sc->sh.r;
1094  uint8_t fixed_clip_set[ALF_NUM_FILTERS_LUMA][ALF_NUM_COEFF_LUMA] = { 0 };
1095  const int16_t *coeff_set;
1096  const uint8_t *clip_idx_set;
1097  const uint8_t *class_to_filt;
1098  const int size = width * height / ALF_BLOCK_SIZE / ALF_BLOCK_SIZE;
1099  int class_idx[ALF_MAX_BLOCKS_IN_CTU];
1100  int transpose_idx[ALF_MAX_BLOCKS_IN_CTU];
1101 
1102  if (alf->ctb_filt_set_idx_y < 16) {
1103  coeff_set = &ff_vvc_alf_fix_filt_coeff[0][0];
1104  clip_idx_set = &fixed_clip_set[0][0];
1105  class_to_filt = ff_vvc_alf_class_to_filt_map[alf->ctb_filt_set_idx_y];
1106  } else {
1107  const int id = rsh->sh_alf_aps_id_luma[alf->ctb_filt_set_idx_y - 16];
1108  const VVCALF *aps = fc->ps.alf_list[id];
1109  coeff_set = &aps->luma_coeff[0][0];
1110  clip_idx_set = &aps->luma_clip_idx[0][0];
1111  class_to_filt = ff_vvc_alf_aps_class_to_filt_map;
1112  }
1113  fc->vvcdsp.alf.classify(class_idx, transpose_idx, src, src_stride, width, height,
1114  vb_pos, lc->alf_gradient_tmp);
1115  fc->vvcdsp.alf.recon_coeff_and_clip(coeff, clip, class_idx, transpose_idx, size,
1116  coeff_set, clip_idx_set, class_to_filt);
1117 }
1118 
1119 static void alf_filter_luma(VVCLocalContext *lc, uint8_t *dst, const uint8_t *src,
1120  const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int x0, const int y0,
1121  const int width, const int height, const int _vb_pos, ALFParams *alf)
1122 {
1123  const VVCFrameContext *fc = lc->fc;
1124  int vb_pos = _vb_pos - y0;
1125  int16_t *coeff = (int16_t*)lc->tmp;
1126  int16_t *clip = (int16_t *)lc->tmp1;
1127 
1128  av_assert0(ALF_MAX_FILTER_SIZE <= sizeof(lc->tmp));
1129  av_assert0(ALF_MAX_FILTER_SIZE * sizeof(int16_t) <= sizeof(lc->tmp1));
1130 
1131  alf_get_coeff_and_clip(lc, coeff, clip, src, src_stride, width, height, vb_pos, alf);
1132  fc->vvcdsp.alf.filter[LUMA](dst, dst_stride, src, src_stride, width, height, coeff, clip, vb_pos);
1133 }
1134 
1135 static int alf_clip_from_idx(const VVCFrameContext *fc, const int idx)
1136 {
1137  const VVCSPS *sps = fc->ps.sps;
1138  const int offset[] = {0, 3, 5, 7};
1139 
1140  return 1 << (sps->bit_depth - offset[idx]);
1141 }
1142 
1143 static void alf_filter_chroma(VVCLocalContext *lc, uint8_t *dst, const uint8_t *src,
1144  const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int c_idx,
1145  const int width, const int height, const int vb_pos, ALFParams *alf)
1146 {
1147  VVCFrameContext *fc = lc->fc;
1148  const H266RawSliceHeader *rsh = lc->sc->sh.r;
1149  const VVCALF *aps = fc->ps.alf_list[rsh->sh_alf_aps_id_chroma];
1150  const int idx = alf->alf_ctb_filter_alt_idx[c_idx - 1];
1151  const int16_t *coeff = aps->chroma_coeff[idx];
1152  int16_t clip[ALF_NUM_COEFF_CHROMA];
1153 
1154  for (int i = 0; i < ALF_NUM_COEFF_CHROMA; i++)
1155  clip[i] = alf_clip_from_idx(fc, aps->chroma_clip_idx[idx][i]);
1156 
1157  fc->vvcdsp.alf.filter[CHROMA](dst, dst_stride, src, src_stride, width, height, coeff, clip, vb_pos);
1158 }
1159 
1160 static void alf_filter_cc(VVCLocalContext *lc, uint8_t *dst, const uint8_t *luma,
1161  const ptrdiff_t dst_stride, const ptrdiff_t luma_stride, const int c_idx,
1162  const int width, const int height, const int hs, const int vs, const int vb_pos, ALFParams *alf)
1163 {
1164  const VVCFrameContext *fc = lc->fc;
1165  const H266RawSliceHeader *rsh = lc->sc->sh.r;
1166  const int idx = c_idx - 1;
1167  const int cc_aps_id = c_idx == CB ? rsh->sh_alf_cc_cb_aps_id : rsh->sh_alf_cc_cr_aps_id;
1168  const VVCALF *aps = fc->ps.alf_list[cc_aps_id];
1169 
1170  if (aps) {
1171  const int16_t *coeff = aps->cc_coeff[idx][alf->ctb_cc_idc[idx] - 1];
1172 
1173  fc->vvcdsp.alf.filter_cc(dst, dst_stride, luma, luma_stride, width, height, hs, vs, coeff, vb_pos);
1174  }
1175 }
1176 
1177 void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext* lc, const int x0, const int y0)
1178 {
1179  VVCFrameContext *fc = lc->fc;
1180  const int x_ctb = x0 >> fc->ps.sps->ctb_log2_size_y;
1181  const int y_ctb = y0 >> fc->ps.sps->ctb_log2_size_y;
1182  const int ctb_size_y = fc->ps.sps->ctb_size_y;
1183  const int ps = fc->ps.sps->pixel_shift;
1184  const int c_end = fc->ps.sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1;
1185 
1186  for (int c_idx = 0; c_idx < c_end; c_idx++) {
1187  const int hs = fc->ps.sps->hshift[c_idx];
1188  const int vs = fc->ps.sps->vshift[c_idx];
1189  const int x = x0 >> hs;
1190  const int y = y0 >> vs;
1191  const int width = FFMIN(fc->ps.pps->width - x0, ctb_size_y) >> hs;
1192  const int height = FFMIN(fc->ps.pps->height - y0, ctb_size_y) >> vs;
1193 
1194  const int src_stride = fc->frame->linesize[c_idx];
1195  uint8_t* src = &fc->frame->data[c_idx][y * src_stride + (x << ps)];
1196 
1197  alf_copy_ctb_to_hv(fc, src, src_stride, x, y, width, height, x_ctb, y_ctb, c_idx);
1198  }
1199 }
1200 
1201 void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0)
1202 {
1203  VVCFrameContext *fc = lc->fc;
1204  const VVCPPS *pps = fc->ps.pps;
1205  const int x_ctb = x0 >> fc->ps.sps->ctb_log2_size_y;
1206  const int y_ctb = y0 >> fc->ps.sps->ctb_log2_size_y;
1207  const int ctb_size_y = fc->ps.sps->ctb_size_y;
1208  const int ps = fc->ps.sps->pixel_shift;
1209  const int padded_stride = EDGE_EMU_BUFFER_STRIDE << ps;
1210  const int padded_offset = padded_stride * ALF_PADDING_SIZE + (ALF_PADDING_SIZE << ps);
1211  const int c_end = fc->ps.sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1;
1212  ALFParams *alf = &CTB(fc->tab.alf, x_ctb, y_ctb);
1213  int edges[MAX_EDGES] = { x_ctb == 0, y_ctb == 0, x_ctb == pps->ctb_width - 1, y_ctb == pps->ctb_height - 1 };
1214 
1215  if (!pps->r->pps_loop_filter_across_tiles_enabled_flag) {
1216  edges[LEFT] = edges[LEFT] || (lc->boundary_flags & BOUNDARY_LEFT_TILE);
1217  edges[TOP] = edges[TOP] || (lc->boundary_flags & BOUNDARY_UPPER_TILE);
1218  edges[RIGHT] = edges[RIGHT] || pps->ctb_to_col_bd[x_ctb] != pps->ctb_to_col_bd[x_ctb + 1];
1219  edges[BOTTOM] = edges[BOTTOM] || pps->ctb_to_row_bd[y_ctb] != pps->ctb_to_row_bd[y_ctb + 1];
1220  }
1221 
1222  if (!pps->r->pps_loop_filter_across_slices_enabled_flag) {
1223  edges[LEFT] = edges[LEFT] || (lc->boundary_flags & BOUNDARY_LEFT_SLICE);
1224  edges[TOP] = edges[TOP] || (lc->boundary_flags & BOUNDARY_UPPER_SLICE);
1225  edges[RIGHT] = edges[RIGHT] || CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb + 1, y_ctb);
1226  edges[BOTTOM] = edges[BOTTOM] || CTB(fc->tab.slice_idx, x_ctb, y_ctb) != CTB(fc->tab.slice_idx, x_ctb, y_ctb + 1);
1227  }
1228 
1229  for (int c_idx = 0; c_idx < c_end; c_idx++) {
1230  const int hs = fc->ps.sps->hshift[c_idx];
1231  const int vs = fc->ps.sps->vshift[c_idx];
1232  const int ctb_size_h = ctb_size_y >> hs;
1233  const int ctb_size_v = ctb_size_y >> vs;
1234  const int x = x0 >> hs;
1235  const int y = y0 >> vs;
1236  const int pic_width = fc->ps.pps->width >> hs;
1237  const int pic_height = fc->ps.pps->height >> vs;
1238  const int width = FFMIN(pic_width - x, ctb_size_h);
1239  const int height = FFMIN(pic_height - y, ctb_size_v);
1240  const int src_stride = fc->frame->linesize[c_idx];
1241  uint8_t *src = &fc->frame->data[c_idx][y * src_stride + (x << ps)];
1242  uint8_t *padded;
1243 
1244  if (alf->ctb_flag[c_idx] || (!c_idx && (alf->ctb_cc_idc[0] || alf->ctb_cc_idc[1]))) {
1245  padded = (c_idx ? lc->alf_buffer_chroma : lc->alf_buffer_luma) + padded_offset;
1246  alf_prepare_buffer(fc, padded, src, x, y, x_ctb, y_ctb, width, height,
1247  padded_stride, src_stride, c_idx, edges);
1248  }
1249  if (alf->ctb_flag[c_idx]) {
1250  if (!c_idx) {
1251  alf_filter_luma(lc, src, padded, src_stride, padded_stride, x, y,
1252  width, height, y + ctb_size_v - ALF_VB_POS_ABOVE_LUMA, alf);
1253  } else {
1254  alf_filter_chroma(lc, src, padded, src_stride, padded_stride, c_idx,
1255  width, height, ctb_size_v - ALF_VB_POS_ABOVE_CHROMA, alf);
1256  }
1257  }
1258  if (c_idx && alf->ctb_cc_idc[c_idx - 1]) {
1259  padded = lc->alf_buffer_luma + padded_offset;
1260  alf_filter_cc(lc, src, padded, src_stride, padded_stride, c_idx,
1261  width, height, hs, vs, (ctb_size_v << vs) - ALF_VB_POS_ABOVE_LUMA, alf);
1262  }
1263 
1264  alf->applied[c_idx] = 1;
1265  }
1266 }
1267 
1268 
1269 void ff_vvc_lmcs_filter(const VVCLocalContext *lc, const int x, const int y)
1270 {
1271  const SliceContext *sc = lc->sc;
1272  const VVCFrameContext *fc = lc->fc;
1273  const int ctb_size = fc->ps.sps->ctb_size_y;
1274  const int width = FFMIN(fc->ps.pps->width - x, ctb_size);
1275  const int height = FFMIN(fc->ps.pps->height - y, ctb_size);
1276  uint8_t *data = fc->frame->data[LUMA] + y * fc->frame->linesize[LUMA] + (x << fc->ps.sps->pixel_shift);
1277  if (sc->sh.r->sh_lmcs_used_flag)
1278  fc->vvcdsp.lmcs.filter(data, fc->frame->linesize[LUMA], width, height, &fc->ps.lmcs.inv_lut);
1279 }
ALFParams::applied
uint8_t applied[3]
Definition: vvc_ctu.h:463
CB
#define CB
Definition: hevc_filter.c:32
A
#define A(x)
Definition: vpx_arith.h:28
VVCSPS
Definition: vvc_ps.h:58
MIN_TU_LOG2
#define MIN_TU_LOG2
MinTbLog2SizeY.
Definition: vvcdec.h:39
DBParams
Definition: hevcdec.h:341
ALF_BORDER_LUMA
#define ALF_BORDER_LUMA
Definition: vvc_ctu.h:73
ff_vvc_sao_filter
void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
sao filter for the CTU
Definition: vvc_filter.c:154
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: vvc_filter.c:795
vvc_deblock_bs_chroma_horizontal
static void vvc_deblock_bs_chroma_horizontal(const VVCLocalContext *lc, const int x0, const int y0, const int width, const int height)
Definition: vvc_filter.c:673
level
uint8_t level
Definition: svq3.c:204
VVCPPS
Definition: vvc_ps.h:92
av_clip
#define av_clip
Definition: common.h:98
ff_vvc_lmcs_filter
void ff_vvc_lmcs_filter(const VVCLocalContext *lc, const int x, const int y)
lmcs filter for the CTU
Definition: vvc_filter.c:1269
tctable
static const uint16_t tctable[66]
Definition: vvc_filter.c:38
vvc_deblock_bs
static void vvc_deblock_bs(const VVCLocalContext *lc, const int x0, const int y0, const int vertical)
Definition: vvc_filter.c:703
SAO_BAND
@ SAO_BAND
Definition: hevcdec.h:159
VVC_MAX_SAMPLE_ARRAYS
@ VVC_MAX_SAMPLE_ARRAYS
Definition: vvc.h:77
src1
const pixel * src1
Definition: h264pred_template.c:421
ff_vvc_alf_filter
void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0)
alf filter for the CTU
Definition: vvc_filter.c:1201
ALF_VB_POS_ABOVE_LUMA
#define ALF_VB_POS_ABOVE_LUMA
Definition: vvc_ctu.h:76
VVCLocalContext::alf_buffer_chroma
uint8_t alf_buffer_chroma[(MAX_CTU_SIZE+2 *ALF_PADDING_SIZE) *EDGE_EMU_BUFFER_STRIDE *2]
Definition: vvc_ctu.h:387
VVCLocalContext::tmp
int16_t tmp[MAX_PB_SIZE *MAX_PB_SIZE]
Definition: vvc_ctu.h:380
MIN_PU_LOG2
#define MIN_PU_LOG2
Definition: vvcdec.h:40
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: vvc_filter.c:1027
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, ALFParams *alf)
Definition: vvc_filter.c:1143
alf_clip_from_idx
static int alf_clip_from_idx(const VVCFrameContext *fc, const int idx)
Definition: vvc_filter.c:1135
w
uint8_t w
Definition: llviddspenc.c:38
VVCLocalContext::sc
SliceContext * sc
Definition: vvc_ctu.h:430
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: vvc_filter.c:742
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:148
Mv::y
int16_t y
vertical component of motion vector
Definition: hevcdec.h:297
SAO_EDGE
@ SAO_EDGE
Definition: hevcdec.h:160
VVCSH::r
const H266RawSliceHeader * r
RefStruct reference.
Definition: vvc_ps.h:225
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:472
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: vvc_filter.c:1018
RIGHT
#define RIGHT
Definition: vvc_filter.c:31
RefPicList
Definition: hevcdec.h:189
vvc_deblock_subblock_bs_horizontal
static void vvc_deblock_subblock_bs_horizontal(const VVCLocalContext *lc, const int cb_x, const int cb_y, const int x0, const int y0, const int width, const int height)
Definition: vvc_filter.c:441
ff_vvc_get_qPy
int ff_vvc_get_qPy(const VVCFrameContext *fc, const int xc, const int yc)
Definition: vvc_ctu.c:2536
PF_INTRA
@ PF_INTRA
Definition: hevcdec.h:113
BOUNDARY_LEFT_TILE
#define BOUNDARY_LEFT_TILE
Definition: hevcdec.h:432
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: vvc_filter.c:963
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: vvc_filter.c:952
H266RawSliceHeader::sh_alf_cc_cr_aps_id
uint8_t sh_alf_cc_cr_aps_id
Definition: cbs_h266.h:790
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, ALFParams *alf)
Definition: vvc_filter.c:1119
vvc_data.h
VVCLocalContext::sao_buffer
uint8_t sao_buffer[(MAX_CTU_SIZE+2 *SAO_PADDING_SIZE) *EDGE_EMU_BUFFER_STRIDE *2]
Definition: vvc_ctu.h:385
VVCLocalContext::fc
VVCFrameContext * fc
Definition: vvc_ctu.h:431
VVCLocalContext::tmp1
int16_t tmp1[MAX_PB_SIZE *MAX_PB_SIZE]
Definition: vvc_ctu.h:381
tab
static const struct twinvq_data tab
Definition: twinvq_data.h:10345
vvc_refs.h
SliceContext::rpl
RefPicList * rpl
Definition: vvcdec.h:88
VVCALF
Definition: vvc_ps.h:161
vvc_deblock_bs_luma_vertical
static void vvc_deblock_bs_luma_vertical(const VVCLocalContext *lc, const int x0, const int y0, const int width, const int height)
Definition: vvc_filter.c:531
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
DBParams::beta_offset
int beta_offset
Definition: hevcdec.h:342
clip
clip
Definition: af_crystalizer.c:121
DBParams::tc_offset
int tc_offset
Definition: hevcdec.h:343
width
#define width
deblock_bs_fn
void(* deblock_bs_fn)(const VVCLocalContext *lc, const int x0, const int y0, const int width, const int height)
Definition: vvc_filter.c:700
boundary_strength
static int boundary_strength(const VVCLocalContext *lc, const MvField *curr, const MvField *neigh, const RefPicList *neigh_rpl)
Definition: vvc_filter.c:308
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
B
#define B
Definition: huffyuv.h:42
ALF_PADDING_SIZE
#define ALF_PADDING_SIZE
Definition: vvc_ctu.h:70
TOP
#define TOP
Definition: vvc_filter.c:30
ALF_NUM_COEFF_CHROMA
#define ALF_NUM_COEFF_CHROMA
Definition: vvc_ps.h:158
vvc_deblock_subblock_bs_vertical
static void vvc_deblock_subblock_bs_vertical(const VVCLocalContext *lc, const int cb_x, const int cb_y, const int x0, const int y0, const int width, const int height)
Definition: vvc_filter.c:403
VVCLocalContext::alf_gradient_tmp
int32_t alf_gradient_tmp[ALF_GRADIENT_SIZE *ALF_GRADIENT_SIZE *ALF_NUM_DIR]
Definition: vvc_ctu.h:388
H266RawSliceHeader::sh_lmcs_used_flag
uint8_t sh_lmcs_used_flag
Definition: cbs_h266.h:792
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
ff_vvc_alf_aps_class_to_filt_map
const uint8_t ff_vvc_alf_aps_class_to_filt_map[25]
Definition: vvc_data.c:1731
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: vvc_filter.c:81
aps
static int FUNC() aps(CodedBitstreamContext *ctx, RWContext *rw, H266RawAPS *current, int prefix)
Definition: cbs_h266_syntax_template.c:2460
VVCLocalContext::alf_buffer_luma
uint8_t alf_buffer_luma[(MAX_CTU_SIZE+2 *ALF_PADDING_SIZE) *EDGE_EMU_BUFFER_STRIDE *2]
Definition: vvc_ctu.h:386
NULL
#define NULL
Definition: coverity.c:32
VVCLocalContext
Definition: vvc_ctu.h:368
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: vvc_filter.c:62
list
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining list
Definition: filter_design.txt:25
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: vvc_filter.c:143
BOUNDARY_UPPER_TILE
#define BOUNDARY_UPPER_TILE
Definition: hevcdec.h:434
DEBLOCK_STEP
#define DEBLOCK_STEP
Definition: vvc_filter.c:304
MvField::ciip_flag
uint8_t ciip_flag
ciip_flag
Definition: vvc_ctu.h:201
Mv::x
int16_t x
horizontal component of motion vector
Definition: hevcdec.h:296
PF_BI
@ PF_BI
Definition: hevcdec.h:116
SliceContext
Definition: mss12.h:70
SAOParams::offset_val
int16_t offset_val[3][5]
SaoOffsetVal.
Definition: hevcdsp.h:42
TC_CALC
#define TC_CALC(qp, bs)
Definition: vvc_filter.c:770
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: vvc_filter.c:761
BOUNDARY_UPPER_SLICE
#define BOUNDARY_UPPER_SLICE
Definition: hevcdec.h:433
pps
static int FUNC() pps(CodedBitstreamContext *ctx, RWContext *rw, H264RawPPS *current)
Definition: cbs_h264_syntax_template.c:404
vvc_deblock_bs_luma_horizontal
static void vvc_deblock_bs_luma_horizontal(const VVCLocalContext *lc, const int x0, const int y0, const int width, const int height)
Definition: vvc_filter.c:588
ff_vvc_deblock_vertical
void ff_vvc_deblock_vertical(const VVCLocalContext *lc, int x0, int y0)
vertical deblock filter for the CTU
Definition: vvc_filter.c:808
ff_vvc_alf_copy_ctu_to_hv
void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext *lc, const int x0, const int y0)
Definition: vvc_filter.c:1177
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 RefPicList *rpl_p, const int c_idx, const int off_to_cb, const uint8_t has_sub_block)
Definition: vvc_filter.c:481
CTB
#define CTB(tab, x, y)
Definition: hevc_filter.c:254
ALF_NUM_COEFF_LUMA
#define ALF_NUM_COEFF_LUMA
Definition: vvc_ps.h:157
TAB_BS
#define TAB_BS(t, x, y)
Definition: vvc_filter.c:300
size
int size
Definition: twinvq_data.h:10344
get_qPc
static int get_qPc(const VVCFrameContext *fc, const int x0, const int y0, const int chroma)
Definition: vvc_filter.c:54
CR
#define CR
Definition: hevc_filter.c:33
H266RawSliceHeader::sh_alf_aps_id_chroma
uint8_t sh_alf_aps_id_chroma
Definition: cbs_h266.h:786
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 x_ctb, const int y_ctb, const int c_idx)
Definition: vvc_filter.c:996
MvField
Definition: hevcdec.h:300
vvc_deblock_bs_chroma_vertical
static void vvc_deblock_bs_chroma_vertical(const VVCLocalContext *lc, const int x0, const int y0, const int width, const int height)
Definition: vvc_filter.c:645
frame.h
ALF_BORDER_CHROMA
#define ALF_BORDER_CHROMA
Definition: vvc_ctu.h:74
height
#define height
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
ALF_NUM_FILTERS_LUMA
#define ALF_NUM_FILTERS_LUMA
Definition: vvc_ps.h:153
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 x_ctb, const int y_ctb, const int top)
Definition: vvc_filter.c:100
vvc_filter.h
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: vvc_filter.c:986
MvField::pred_flag
int8_t pred_flag
Definition: hevcdec.h:303
SAOParams::eo_class
int eo_class[3]
sao_eo_class
Definition: hevcdsp.h:40
ALFParams::ctb_cc_idc
uint8_t ctb_cc_idc[2]
alf_ctb_cc_cb_idc, alf_ctb_cc_cr_idc
Definition: vvc_ctu.h:461
H266RawSliceHeader
Definition: cbs_h266.h:769
VVCLocalContext::boundary_flags
int boundary_flags
Definition: vvc_ctu.h:428
MODE_INTRA
#define MODE_INTRA
Definition: vp3.c:83
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
H266RawSliceHeader::sh_alf_aps_id_luma
uint8_t sh_alf_aps_id_luma[8]
Definition: cbs_h266.h:783
vvc_ctu.h
MAX_PB_SIZE
#define MAX_PB_SIZE
Definition: hevcdsp.h:32
TAB_MAX_LEN
#define TAB_MAX_LEN(t, x, y)
Definition: vvc_filter.c:301
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: vvc_filter.c:776
BOTTOM
#define BOTTOM
Definition: vvc_filter.c:32
ff_vvc_alf_class_to_filt_map
const uint8_t ff_vvc_alf_class_to_filt_map[16][25]
Definition: vvc_data.c:1712
av_always_inline
#define av_always_inline
Definition: attributes.h:49
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
sao_copy_ctb_to_hv
static void sao_copy_ctb_to_hv(VVCLocalContext *lc, const int rx, const int ry, const int top)
Definition: vvc_filter.c:123
EDGE_EMU_BUFFER_STRIDE
#define EDGE_EMU_BUFFER_STRIDE
Definition: hevcdec.h:67
H266RawSliceHeader::sh_alf_cc_cb_aps_id
uint8_t sh_alf_cc_cb_aps_id
Definition: cbs_h266.h:788
SAOParams
Definition: hevcdsp.h:34
stride
#define stride
Definition: h264pred_template.c:537
ALF_VB_POS_ABOVE_CHROMA
#define ALF_VB_POS_ABOVE_CHROMA
Definition: vvc_ctu.h:77
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
ff_vvc_alf_fix_filt_coeff
const int16_t ff_vvc_alf_fix_filt_coeff[64][12]
Definition: vvc_data.c:1644
pos
unsigned int pos
Definition: spdifenc.c:413
ALFParams::alf_ctb_filter_alt_idx
uint8_t alf_ctb_filter_alt_idx[2]
alf_ctb_filter_alt_idx[]
Definition: vvc_ctu.h:460
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
id
enum AVCodecID id
Definition: dts2pts.c:364
left
Tag MUST be and< 10hcoeff half pel interpolation filter coefficients, hcoeff[0] are the 2 middle coefficients[1] are the next outer ones and so on, resulting in a filter like:...eff[2], hcoeff[1], hcoeff[0], hcoeff[0], hcoeff[1], hcoeff[2] ... the sign of the coefficients is not explicitly stored but alternates after each coeff and coeff[0] is positive, so ...,+,-,+,-,+,+,-,+,-,+,... hcoeff[0] is not explicitly stored but found by subtracting the sum of all stored coefficients with signs from 32 hcoeff[0]=32 - hcoeff[1] - hcoeff[2] - ... a good choice for hcoeff and htaps is htaps=6 hcoeff={40,-10, 2} an alternative which requires more computations at both encoder and decoder side and may or may not be better is htaps=8 hcoeff={42,-14, 6,-2}ref_frames minimum of the number of available reference frames and max_ref_frames for example the first frame after a key frame always has ref_frames=1spatial_decomposition_type wavelet type 0 is a 9/7 symmetric compact integer wavelet 1 is a 5/3 symmetric compact integer wavelet others are reserved stored as delta from last, last is reset to 0 if always_reset||keyframeqlog quality(logarithmic quantizer scale) stored as delta from last, last is reset to 0 if always_reset||keyframemv_scale stored as delta from last, last is reset to 0 if always_reset||keyframe FIXME check that everything works fine if this changes between framesqbias dequantization bias stored as delta from last, last is reset to 0 if always_reset||keyframeblock_max_depth maximum depth of the block tree stored as delta from last, last is reset to 0 if always_reset||keyframequant_table quantization tableHighlevel bitstream structure:==============================--------------------------------------------|Header|--------------------------------------------|------------------------------------|||Block0||||split?||||yes no||||......... intra?||||:Block01 :yes no||||:Block02 :....... ..........||||:Block03 ::y DC ::ref index:||||:Block04 ::cb DC ::motion x :||||......... :cr DC ::motion y :||||....... ..........|||------------------------------------||------------------------------------|||Block1|||...|--------------------------------------------|------------ ------------ ------------|||Y subbands||Cb subbands||Cr subbands||||--- ---||--- ---||--- ---|||||LL0||HL0||||LL0||HL0||||LL0||HL0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||LH0||HH0||||LH0||HH0||||LH0||HH0|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HL1||LH1||||HL1||LH1||||HL1||LH1|||||--- ---||--- ---||--- ---||||--- ---||--- ---||--- ---|||||HH1||HL2||||HH1||HL2||||HH1||HL2|||||...||...||...|||------------ ------------ ------------|--------------------------------------------Decoding process:=================------------|||Subbands|------------||||------------|Intra DC||||LL0 subband prediction ------------|\ Dequantization ------------------- \||Reference frames|\ IDWT|------- -------|Motion \|||Frame 0||Frame 1||Compensation . OBMC v -------|------- -------|--------------. \------> Frame n output Frame Frame<----------------------------------/|...|------------------- Range Coder:============Binary Range Coder:------------------- The implemented range coder is an adapted version based upon "Range encoding: an algorithm for removing redundancy from a digitised message." by G. N. N. Martin. The symbols encoded by the Snow range coder are bits(0|1). The associated probabilities are not fix but change depending on the symbol mix seen so far. bit seen|new state ---------+----------------------------------------------- 0|256 - state_transition_table[256 - old_state];1|state_transition_table[old_state];state_transition_table={ 0, 0, 0, 0, 0, 0, 0, 0, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 190, 191, 192, 194, 194, 195, 196, 197, 198, 199, 200, 201, 202, 202, 204, 205, 206, 207, 208, 209, 209, 210, 211, 212, 213, 215, 215, 216, 217, 218, 219, 220, 220, 222, 223, 224, 225, 226, 227, 227, 229, 229, 230, 231, 232, 234, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 248, 0, 0, 0, 0, 0, 0, 0};FIXME Range Coding of integers:------------------------- FIXME Neighboring Blocks:===================left and top are set to the respective blocks unless they are outside of the image in which case they are set to the Null block top-left is set to the top left block unless it is outside of the image in which case it is set to the left block if this block has no larger parent block or it is at the left side of its parent block and the top right block is not outside of the image then the top right block is used for top-right else the top-left block is used Null block y, cb, cr are 128 level, ref, mx and my are 0 Motion Vector Prediction:=========================1. the motion vectors of all the neighboring blocks are scaled to compensate for the difference of reference frames scaled_mv=(mv *(256 *(current_reference+1)/(mv.reference+1))+128)> the median of the scaled left
Definition: snow.txt:386
ff_vvc_deblock_horizontal
void ff_vvc_deblock_horizontal(const VVCLocalContext *lc, int x0, int y0)
horizontal deblock filter for the CTU
Definition: vvc_filter.c:878
ALF_MAX_FILTER_SIZE
#define ALF_MAX_FILTER_SIZE
Definition: vvc_filter.c:1087
ALFParams::ctb_filt_set_idx_y
uint8_t ctb_filt_set_idx_y
AlfCtbFiltSetIdxY.
Definition: vvc_ctu.h:459
SAOParams::type_idx
uint8_t type_idx[3]
sao_type_idx
Definition: hevcdsp.h:44
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 x_ctb, const int y_ctb, const int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int c_idx, const int *edges)
Definition: vvc_filter.c:1052
CHROMA_GRID
#define CHROMA_GRID
Definition: vvc_filter.c:306
RefPicList::list
int list[HEVC_MAX_REFS]
Definition: hevcdec.h:191
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, ALFParams *alf)
Definition: vvc_filter.c:1089
MAX_QP
#define MAX_QP
Definition: hevcdec.h:49
MvField::mv
Mv mv[2]
mvL0, vvL1
Definition: hevcdec.h:301
ALFParams
Definition: vvc_ctu.h:457
tc
#define tc
Definition: regdef.h:69
Mv
Definition: hevcdec.h:295
MvField::ref_idx
int8_t ref_idx[2]
refIdxL0, refIdxL1
Definition: hevcdec.h:302
MAX_EDGES
#define MAX_EDGES
Definition: vvc_filter.c:33
ff_vvc_get_ref_list
const RefPicList * ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
Definition: vvc_refs.c:66
betatable
static const uint8_t betatable[64]
Definition: vvc_filter.c:47
ALF_BLOCK_SIZE
#define ALF_BLOCK_SIZE
Definition: vvc_ctu.h:71
derive_max_filter_length_luma
static void derive_max_filter_length_luma(const VVCFrameContext *fc, const int qx, const int qy, const int is_intra, const int has_subblock, const int vertical, uint8_t *max_len_p, uint8_t *max_len_q)
Definition: vvc_filter.c:378
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
SliceContext::sh
VVCSH sh
Definition: vvcdec.h:85
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
VVCFrameContext
Definition: vvcdec.h:92
ALFParams::ctb_flag
uint8_t ctb_flag[3]
alf_ctb_flag[]
Definition: vvc_ctu.h:458
int32_t
int32_t
Definition: audioconvert.c:56
LEFT
#define LEFT
Definition: vvc_filter.c:29
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: vvc_filter.c:732
coeff
static const double coeff[2][5]
Definition: vf_owdenoise.c:79
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: vvc_filter.c:801
h
h
Definition: vp9dsp_template.c:2038
BOUNDARY_LEFT_SLICE
#define BOUNDARY_LEFT_SLICE
Definition: hevcdec.h:431
SAOParams::band_position
uint8_t band_position[3]
sao_band_position
Definition: hevcdsp.h:38
ALF_MAX_BLOCKS_IN_CTU
#define ALF_MAX_BLOCKS_IN_CTU
Definition: vvc_filter.c:1086
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, ALFParams *alf)
Definition: vvc_filter.c:1160
copy_pixel
static void copy_pixel(uint8_t *dst, const uint8_t *src, const int pixel_shift)
Definition: vvc_filter.c:73
LUMA
#define LUMA
Definition: hevc_filter.c:31
LUMA_GRID
#define LUMA_GRID
Definition: vvc_filter.c:305
PF_IBC
@ PF_IBC
Definition: vvc_ctu.h:220