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 #include "libavutil/frame.h"
23 
24 #include "ctu.h"
25 #include "data.h"
26 #include "filter.h"
27 #include "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 rx, const int ry, 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 * ry) * w + x) << ps),
111  src, width << ps);
112  } else {
113  /* bottom */
114  memcpy(fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * ry + 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 * rx) * h + y) << ps), src, ps, height, 1 << ps, src_stride);
119  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);
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  const int rx = x >> fc->ps.sps->ctb_log2_size_y;
161  const int ry = y >> fc->ps.sps->ctb_log2_size_y;
162  int edges[4] = { !rx, !ry, rx == fc->ps.pps->ctb_width - 1, ry == fc->ps.pps->ctb_height - 1 };
163  const SAOParams *sao = &CTB(fc->tab.sao, rx, ry);
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  uint8_t tile_edge[] = { 0, 0, 0, 0 };
169  uint8_t subpic_edge[] = { 0, 0, 0, 0 };
170  const int subpic_idx = lc->sc->sh.r->curr_subpic_idx;
171  const uint8_t lfase = fc->ps.pps->r->pps_loop_filter_across_slices_enabled_flag;
172  const uint8_t no_tile_filter = fc->ps.pps->r->num_tiles_in_pic > 1 &&
173  !fc->ps.pps->r->pps_loop_filter_across_tiles_enabled_flag;
174  const uint8_t no_subpic_filter = fc->ps.sps->r->sps_num_subpics_minus1 &&
175  !fc->ps.sps->r->sps_loop_filter_across_subpic_enabled_flag[subpic_idx];
176  const uint8_t restore = no_subpic_filter || no_tile_filter || !lfase;
177 
178  if (restore) {
179  if (!edges[LEFT]) {
180  tile_edge[LEFT] = no_tile_filter && fc->ps.pps->ctb_to_col_bd[rx] == rx;
181  subpic_edge[LEFT] = no_subpic_filter && fc->ps.sps->r->sps_subpic_ctu_top_left_x[subpic_idx] == rx;
182  vert_edge[0] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx - 1, ry)) || tile_edge[LEFT] || subpic_edge[LEFT];
183  }
184  if (!edges[RIGHT]) {
185  tile_edge[RIGHT] = no_tile_filter && fc->ps.pps->ctb_to_col_bd[rx] != fc->ps.pps->ctb_to_col_bd[rx + 1];
186  subpic_edge[RIGHT] = no_subpic_filter &&
187  fc->ps.sps->r->sps_subpic_ctu_top_left_x[subpic_idx] + fc->ps.sps->r->sps_subpic_width_minus1[subpic_idx] == rx;
188  vert_edge[1] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx + 1, ry)) || tile_edge[RIGHT] || subpic_edge[RIGHT];
189  }
190  if (!edges[TOP]) {
191  tile_edge[TOP] = no_tile_filter && fc->ps.pps->ctb_to_row_bd[ry] == ry;
192  subpic_edge[TOP] = no_subpic_filter && fc->ps.sps->r->sps_subpic_ctu_top_left_y[subpic_idx] == ry;
193  horiz_edge[0] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx, ry - 1)) || tile_edge[TOP] || subpic_edge[TOP];
194  }
195  if (!edges[BOTTOM]) {
196  tile_edge[BOTTOM] = no_tile_filter && fc->ps.pps->ctb_to_row_bd[ry] != fc->ps.pps->ctb_to_row_bd[ry + 1];
197  subpic_edge[BOTTOM] = no_subpic_filter &&
198  fc->ps.sps->r->sps_subpic_ctu_top_left_y[subpic_idx] + fc->ps.sps->r->sps_subpic_height_minus1[subpic_idx] == ry;
199  horiz_edge[1] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx, ry + 1)) || tile_edge[BOTTOM] || subpic_edge[BOTTOM];
200  }
201  if (!edges[LEFT] && !edges[TOP]) {
202  diag_edge[0] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx - 1, ry - 1)) ||
203  tile_edge[LEFT] || tile_edge[TOP] || subpic_edge[LEFT] || subpic_edge[TOP];
204  }
205  if (!edges[TOP] && !edges[RIGHT]) {
206  diag_edge[1] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx + 1, ry - 1)) ||
207  tile_edge[RIGHT] || tile_edge[TOP] || subpic_edge[TOP] || subpic_edge[RIGHT];
208  }
209  if (!edges[RIGHT] && !edges[BOTTOM]) {
210  diag_edge[2] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx + 1, ry + 1)) ||
211  tile_edge[RIGHT] || tile_edge[BOTTOM] || subpic_edge[RIGHT] || subpic_edge[BOTTOM];
212  }
213  if (!edges[LEFT] && !edges[BOTTOM]) {
214  diag_edge[3] = (!lfase && CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx - 1, ry + 1)) ||
215  tile_edge[LEFT] || tile_edge[BOTTOM] || subpic_edge[LEFT] || subpic_edge[BOTTOM];
216  }
217  }
218 
219  for (c_idx = 0; c_idx < (fc->ps.sps->r->sps_chroma_format_idc ? 3 : 1); c_idx++) {
220  int x0 = x >> fc->ps.sps->hshift[c_idx];
221  int y0 = y >> fc->ps.sps->vshift[c_idx];
222  ptrdiff_t src_stride = fc->frame->linesize[c_idx];
223  int ctb_size_h = ctb_size_y >> fc->ps.sps->hshift[c_idx];
224  int ctb_size_v = ctb_size_y >> fc->ps.sps->vshift[c_idx];
225  int width = FFMIN(ctb_size_h, (fc->ps.pps->width >> fc->ps.sps->hshift[c_idx]) - x0);
226  int height = FFMIN(ctb_size_v, (fc->ps.pps->height >> fc->ps.sps->vshift[c_idx]) - y0);
227  int tab = sao_tab[(FFALIGN(width, 8) >> 3) - 1];
228  uint8_t *src = &fc->frame->data[c_idx][y0 * src_stride + (x0 << fc->ps.sps->pixel_shift)];
229  ptrdiff_t dst_stride;
230  uint8_t *dst;
231 
232  switch (sao->type_idx[c_idx]) {
233  case SAO_BAND:
234  fc->vvcdsp.sao.band_filter[tab](src, src, src_stride, src_stride,
235  sao->offset_val[c_idx], sao->band_position[c_idx], width, height);
236  break;
237  case SAO_EDGE:
238  {
239  const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
240  const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
241  const int sh = fc->ps.sps->pixel_shift;
242 
243  dst_stride = 2*MAX_PB_SIZE + AV_INPUT_BUFFER_PADDING_SIZE;
244  dst = lc->sao_buffer + dst_stride + AV_INPUT_BUFFER_PADDING_SIZE;
245 
246  if (!edges[TOP]) {
247  const int left = 1 - edges[LEFT];
248  const int right = 1 - edges[RIGHT];
249  const uint8_t *src1;
250  uint8_t *dst1;
251  int pos = 0;
252 
253  dst1 = dst - dst_stride - (left << sh);
254  src1 = fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * ry - 1) * w + x0 - left) << sh);
255  if (left) {
256  copy_pixel(dst1, src1, sh);
257  pos += (1 << sh);
258  }
259  memcpy(dst1 + pos, src1 + pos, width << sh);
260  if (right) {
261  pos += width << sh;
262  copy_pixel(dst1 + pos, src1 + pos, sh);
263  }
264  }
265  if (!edges[BOTTOM]) {
266  const int left = 1 - edges[LEFT];
267  const int right = 1 - edges[RIGHT];
268  const uint8_t *src1;
269  uint8_t *dst1;
270  int pos = 0;
271 
272  dst1 = dst + height * dst_stride - (left << sh);
273  src1 = fc->tab.sao_pixel_buffer_h[c_idx] + (((2 * ry + 2) * w + x0 - left) << sh);
274  if (left) {
275  copy_pixel(dst1, src1, sh);
276  pos += (1 << sh);
277  }
278  memcpy(dst1 + pos, src1 + pos, width << sh);
279  if (right) {
280  pos += width << sh;
281  copy_pixel(dst1 + pos, src1 + pos, sh);
282  }
283  }
284  if (!edges[LEFT]) {
285  copy_vert(dst - (1 << sh),
286  fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * rx - 1) * h + y0) << sh),
287  sh, height, dst_stride, 1 << sh);
288  }
289  if (!edges[RIGHT]) {
290  copy_vert(dst + (width << sh),
291  fc->tab.sao_pixel_buffer_v[c_idx] + (((2 * rx + 2) * h + y0) << sh),
292  sh, height, dst_stride, 1 << sh);
293  }
294 
295  copy_ctb(dst, src, width << sh, height, dst_stride, src_stride);
296  fc->vvcdsp.sao.edge_filter[tab](src, dst, src_stride, sao->offset_val[c_idx],
297  sao->eo_class[c_idx], width, height);
298  fc->vvcdsp.sao.edge_restore[restore](src, dst, src_stride, dst_stride,
299  sao, edges, width, height, c_idx, vert_edge, horiz_edge, diag_edge);
300  break;
301  }
302  }
303  }
304 }
305 
306 #define TAB_BS(t, x, y) (t)[((y) >> 2) * (fc->tab.sz.bs_width) + ((x) >> 2)]
307 #define TAB_MAX_LEN(t, x, y) (t)[((y) >> 2) * (fc->tab.sz.bs_width) + ((x) >> 2)]
308 
309 //8 samples a time
310 #define DEBLOCK_STEP 8
311 #define LUMA_GRID 4
312 #define CHROMA_GRID 8
313 
314 static int boundary_strength(const VVCLocalContext *lc, const MvField *curr, const MvField *neigh,
315  const RefPicList *neigh_rpl)
316 {
317  RefPicList *rpl = lc->sc->rpl;
318 
319  if (curr->pred_flag == PF_IBC)
320  return FFABS(neigh->mv[0].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 8;
321 
322  if (curr->pred_flag == PF_BI && neigh->pred_flag == PF_BI) {
323  // same L0 and L1
324  if (rpl[L0].refs[curr->ref_idx[L0]].poc == neigh_rpl[L0].refs[neigh->ref_idx[L0]].poc &&
325  rpl[L0].refs[curr->ref_idx[L0]].poc == rpl[L1].refs[curr->ref_idx[L1]].poc &&
326  neigh_rpl[L0].refs[neigh->ref_idx[L0]].poc == neigh_rpl[L1].refs[neigh->ref_idx[L1]].poc) {
327  if ((FFABS(neigh->mv[0].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 8 ||
328  FFABS(neigh->mv[1].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 8) &&
329  (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 8 ||
330  FFABS(neigh->mv[0].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 8))
331  return 1;
332  else
333  return 0;
334  } else if (neigh_rpl[L0].refs[neigh->ref_idx[L0]].poc == rpl[L0].refs[curr->ref_idx[L0]].poc &&
335  neigh_rpl[L1].refs[neigh->ref_idx[L1]].poc == rpl[L1].refs[curr->ref_idx[L1]].poc) {
336  if (FFABS(neigh->mv[0].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[0].y) >= 8 ||
337  FFABS(neigh->mv[1].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[1].y) >= 8)
338  return 1;
339  else
340  return 0;
341  } else if (neigh_rpl[L1].refs[neigh->ref_idx[L1]].poc == rpl[L0].refs[curr->ref_idx[L0]].poc &&
342  neigh_rpl[L0].refs[neigh->ref_idx[L0]].poc == rpl[L1].refs[curr->ref_idx[L1]].poc) {
343  if (FFABS(neigh->mv[1].x - curr->mv[0].x) >= 8 || FFABS(neigh->mv[1].y - curr->mv[0].y) >= 8 ||
344  FFABS(neigh->mv[0].x - curr->mv[1].x) >= 8 || FFABS(neigh->mv[0].y - curr->mv[1].y) >= 8)
345  return 1;
346  else
347  return 0;
348  } else {
349  return 1;
350  }
351  } else if ((curr->pred_flag != PF_BI) && (neigh->pred_flag != PF_BI)){ // 1 MV
352  Mv A, B;
353  int ref_A, ref_B;
354 
355  if (curr->pred_flag & 1) {
356  A = curr->mv[0];
357  ref_A = rpl[L0].refs[curr->ref_idx[L0]].poc;
358  } else {
359  A = curr->mv[1];
360  ref_A = rpl[L1].refs[curr->ref_idx[L1]].poc;
361  }
362 
363  if (neigh->pred_flag & 1) {
364  B = neigh->mv[0];
365  ref_B = neigh_rpl[L0].refs[neigh->ref_idx[L0]].poc;
366  } else {
367  B = neigh->mv[1];
368  ref_B = neigh_rpl[L1].refs[neigh->ref_idx[L1]].poc;
369  }
370 
371  if (ref_A == ref_B) {
372  if (FFABS(A.x - B.x) >= 8 || FFABS(A.y - B.y) >= 8)
373  return 1;
374  else
375  return 0;
376  } else
377  return 1;
378  }
379 
380  return 1;
381 }
382 
383 //part of 8.8.3.3 Derivation process of transform block boundary
384 static void derive_max_filter_length_luma(const VVCFrameContext *fc, const int qx, const int qy,
385  const int is_intra, const int has_subblock, const int vertical, uint8_t *max_len_p, uint8_t *max_len_q)
386 {
387  const int px = vertical ? qx - 1 : qx;
388  const int py = !vertical ? qy - 1 : qy;
389  const uint8_t *tb_size = vertical ? fc->tab.tb_width[LUMA] : fc->tab.tb_height[LUMA];
390  const int size_p = tb_size[(py >> MIN_TU_LOG2) * fc->ps.pps->min_tu_width + (px >> MIN_TU_LOG2)];
391  const int size_q = tb_size[(qy >> MIN_TU_LOG2) * fc->ps.pps->min_tu_width + (qx >> MIN_TU_LOG2)];
392  const int min_cb_log2 = fc->ps.sps->min_cb_log2_size_y;
393  const int off_p = (py >> min_cb_log2) * fc->ps.pps->min_cb_width + (px >> min_cb_log2);
394  if (size_p <= 4 || size_q <= 4) {
395  *max_len_p = *max_len_q = 1;
396  } else {
397  *max_len_p = *max_len_q = 3;
398  if (size_p >= 32)
399  *max_len_p = 7;
400  if (size_q >= 32)
401  *max_len_q = 7;
402  }
403  if (has_subblock)
404  *max_len_q = FFMIN(5, *max_len_q);
405  if (fc->tab.msf[off_p] || fc->tab.iaf[off_p])
406  *max_len_p = FFMIN(5, *max_len_p);
407 }
408 
410  const int cb_x, const int cb_y, const int x0, const int y0, const int width, const int height)
411 {
412  const VVCFrameContext *fc = lc->fc;
413  const MvField *tab_mvf = fc->tab.mvf;
414  const RefPicList *rpl = lc->sc->rpl;
415  const int min_pu_width = fc->ps.pps->min_pu_width;
416  const int log2_min_pu_size = MIN_PU_LOG2;
417 
418  // bs for TU internal vertical PU boundaries
419  for (int j = 0; j < height; j += 4) {
420  const int y_pu = (y0 + j) >> log2_min_pu_size;
421 
422  for (int i = 8 - ((x0 - cb_x) % 8); i < width; i += 8) {
423  const int xp_pu = (x0 + i - 1) >> log2_min_pu_size;
424  const int xq_pu = (x0 + i) >> log2_min_pu_size;
425  const MvField *left = &tab_mvf[y_pu * min_pu_width + xp_pu];
426  const MvField *curr = &tab_mvf[y_pu * min_pu_width + xq_pu];
427  const int x = x0 + i;
428  const int y = y0 + j;
429  const int bs = boundary_strength(lc, curr, left, rpl);
430  uint8_t max_len_p = 0, max_len_q = 0;
431 
432  TAB_BS(fc->tab.vertical_bs[LUMA], x, y) = bs;
433 
434  if (i == 4 || i == width - 4)
435  max_len_p = max_len_q = 1;
436  else if (i == 8 || i == width - 8)
437  max_len_p = max_len_q = 2;
438  else
439  max_len_p = max_len_q = 3;
440 
441  TAB_MAX_LEN(fc->tab.vertical_p, x, y) = max_len_p;
442  TAB_MAX_LEN(fc->tab.vertical_q, x, y) = max_len_q;
443  }
444  }
445 }
446 
448  const int cb_x, const int cb_y, const int x0, const int y0, const int width, const int height)
449 {
450  const VVCFrameContext *fc = lc->fc;
451  const MvField* tab_mvf = fc->tab.mvf;
452  const RefPicList* rpl = lc->sc->rpl;
453  const int min_pu_width = fc->ps.pps->min_pu_width;
454  const int log2_min_pu_size = MIN_PU_LOG2;
455 
456  // bs for TU internal horizontal PU boundaries
457  for (int j = 8 - ((y0 - cb_y) % 8); j < height; j += 8) {
458  int yp_pu = (y0 + j - 1) >> log2_min_pu_size;
459  int yq_pu = (y0 + j) >> log2_min_pu_size;
460 
461  for (int i = 0; i < width; i += 4) {
462  const int x_pu = (x0 + i) >> log2_min_pu_size;
463  const MvField *top = &tab_mvf[yp_pu * min_pu_width + x_pu];
464  const MvField *curr = &tab_mvf[yq_pu * min_pu_width + x_pu];
465  const int x = x0 + i;
466  const int y = y0 + j;
467  const int bs = boundary_strength(lc, curr, top, rpl);
468  uint8_t max_len_p = 0, max_len_q = 0;
469 
470  TAB_BS(fc->tab.horizontal_bs[LUMA], x, y) = bs;
471 
472  //fixme:
473  //edgeTbFlags[ x − sbW ][ y ] is equal to 1
474  //edgeTbFlags[ x + sbW ][ y ] is equal to 1
475  if (j == 4 || j == height - 4)
476  max_len_p = max_len_q = 1;
477  else if (j == 8 || j == height - 8)
478  max_len_p = max_len_q = 2;
479  else
480  max_len_p = max_len_q = 3;
481  TAB_MAX_LEN(fc->tab.horizontal_p, x, y) = max_len_p;
482  TAB_MAX_LEN(fc->tab.horizontal_q, x, y) = max_len_q;
483  }
484  }
485 }
486 
488  const int x_p, const int y_p, const int x_q, const int y_q,
489  const RefPicList *rpl_p, const int c_idx, const int off_to_cb, const uint8_t has_sub_block)
490 {
491  const VVCFrameContext *fc = lc->fc;
492  const MvField *tab_mvf = fc->tab.mvf;
493  const int log2_min_pu_size = MIN_PU_LOG2;
494  const int log2_min_tu_size = MIN_TU_LOG2;
495  const int log2_min_cb_size = fc->ps.sps->min_cb_log2_size_y;
496  const int min_pu_width = fc->ps.pps->min_pu_width;
497  const int min_tu_width = fc->ps.pps->min_tu_width;
498  const int min_cb_width = fc->ps.pps->min_cb_width;
499  const int pu_p = (y_p >> log2_min_pu_size) * min_pu_width + (x_p >> log2_min_pu_size);
500  const int pu_q = (y_q >> log2_min_pu_size) * min_pu_width + (x_q >> log2_min_pu_size);
501  const MvField *mvf_p = &tab_mvf[pu_p];
502  const MvField *mvf_q = &tab_mvf[pu_q];
503  const uint8_t chroma = !!c_idx;
504  const int tu_p = (y_p >> log2_min_tu_size) * min_tu_width + (x_p >> log2_min_tu_size);
505  const int tu_q = (y_q >> log2_min_tu_size) * min_tu_width + (x_q >> log2_min_tu_size);
506  const uint8_t pcmf = fc->tab.pcmf[chroma][tu_p] && fc->tab.pcmf[chroma][tu_q];
507  const int cb_p = (y_p >> log2_min_cb_size) * min_cb_width + (x_p >> log2_min_cb_size);
508  const int cb_q = (y_q >> log2_min_cb_size) * min_cb_width + (x_q >> log2_min_cb_size);
509  const uint8_t intra = fc->tab.cpm[chroma][cb_p] == MODE_INTRA || fc->tab.cpm[chroma][cb_q] == MODE_INTRA;
510  const uint8_t same_mode = fc->tab.cpm[chroma][cb_p] == fc->tab.cpm[chroma][cb_q];
511 
512  if (pcmf)
513  return 0;
514 
515  if (intra || mvf_p->ciip_flag || mvf_q->ciip_flag)
516  return 2;
517 
518  if (chroma) {
519  return fc->tab.tu_coded_flag[c_idx][tu_p] ||
520  fc->tab.tu_coded_flag[c_idx][tu_q] ||
521  fc->tab.tu_joint_cbcr_residual_flag[tu_p] ||
522  fc->tab.tu_joint_cbcr_residual_flag[tu_q];
523  }
524 
525  if (fc->tab.tu_coded_flag[LUMA][tu_p] || fc->tab.tu_coded_flag[LUMA][tu_q])
526  return 1;
527 
528  if ((off_to_cb && ((off_to_cb % 8) || !has_sub_block)))
529  return 0; // inside a cu, not aligned to 8 or with no subblocks
530 
531  if (!same_mode)
532  return 1;
533 
534  return boundary_strength(lc, mvf_q, mvf_p, rpl_p);
535 }
536 
537 static int deblock_is_boundary(const VVCLocalContext *lc, const int boundary,
538  const int pos, const int rs, const int vertical)
539 {
540  const VVCFrameContext *fc = lc->fc;
541  const H266RawSPS *rsps = fc->ps.sps->r;
542  const H266RawPPS *rpps = fc->ps.pps->r;
543  int flag;
544  if (boundary && (pos % fc->ps.sps->ctb_size_y) == 0) {
546  if (lc->boundary_flags & flag &&
548  return 0;
549 
551  if (lc->boundary_flags & flag &&
553  return 0;
554 
556  if (lc->boundary_flags & flag) {
557  const int q_rs = rs - (vertical ? 1 : fc->ps.pps->ctb_width);
558  const SliceContext *q_slice = lc->fc->slices[lc->fc->tab.slice_idx[q_rs]];
559 
560  if (!rsps->sps_loop_filter_across_subpic_enabled_flag[q_slice->sh.r->curr_subpic_idx] ||
562  return 0;
563  }
564  }
565  return boundary;
566 }
567 
569  const int x0, const int y0, const int width, const int height, const int rs)
570 {
571  const VVCFrameContext *fc = lc->fc;
572  const MvField *tab_mvf = fc->tab.mvf;
573  const int log2_min_pu_size = MIN_PU_LOG2;
574  const int min_pu_width = fc->ps.pps->min_pu_width;
575  const int min_cb_log2 = fc->ps.sps->min_cb_log2_size_y;
576  const int min_cb_width = fc->ps.pps->min_cb_width;
577  const int is_intra = tab_mvf[(y0 >> log2_min_pu_size) * min_pu_width +
578  (x0 >> log2_min_pu_size)].pred_flag == PF_INTRA;
579  int boundary_left;
580  int has_vertical_sb = 0;
581 
582  const int off_q = (y0 >> min_cb_log2) * min_cb_width + (x0 >> min_cb_log2);
583  const int cb_x = fc->tab.cb_pos_x[LUMA][off_q];
584  const int cb_y = fc->tab.cb_pos_y[LUMA][off_q];
585  const int cb_width = fc->tab.cb_width[LUMA][off_q];
586  const int off_x = cb_x - x0;
587 
588  if (!is_intra) {
589  if (fc->tab.msf[off_q] || fc->tab.iaf[off_q])
590  has_vertical_sb = cb_width > 8;
591  }
592 
593  // bs for vertical TU boundaries
594  boundary_left = deblock_is_boundary(lc, x0 > 0 && !(x0 & 3), x0, rs, 1);
595 
596  if (boundary_left) {
597  const RefPicList *rpl_left =
598  (lc->boundary_flags & BOUNDARY_LEFT_SLICE) ? ff_vvc_get_ref_list(fc, fc->ref, x0 - 1, y0) : lc->sc->rpl;
599  for (int i = 0; i < height; i += 4) {
600  uint8_t max_len_p, max_len_q;
601  const int bs = deblock_bs(lc, x0 - 1, y0 + i, x0, y0 + i, rpl_left, 0, off_x, has_vertical_sb);
602 
603  TAB_BS(fc->tab.vertical_bs[LUMA], x0, (y0 + i)) = bs;
604 
605  derive_max_filter_length_luma(fc, x0, y0 + i, is_intra, has_vertical_sb, 1, &max_len_p, &max_len_q);
606  TAB_MAX_LEN(fc->tab.vertical_p, x0, y0 + i) = max_len_p;
607  TAB_MAX_LEN(fc->tab.vertical_q, x0, y0 + i) = max_len_q;
608  }
609  }
610 
611  if (!is_intra) {
612  if (fc->tab.msf[off_q] || fc->tab.iaf[off_q])
613  vvc_deblock_subblock_bs_vertical(lc, cb_x, cb_y, x0, y0, width, height);
614  }
615 }
616 
618  const int x0, const int y0, const int width, const int height, const int rs)
619 {
620  const VVCFrameContext *fc = lc->fc;
621  const MvField *tab_mvf = fc->tab.mvf;
622  const int log2_min_pu_size = MIN_PU_LOG2;
623  const int min_pu_width = fc->ps.pps->min_pu_width;
624  const int min_cb_log2 = fc->ps.sps->min_cb_log2_size_y;
625  const int min_cb_width = fc->ps.pps->min_cb_width;
626  const int is_intra = tab_mvf[(y0 >> log2_min_pu_size) * min_pu_width +
627  (x0 >> log2_min_pu_size)].pred_flag == PF_INTRA;
628  int boundary_upper;
629  int has_horizontal_sb = 0;
630 
631  const int off_q = (y0 >> min_cb_log2) * min_cb_width + (x0 >> min_cb_log2);
632  const int cb_x = fc->tab.cb_pos_x[LUMA][off_q];
633  const int cb_y = fc->tab.cb_pos_y[LUMA][off_q];
634  const int cb_height = fc->tab.cb_height[LUMA][off_q];
635  const int off_y = y0 - cb_y;
636 
637  if (!is_intra) {
638  if (fc->tab.msf[off_q] || fc->tab.iaf[off_q])
639  has_horizontal_sb = cb_height > 8;
640  }
641 
642  boundary_upper = deblock_is_boundary(lc, y0 > 0 && !(y0 & 3), y0, rs, 0);
643 
644  if (boundary_upper) {
645  const RefPicList *rpl_top =
646  (lc->boundary_flags & BOUNDARY_UPPER_SLICE) ? ff_vvc_get_ref_list(fc, fc->ref, x0, y0 - 1) : lc->sc->rpl;
647 
648  for (int i = 0; i < width; i += 4) {
649  uint8_t max_len_p, max_len_q;
650  const int bs = deblock_bs(lc, x0 + i, y0 - 1, x0 + i, y0, rpl_top, 0, off_y, has_horizontal_sb);
651 
652  TAB_BS(fc->tab.horizontal_bs[LUMA], x0 + i, y0) = bs;
653 
654  derive_max_filter_length_luma(fc, x0 + i, y0, is_intra, has_horizontal_sb, 0, &max_len_p, &max_len_q);
655  TAB_MAX_LEN(fc->tab.horizontal_p, x0 + i, y0) = max_len_p;
656  TAB_MAX_LEN(fc->tab.horizontal_q, x0 + i, y0) = max_len_q;
657  }
658  }
659 
660  if (!is_intra) {
661  if (fc->tab.msf[off_q] || fc->tab.iaf[off_q])
662  vvc_deblock_subblock_bs_horizontal(lc, cb_x, cb_y, x0, y0, width, height);
663  }
664 }
665 
667  const int x0, const int y0, const int width, const int height, const int rs)
668 {
669  const VVCFrameContext *fc = lc->fc;
670  const int boundary_left = deblock_is_boundary(lc,
671  x0 > 0 && !(x0 & ((CHROMA_GRID << fc->ps.sps->hshift[CHROMA]) - 1)), x0, rs, 1);
672 
673  if (boundary_left) {
674  for (int i = 0; i < height; i += 2) {
675  for (int c_idx = CB; c_idx <= CR; c_idx++) {
676  const int bs = deblock_bs(lc, x0 - 1, y0 + i, x0, y0 + i, NULL, c_idx, 0, 0);
677 
678  TAB_BS(fc->tab.vertical_bs[c_idx], x0, (y0 + i)) = bs;
679  }
680  }
681  }
682 }
683 
685  const int x0, const int y0, const int width, const int height, const int rs)
686 {
687  const VVCFrameContext *fc = lc->fc;
688  const int boundary_upper = deblock_is_boundary(lc,
689  y0 > 0 && !(y0 & ((CHROMA_GRID << fc->ps.sps->vshift[CHROMA]) - 1)), y0, rs, 0);
690 
691  if (boundary_upper) {
692  for (int i = 0; i < width; i += 2) {
693  for (int c_idx = CB; c_idx <= CR; c_idx++) {
694  const int bs = deblock_bs(lc, x0 + i, y0 - 1, x0 + i, y0, NULL, c_idx, 0, 0);
695 
696  TAB_BS(fc->tab.horizontal_bs[c_idx], x0 + i, y0) = bs;
697  }
698  }
699  }
700 }
701 
702 typedef void (*deblock_bs_fn)(const VVCLocalContext *lc, const int x0, const int y0,
703  const int width, const int height, const int rs);
704 
705 static void vvc_deblock_bs(const VVCLocalContext *lc, const int x0, const int y0, const int rs, const int vertical)
706 {
707  const VVCFrameContext *fc = lc->fc;
708  const VVCSPS *sps = fc->ps.sps;
709  const VVCPPS *pps = fc->ps.pps;
710  const int ctb_size = sps->ctb_size_y;
711  const int x_end = FFMIN(x0 + ctb_size, pps->width) >> MIN_TU_LOG2;
712  const int y_end = FFMIN(y0 + ctb_size, pps->height) >> MIN_TU_LOG2;
713  deblock_bs_fn deblock_bs[2][2] = {
716  };
717 
718  for (int is_chroma = 0; is_chroma <= 1; is_chroma++) {
719  const int hs = sps->hshift[is_chroma];
720  const int vs = sps->vshift[is_chroma];
721  for (int y = y0 >> MIN_TU_LOG2; y < y_end; y++) {
722  for (int x = x0 >> MIN_TU_LOG2; x < x_end; x++) {
723  const int off = y * fc->ps.pps->min_tu_width + x;
724  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) {
725  deblock_bs[vertical][is_chroma](lc, x << MIN_TU_LOG2, y << MIN_TU_LOG2,
726  fc->tab.tb_width[is_chroma][off] << hs, fc->tab.tb_height[is_chroma][off] << vs, rs);
727  }
728  }
729  }
730  }
731 }
732 
733 //part of 8.8.3.3 Derivation process of transform block boundary
734 static void max_filter_length_luma(const VVCFrameContext *fc, const int qx, const int qy,
735  const int vertical, uint8_t *max_len_p, uint8_t *max_len_q)
736 {
737  const uint8_t *tab_len_p = vertical ? fc->tab.vertical_p : fc->tab.horizontal_p;
738  const uint8_t *tab_len_q = vertical ? fc->tab.vertical_q : fc->tab.horizontal_q;
739  *max_len_p = TAB_MAX_LEN(tab_len_p, qx, qy);
740  *max_len_q = TAB_MAX_LEN(tab_len_q, qx, qy);
741 }
742 
743 //part of 8.8.3.3 Derivation process of transform block boundary
744 static void max_filter_length_chroma(const VVCFrameContext *fc, const int qx, const int qy,
745  const int vertical, const int horizontal_ctu_edge, const int bs, uint8_t *max_len_p, uint8_t *max_len_q)
746 {
747  const int px = vertical ? qx - 1 : qx;
748  const int py = !vertical ? qy - 1 : qy;
749  const uint8_t *tb_size = vertical ? fc->tab.tb_width[CHROMA] : fc->tab.tb_height[CHROMA];
750 
751  const int size_p = tb_size[(py >> MIN_TU_LOG2) * fc->ps.pps->min_tu_width + (px >> MIN_TU_LOG2)];
752  const int size_q = tb_size[(qy >> MIN_TU_LOG2) * fc->ps.pps->min_tu_width + (qx >> MIN_TU_LOG2)];
753  if (size_p >= 8 && size_q >= 8) {
754  *max_len_p = *max_len_q = 3;
755  if (horizontal_ctu_edge)
756  *max_len_p = 1;
757  } else {
758  //part of 8.8.3.6.4 Decision process for chroma block edges
759  *max_len_p = *max_len_q = (bs == 2);
760  }
761 }
762 
763 static void max_filter_length(const VVCFrameContext *fc, const int qx, const int qy,
764  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)
765 {
766  if (!c_idx)
767  max_filter_length_luma(fc, qx, qy, vertical, max_len_p, max_len_q);
768  else
769  max_filter_length_chroma(fc, qx, qy, vertical, horizontal_ctu_edge, bs, max_len_p, max_len_q);
770 }
771 
772 #define TC_CALC(qp, bs) \
773  tctable[av_clip((qp) + DEFAULT_INTRA_TC_OFFSET * ((bs) - 1) + \
774  (tc_offset & -2), \
775  0, MAX_QP + DEFAULT_INTRA_TC_OFFSET)]
776 
777 // part of 8.8.3.6.2 Decision process for luma block edges
778 static int get_qp_y(const VVCFrameContext *fc, const uint8_t *src, const int x, const int y, const int vertical)
779 {
780  const VVCSPS *sps = fc->ps.sps;
781  const int qp = (ff_vvc_get_qPy(fc, x - vertical, y - !vertical) + ff_vvc_get_qPy(fc, x, y) + 1) >> 1;
782  int qp_offset = 0;
783  int level;
784 
785  if (!sps->r->sps_ladf_enabled_flag)
786  return qp;
787 
788  level = fc->vvcdsp.lf.ladf_level[vertical](src, fc->frame->linesize[LUMA]);
789  qp_offset = sps->r->sps_ladf_lowest_interval_qp_offset;
790  for (int i = 0; i < sps->num_ladf_intervals - 1 && level > sps->ladf_interval_lower_bound[i + 1]; i++)
791  qp_offset = sps->r->sps_ladf_qp_offset[i];
792 
793  return qp + qp_offset;
794 }
795 
796 // part of 8.8.3.6.2 Decision process for luma block edges
797 static int get_qp_c(const VVCFrameContext *fc, const int x, const int y, const int c_idx, const int vertical)
798 {
799  const VVCSPS *sps = fc->ps.sps;
800  return (get_qPc(fc, x - vertical, y - !vertical, c_idx) + get_qPc(fc, x, y, c_idx) - 2 * sps->qp_bd_offset + 1) >> 1;
801 }
802 
803 static int get_qp(const VVCFrameContext *fc, const uint8_t *src, const int x, const int y, const int c_idx, const int vertical)
804 {
805  if (!c_idx)
806  return get_qp_y(fc, src, x, y, vertical);
807  return get_qp_c(fc, x, y, c_idx, vertical);
808 }
809 
810 void ff_vvc_deblock_vertical(const VVCLocalContext *lc, const int x0, const int y0, const int rs)
811 {
812  VVCFrameContext *fc = lc->fc;
813  const VVCSPS *sps = fc->ps.sps;
814  const int c_end = sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1;
815  uint8_t *src;
816  int x, y, qp;
817 
818  //not use this yet, may needed by plt.
819  const uint8_t no_p[4] = { 0 };
820  const uint8_t no_q[4] = { 0 } ;
821 
822  const int ctb_log2_size_y = fc->ps.sps->ctb_log2_size_y;
823  int x_end, y_end;
824  const int ctb_size = 1 << ctb_log2_size_y;
825  const DBParams *params = fc->tab.deblock + rs;
826 
827  vvc_deblock_bs(lc, x0, y0, rs, 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, const int x0, const int y0, const int rs)
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 DBParams *params = fc->tab.deblock + rs;
894 
895  vvc_deblock_bs(lc, x0, y0, rs, 0);
896 
897  x_end = x0 + ctb_size;
898  if (x_end > fc->ps.pps->width)
899  x_end = fc->ps.pps->width;
900  y_end = y0 + ctb_size;
901  if (y_end > fc->ps.pps->height)
902  y_end = fc->ps.pps->height;
903 
904  for (int c_idx = 0; c_idx < c_end; c_idx++) {
905  const int hs = sps->hshift[c_idx];
906  const int vs = sps->vshift[c_idx];
907  const int grid = c_idx ? (CHROMA_GRID << vs) : LUMA_GRID;
908  const int beta_offset = params->beta_offset[c_idx];
909  const int tc_offset = params->tc_offset[c_idx];
910 
911  for (y = y0; y < y_end; y += grid) {
912  const uint8_t horizontal_ctu_edge = !(y % fc->ps.sps->ctb_size_y);
913  if (!y)
914  continue;
915 
916  for (x = x0 ? x0: 0; x < x_end; x += (DEBLOCK_STEP << hs)) {
917  int32_t bs[4], beta[4], tc[4], all_zero_bs = 1;
918  uint8_t max_len_p[4], max_len_q[4];
919 
920  for (int i = 0; i < DEBLOCK_STEP >> (2 - hs); i++) {
921  const int dx = i << 2;
922 
923  bs[i] = (x + dx < x_end) ? TAB_BS(fc->tab.horizontal_bs[c_idx], x + dx, y) : 0;
924  if (bs[i]) {
925  src = &fc->frame->data[c_idx][(y >> vs) * fc->frame->linesize[c_idx] + (((x + dx)>> hs) << fc->ps.sps->pixel_shift)];
926  qp = get_qp(fc, src, x + dx, y, c_idx, 0);
927 
928  beta[i] = betatable[av_clip(qp + beta_offset, 0, MAX_QP)];
929 
930  max_filter_length(fc, x + dx, y, c_idx, 0, horizontal_ctu_edge, bs[i], &max_len_p[i], &max_len_q[i]);
931  all_zero_bs = 0;
932  }
933  tc[i] = bs[i] ? TC_CALC(qp, bs[i]) : 0;
934  }
935  if (!all_zero_bs) {
936  src = &fc->frame->data[c_idx][(y >> vs) * fc->frame->linesize[c_idx] + ((x >> hs) << fc->ps.sps->pixel_shift)];
937  if (!c_idx) {
938  fc->vvcdsp.lf.filter_luma[0](src, fc->frame->linesize[c_idx],
939  beta, tc, no_p, no_q, max_len_p, max_len_q, horizontal_ctu_edge);
940  } else {
941  fc->vvcdsp.lf.filter_chroma[0](src, fc->frame->linesize[c_idx],
942  beta, tc, no_p, no_q, max_len_p, max_len_q, hs);
943  }
944  }
945  }
946  }
947  }
948 }
949 
950 static void alf_copy_border(uint8_t *dst, const uint8_t *src,
951  const int pixel_shift, int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride)
952 {
953  width <<= pixel_shift;
954  for (int i = 0; i < height; i++) {
955  memcpy(dst, src, width);
956  dst += dst_stride;
957  src += src_stride;
958  }
959 }
960 
961 static void alf_extend_vert(uint8_t *_dst, const uint8_t *_src,
962  const int pixel_shift, const int width, const int height, ptrdiff_t stride)
963 {
964  if (pixel_shift == 0) {
965  for (int i = 0; i < height; i++) {
966  memset(_dst, *_src, width);
967  _src += stride;
968  _dst += stride;
969  }
970  } else {
971  const uint16_t *src = (const uint16_t *)_src;
972  uint16_t *dst = (uint16_t *)_dst;
973  stride >>= pixel_shift;
974 
975  for (int i = 0; i < height; i++) {
976  for (int j = 0; j < width; j++)
977  dst[j] = *src;
978  src += stride;
979  dst += stride;
980  }
981  }
982 }
983 
984 static void alf_extend_horz(uint8_t *dst, const uint8_t *src,
985  const int pixel_shift, int width, const int height, const ptrdiff_t stride)
986 {
987  width <<= pixel_shift;
988  for (int i = 0; i < height; i++) {
989  memcpy(dst, src, width);
990  dst += stride;
991  }
992 }
993 
994 static void alf_copy_ctb_to_hv(VVCFrameContext *fc, const uint8_t *src, const ptrdiff_t src_stride,
995  const int x, const int y, const int width, const int height, const int rx, const int ry, const int c_idx)
996 {
997  const int ps = fc->ps.sps->pixel_shift;
998  const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
999  const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
1000  const int border_pixels = (c_idx == 0) ? ALF_BORDER_LUMA : ALF_BORDER_CHROMA;
1001  const int offset_h[] = { 0, height - border_pixels };
1002  const int offset_v[] = { 0, width - border_pixels };
1003 
1004  /* copy horizontal edges */
1005  for (int i = 0; i < FF_ARRAY_ELEMS(offset_h); i++) {
1006  alf_copy_border(fc->tab.alf_pixel_buffer_h[c_idx][i] + ((border_pixels * ry * w + x)<< ps),
1007  src + offset_h[i] * src_stride, ps, width, border_pixels, w << ps, src_stride);
1008  }
1009  /* copy vertical edges */
1010  for (int i = 0; i < FF_ARRAY_ELEMS(offset_v); i++) {
1011  alf_copy_border(fc->tab.alf_pixel_buffer_v[c_idx][i] + ((h * rx + y) * (border_pixels << ps)),
1012  src + (offset_v[i] << ps), ps, border_pixels, height, border_pixels << ps, src_stride);
1013  }
1014 }
1015 
1016 static void alf_fill_border_h(uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src, const ptrdiff_t src_stride,
1017  const uint8_t *border, const int width, const int border_pixels, const int ps, const int edge)
1018 {
1019  if (edge)
1020  alf_extend_horz(dst, border, ps, width, border_pixels, dst_stride);
1021  else
1022  alf_copy_border(dst, src, ps, width, border_pixels, dst_stride, src_stride);
1023 }
1024 
1025 static void alf_fill_border_v(uint8_t *dst, const ptrdiff_t dst_stride, const uint8_t *src,
1026  const uint8_t *border, const int border_pixels, const int height, const int pixel_shift, const int *edges, const int edge)
1027 {
1028  const ptrdiff_t src_stride = (border_pixels << pixel_shift);
1029 
1030  if (edge) {
1031  alf_extend_vert(dst, border, pixel_shift, border_pixels, height + 2 * border_pixels, dst_stride);
1032  return;
1033  }
1034 
1035  //left/right
1036  alf_copy_border(dst + dst_stride * border_pixels * edges[TOP], src + src_stride * border_pixels * edges[TOP],
1037  pixel_shift, border_pixels, height + (!edges[TOP] + !edges[BOTTOM]) * border_pixels, dst_stride, src_stride);
1038 
1039  //top left/right
1040  if (edges[TOP])
1041  alf_extend_horz(dst, dst + dst_stride * border_pixels, pixel_shift, border_pixels, border_pixels, dst_stride);
1042 
1043  //bottom left/right
1044  if (edges[BOTTOM]) {
1045  dst += dst_stride * (border_pixels + height);
1046  alf_extend_horz(dst, dst - dst_stride, pixel_shift, border_pixels, border_pixels, dst_stride);
1047  }
1048 }
1049 
1050 static void alf_prepare_buffer(VVCFrameContext *fc, uint8_t *_dst, const uint8_t *_src, const int x, const int y,
1051  const int rx, const int ry, const int width, const int height, const ptrdiff_t dst_stride, const ptrdiff_t src_stride,
1052  const int c_idx, const int *edges)
1053 {
1054  const int ps = fc->ps.sps->pixel_shift;
1055  const int w = fc->ps.pps->width >> fc->ps.sps->hshift[c_idx];
1056  const int h = fc->ps.pps->height >> fc->ps.sps->vshift[c_idx];
1057  const int border_pixels = c_idx == 0 ? ALF_BORDER_LUMA : ALF_BORDER_CHROMA;
1058  uint8_t *dst, *src;
1059 
1060  copy_ctb(_dst, _src, width << ps, height, dst_stride, src_stride);
1061 
1062  //top
1063  src = fc->tab.alf_pixel_buffer_h[c_idx][1] + (((border_pixels * w) << ps) * (ry - 1) + (x << ps));
1064  dst = _dst - border_pixels * dst_stride;
1065  alf_fill_border_h(dst, dst_stride, src, w << ps, _dst, width, border_pixels, ps, edges[TOP]);
1066 
1067  //bottom
1068  src = fc->tab.alf_pixel_buffer_h[c_idx][0] + (((border_pixels * w) << ps) * (ry + 1) + (x << ps));
1069  dst = _dst + height * dst_stride;
1070  alf_fill_border_h(dst, dst_stride, src, w << ps, _dst + (height - 1) * dst_stride, width, border_pixels, ps, edges[BOTTOM]);
1071 
1072 
1073  //left
1074  src = fc->tab.alf_pixel_buffer_v[c_idx][1] + (h * (rx - 1) + y - border_pixels) * (border_pixels << ps);
1075  dst = _dst - (border_pixels << ps) - border_pixels * dst_stride;
1076  alf_fill_border_v(dst, dst_stride, src, dst + (border_pixels << ps), border_pixels, height, ps, edges, edges[LEFT]);
1077 
1078  //right
1079  src = fc->tab.alf_pixel_buffer_v[c_idx][0] + (h * (rx + 1) + y - border_pixels) * (border_pixels << ps);
1080  dst = _dst + (width << ps) - border_pixels * dst_stride;
1081  alf_fill_border_v(dst, dst_stride, src, dst - (1 << ps), border_pixels, height, ps, edges, edges[RIGHT]);
1082 }
1083 
1084 #define ALF_MAX_BLOCKS_IN_CTU (MAX_CTU_SIZE * MAX_CTU_SIZE / ALF_BLOCK_SIZE / ALF_BLOCK_SIZE)
1085 #define ALF_MAX_FILTER_SIZE (ALF_MAX_BLOCKS_IN_CTU * ALF_NUM_COEFF_LUMA)
1086 
1087 static void alf_get_coeff_and_clip(VVCLocalContext *lc, int16_t *coeff, int16_t *clip,
1088  const uint8_t *src, ptrdiff_t src_stride, int width, int height, int vb_pos, ALFParams *alf)
1089 {
1090  const VVCFrameContext *fc = lc->fc;
1091  const H266RawSliceHeader *rsh = lc->sc->sh.r;
1092  uint8_t fixed_clip_set[ALF_NUM_FILTERS_LUMA][ALF_NUM_COEFF_LUMA] = { 0 };
1093  const int16_t *coeff_set;
1094  const uint8_t *clip_idx_set;
1095  const uint8_t *class_to_filt;
1096  const int size = width * height / ALF_BLOCK_SIZE / ALF_BLOCK_SIZE;
1097  int class_idx[ALF_MAX_BLOCKS_IN_CTU];
1098  int transpose_idx[ALF_MAX_BLOCKS_IN_CTU];
1099 
1100  if (alf->ctb_filt_set_idx_y < 16) {
1101  coeff_set = &ff_vvc_alf_fix_filt_coeff[0][0];
1102  clip_idx_set = &fixed_clip_set[0][0];
1103  class_to_filt = ff_vvc_alf_class_to_filt_map[alf->ctb_filt_set_idx_y];
1104  } else {
1105  const int id = rsh->sh_alf_aps_id_luma[alf->ctb_filt_set_idx_y - 16];
1106  const VVCALF *aps = fc->ps.alf_list[id];
1107  coeff_set = &aps->luma_coeff[0][0];
1108  clip_idx_set = &aps->luma_clip_idx[0][0];
1109  class_to_filt = ff_vvc_alf_aps_class_to_filt_map;
1110  }
1111  fc->vvcdsp.alf.classify(class_idx, transpose_idx, src, src_stride, width, height,
1112  vb_pos, lc->alf_gradient_tmp);
1113  fc->vvcdsp.alf.recon_coeff_and_clip(coeff, clip, class_idx, transpose_idx, size,
1114  coeff_set, clip_idx_set, class_to_filt);
1115 }
1116 
1117 static void alf_filter_luma(VVCLocalContext *lc, uint8_t *dst, const uint8_t *src,
1118  const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int x0, const int y0,
1119  const int width, const int height, const int _vb_pos, ALFParams *alf)
1120 {
1121  const VVCFrameContext *fc = lc->fc;
1122  int vb_pos = _vb_pos - y0;
1123  int16_t *coeff = (int16_t*)lc->tmp;
1124  int16_t *clip = (int16_t *)lc->tmp1;
1125 
1126  av_assert0(ALF_MAX_FILTER_SIZE <= sizeof(lc->tmp));
1127  av_assert0(ALF_MAX_FILTER_SIZE * sizeof(int16_t) <= sizeof(lc->tmp1));
1128 
1129  alf_get_coeff_and_clip(lc, coeff, clip, src, src_stride, width, height, vb_pos, alf);
1130  fc->vvcdsp.alf.filter[LUMA](dst, dst_stride, src, src_stride, width, height, coeff, clip, vb_pos);
1131 }
1132 
1133 static int alf_clip_from_idx(const VVCFrameContext *fc, const int idx)
1134 {
1135  const VVCSPS *sps = fc->ps.sps;
1136  const int offset[] = {0, 3, 5, 7};
1137 
1138  return 1 << (sps->bit_depth - offset[idx]);
1139 }
1140 
1141 static void alf_filter_chroma(VVCLocalContext *lc, uint8_t *dst, const uint8_t *src,
1142  const ptrdiff_t dst_stride, const ptrdiff_t src_stride, const int c_idx,
1143  const int width, const int height, const int vb_pos, ALFParams *alf)
1144 {
1145  VVCFrameContext *fc = lc->fc;
1146  const H266RawSliceHeader *rsh = lc->sc->sh.r;
1147  const VVCALF *aps = fc->ps.alf_list[rsh->sh_alf_aps_id_chroma];
1148  const int idx = alf->alf_ctb_filter_alt_idx[c_idx - 1];
1149  const int16_t *coeff = aps->chroma_coeff[idx];
1150  int16_t clip[ALF_NUM_COEFF_CHROMA];
1151 
1152  for (int i = 0; i < ALF_NUM_COEFF_CHROMA; i++)
1153  clip[i] = alf_clip_from_idx(fc, aps->chroma_clip_idx[idx][i]);
1154 
1155  fc->vvcdsp.alf.filter[CHROMA](dst, dst_stride, src, src_stride, width, height, coeff, clip, vb_pos);
1156 }
1157 
1158 static void alf_filter_cc(VVCLocalContext *lc, uint8_t *dst, const uint8_t *luma,
1159  const ptrdiff_t dst_stride, const ptrdiff_t luma_stride, const int c_idx,
1160  const int width, const int height, const int hs, const int vs, const int vb_pos, ALFParams *alf)
1161 {
1162  const VVCFrameContext *fc = lc->fc;
1163  const H266RawSliceHeader *rsh = lc->sc->sh.r;
1164  const int idx = c_idx - 1;
1165  const int cc_aps_id = c_idx == CB ? rsh->sh_alf_cc_cb_aps_id : rsh->sh_alf_cc_cr_aps_id;
1166  const VVCALF *aps = fc->ps.alf_list[cc_aps_id];
1167 
1168  if (aps) {
1169  const int16_t *coeff = aps->cc_coeff[idx][alf->ctb_cc_idc[idx] - 1];
1170 
1171  fc->vvcdsp.alf.filter_cc(dst, dst_stride, luma, luma_stride, width, height, hs, vs, coeff, vb_pos);
1172  }
1173 }
1174 
1175 void ff_vvc_alf_copy_ctu_to_hv(VVCLocalContext* lc, const int x0, const int y0)
1176 {
1177  VVCFrameContext *fc = lc->fc;
1178  const int rx = x0 >> fc->ps.sps->ctb_log2_size_y;
1179  const int ry = y0 >> fc->ps.sps->ctb_log2_size_y;
1180  const int ctb_size_y = fc->ps.sps->ctb_size_y;
1181  const int ps = fc->ps.sps->pixel_shift;
1182  const int c_end = fc->ps.sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1;
1183 
1184  for (int c_idx = 0; c_idx < c_end; c_idx++) {
1185  const int hs = fc->ps.sps->hshift[c_idx];
1186  const int vs = fc->ps.sps->vshift[c_idx];
1187  const int x = x0 >> hs;
1188  const int y = y0 >> vs;
1189  const int width = FFMIN(fc->ps.pps->width - x0, ctb_size_y) >> hs;
1190  const int height = FFMIN(fc->ps.pps->height - y0, ctb_size_y) >> vs;
1191 
1192  const int src_stride = fc->frame->linesize[c_idx];
1193  uint8_t* src = &fc->frame->data[c_idx][y * src_stride + (x << ps)];
1194 
1195  alf_copy_ctb_to_hv(fc, src, src_stride, x, y, width, height, rx, ry, c_idx);
1196  }
1197 }
1198 
1199 void ff_vvc_alf_filter(VVCLocalContext *lc, const int x0, const int y0)
1200 {
1201  VVCFrameContext *fc = lc->fc;
1202  const VVCSPS *sps = fc->ps.sps;
1203  const VVCPPS *pps = fc->ps.pps;
1204  const int rx = x0 >> fc->ps.sps->ctb_log2_size_y;
1205  const int ry = y0 >> fc->ps.sps->ctb_log2_size_y;
1206  const int ctb_size_y = fc->ps.sps->ctb_size_y;
1207  const int ps = fc->ps.sps->pixel_shift;
1208  const int padded_stride = EDGE_EMU_BUFFER_STRIDE << ps;
1209  const int padded_offset = padded_stride * ALF_PADDING_SIZE + (ALF_PADDING_SIZE << ps);
1210  const int c_end = fc->ps.sps->r->sps_chroma_format_idc ? VVC_MAX_SAMPLE_ARRAYS : 1;
1211  const int subpic_idx = lc->sc->sh.r->curr_subpic_idx;
1212  ALFParams *alf = &CTB(fc->tab.alf, rx, ry);
1213  int edges[MAX_EDGES] = { rx == 0, ry == 0, rx == pps->ctb_width - 1, ry == 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[rx] != pps->ctb_to_col_bd[rx + 1];
1219  edges[BOTTOM] = edges[BOTTOM] || pps->ctb_to_row_bd[ry] != pps->ctb_to_row_bd[ry + 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, rx, ry) != CTB(fc->tab.slice_idx, rx + 1, ry);
1226  edges[BOTTOM] = edges[BOTTOM] || CTB(fc->tab.slice_idx, rx, ry) != CTB(fc->tab.slice_idx, rx, ry + 1);
1227  }
1228 
1229  if (!sps->r->sps_loop_filter_across_subpic_enabled_flag[subpic_idx]) {
1230  edges[LEFT] = edges[LEFT] || (lc->boundary_flags & BOUNDARY_LEFT_SUBPIC);
1231  edges[TOP] = edges[TOP] || (lc->boundary_flags & BOUNDARY_UPPER_SUBPIC);
1232  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;
1233  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;
1234  }
1235 
1236  for (int c_idx = 0; c_idx < c_end; c_idx++) {
1237  const int hs = fc->ps.sps->hshift[c_idx];
1238  const int vs = fc->ps.sps->vshift[c_idx];
1239  const int ctb_size_h = ctb_size_y >> hs;
1240  const int ctb_size_v = ctb_size_y >> vs;
1241  const int x = x0 >> hs;
1242  const int y = y0 >> vs;
1243  const int pic_width = fc->ps.pps->width >> hs;
1244  const int pic_height = fc->ps.pps->height >> vs;
1245  const int width = FFMIN(pic_width - x, ctb_size_h);
1246  const int height = FFMIN(pic_height - y, ctb_size_v);
1247  const int src_stride = fc->frame->linesize[c_idx];
1248  uint8_t *src = &fc->frame->data[c_idx][y * src_stride + (x << ps)];
1249  uint8_t *padded;
1250 
1251  if (alf->ctb_flag[c_idx] || (!c_idx && (alf->ctb_cc_idc[0] || alf->ctb_cc_idc[1]))) {
1252  padded = (c_idx ? lc->alf_buffer_chroma : lc->alf_buffer_luma) + padded_offset;
1253  alf_prepare_buffer(fc, padded, src, x, y, rx, ry, width, height,
1254  padded_stride, src_stride, c_idx, edges);
1255  }
1256  if (alf->ctb_flag[c_idx]) {
1257  if (!c_idx) {
1258  alf_filter_luma(lc, src, padded, src_stride, padded_stride, x, y,
1259  width, height, y + ctb_size_v - ALF_VB_POS_ABOVE_LUMA, alf);
1260  } else {
1261  alf_filter_chroma(lc, src, padded, src_stride, padded_stride, c_idx,
1262  width, height, ctb_size_v - ALF_VB_POS_ABOVE_CHROMA, alf);
1263  }
1264  }
1265  if (c_idx && alf->ctb_cc_idc[c_idx - 1]) {
1266  padded = lc->alf_buffer_luma + padded_offset;
1267  alf_filter_cc(lc, src, padded, src_stride, padded_stride, c_idx,
1268  width, height, hs, vs, (ctb_size_v << vs) - ALF_VB_POS_ABOVE_LUMA, alf);
1269  }
1270 
1271  alf->applied[c_idx] = 1;
1272  }
1273 }
1274 
1275 
1276 void ff_vvc_lmcs_filter(const VVCLocalContext *lc, const int x, const int y)
1277 {
1278  const SliceContext *sc = lc->sc;
1279  const VVCFrameContext *fc = lc->fc;
1280  const int ctb_size = fc->ps.sps->ctb_size_y;
1281  const int width = FFMIN(fc->ps.pps->width - x, ctb_size);
1282  const int height = FFMIN(fc->ps.pps->height - y, ctb_size);
1283  uint8_t *data = fc->frame->data[LUMA] + y * fc->frame->linesize[LUMA] + (x << fc->ps.sps->pixel_shift);
1284  if (sc->sh.r->sh_lmcs_used_flag)
1285  fc->vvcdsp.lmcs.filter(data, fc->frame->linesize[LUMA], width, height, &fc->ps.lmcs.inv_lut);
1286 }
ALFParams::applied
uint8_t applied[3]
Definition: ctu.h:465
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: filter.c:1087
CB
#define CB
Definition: hevc_filter.c:32
A
#define A(x)
Definition: vpx_arith.h:28
VVCSPS
Definition: ps.h:58
ALF_MAX_BLOCKS_IN_CTU
#define ALF_MAX_BLOCKS_IN_CTU
Definition: filter.c:1084
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:961
DBParams
Definition: hevcdec.h:341
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
ALF_BORDER_LUMA
#define ALF_BORDER_LUMA
Definition: ctu.h:76
BOTTOM
#define BOTTOM
Definition: filter.c:32
level
uint8_t level
Definition: svq3.c:205
VVCPPS
Definition: ps.h:92
av_clip
#define av_clip
Definition: common.h:99
H266RawPPS::pps_loop_filter_across_tiles_enabled_flag
uint8_t pps_loop_filter_across_tiles_enabled_flag
Definition: cbs_h266.h:531
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:810
RIGHT
#define RIGHT
Definition: filter.c:31
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:100
filter.h
VVC_MAX_SAMPLE_ARRAYS
@ VVC_MAX_SAMPLE_ARRAYS
Definition: vvc.h:77
TAB_MAX_LEN
#define TAB_MAX_LEN(t, x, y)
Definition: filter.c:307
SAO_BAND
@ SAO_BAND
Definition: hevcdec.h:159
ALF_VB_POS_ABOVE_LUMA
#define ALF_VB_POS_ABOVE_LUMA
Definition: ctu.h:79
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:1025
TC_CALC
#define TC_CALC(qp, bs)
Definition: filter.c:772
PF_IBC
@ PF_IBC
Definition: ctu.h:223
src1
const pixel * src1
Definition: h264pred_template.c:421
MAX_EDGES
#define MAX_EDGES
Definition: filter.c:33
VVCLocalContext::alf_buffer_chroma
uint8_t alf_buffer_chroma[(MAX_CTU_SIZE+2 *ALF_PADDING_SIZE) *EDGE_EMU_BUFFER_STRIDE *2]
Definition: ctu.h:387
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
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: filter.c:487
VVCLocalContext::tmp
int16_t tmp[MAX_PB_SIZE *MAX_PB_SIZE]
Definition: ctu.h:381
w
uint8_t w
Definition: llviddspenc.c:38
VVCLocalContext::sc
SliceContext * sc
Definition: ctu.h:432
LUMA_GRID
#define LUMA_GRID
Definition: filter.c:311
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: ps.h:232
ALF_MAX_FILTER_SIZE
#define ALF_MAX_FILTER_SIZE
Definition: filter.c:1085
fc
#define fc(width, name, range_min, range_max)
Definition: cbs_av1.c:464
RefPicList
Definition: hevcdec.h:189
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:537
PF_INTRA
@ PF_INTRA
Definition: hevcdec.h:113
DEBLOCK_STEP
#define DEBLOCK_STEP
Definition: filter.c:310
VVCFrameContext::slices
SliceContext ** slices
Definition: dec.h:126
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:143
tctable
static const uint16_t tctable[66]
Definition: filter.c:38
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, const int rs)
Definition: filter.c:684
BOUNDARY_LEFT_TILE
#define BOUNDARY_LEFT_TILE
Definition: hevcdec.h:436
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:803
MIN_PU_LOG2
#define MIN_PU_LOG2
Definition: dec.h:40
H266RawSliceHeader::sh_alf_cc_cr_aps_id
uint8_t sh_alf_cc_cr_aps_id
Definition: cbs_h266.h:790
TOP
#define TOP
Definition: filter.c:30
VVCLocalContext::sao_buffer
uint8_t sao_buffer[(MAX_CTU_SIZE+2 *SAO_PADDING_SIZE) *EDGE_EMU_BUFFER_STRIDE *2]
Definition: ctu.h:385
VVCLocalContext::fc
VVCFrameContext * fc
Definition: ctu.h:433
VVCLocalContext::tmp1
int16_t tmp1[MAX_PB_SIZE *MAX_PB_SIZE]
Definition: ctu.h:382
tab
static const struct twinvq_data tab
Definition: twinvq_data.h:10345
vvc_deblock_bs
static void vvc_deblock_bs(const VVCLocalContext *lc, const int x0, const int y0, const int rs, const int vertical)
Definition: filter.c:705
SliceContext::rpl
RefPicList * rpl
Definition: dec.h:111
VVCALF
Definition: ps.h:165
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:123
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:312
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
LEFT
#define LEFT
Definition: filter.c:29
RefPicList::refs
VVCRefPic refs[VVC_MAX_REF_ENTRIES]
Definition: dec.h:56
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
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, const int rs)
Definition: filter.c:666
boundary_strength
static int boundary_strength(const VVCLocalContext *lc, const MvField *curr, const MvField *neigh, const RefPicList *neigh_rpl)
Definition: filter.c:314
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
B
#define B
Definition: huffyuv.h:42
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:62
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:878
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:81
ff_vvc_alf_class_to_filt_map
const uint8_t ff_vvc_alf_class_to_filt_map[16][25]
Definition: data.c:1712
VVCFrameContext::slice_idx
int16_t * slice_idx
Definition: dec.h:146
VVCLocalContext::alf_gradient_tmp
int32_t alf_gradient_tmp[ALF_GRADIENT_SIZE *ALF_GRADIENT_SIZE *ALF_NUM_DIR]
Definition: 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:73
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:2463
VVCLocalContext::alf_buffer_luma
uint8_t alf_buffer_luma[(MAX_CTU_SIZE+2 *ALF_PADDING_SIZE) *EDGE_EMU_BUFFER_STRIDE *2]
Definition: ctu.h:386
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:1199
NULL
#define NULL
Definition: coverity.c:32
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:778
VVCLocalContext
Definition: ctu.h:371
H266RawSliceHeader::curr_subpic_idx
uint16_t curr_subpic_idx
CurrSubpicIdx.
Definition: cbs_h266.h:835
L0
#define L0
Definition: hevcdec.h:57
ALF_NUM_COEFF_LUMA
#define ALF_NUM_COEFF_LUMA
Definition: ps.h:161
BOUNDARY_UPPER_TILE
#define BOUNDARY_UPPER_TILE
Definition: hevcdec.h:438
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:994
MvField::ciip_flag
uint8_t ciip_flag
ciip_flag
Definition: ctu.h:204
Mv::x
int16_t x
horizontal component of motion vector
Definition: hevcdec.h:296
PF_BI
@ PF_BI
Definition: hevcdec.h:116
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: filter.c:384
SliceContext
Definition: mss12.h:70
SAOParams::offset_val
int16_t offset_val[3][5]
SaoOffsetVal.
Definition: hevcdsp.h:42
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:797
ff_vvc_sao_filter
void ff_vvc_sao_filter(VVCLocalContext *lc, int x, int y)
sao filter for the CTU
Definition: filter.c:154
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:734
BOUNDARY_UPPER_SLICE
#define BOUNDARY_UPPER_SLICE
Definition: hevcdec.h:437
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:763
betatable
static const uint8_t betatable[64]
Definition: filter.c:47
ALF_PADDING_SIZE
#define ALF_PADDING_SIZE
Definition: ctu.h:73
CTB
#define CTB(tab, x, y)
Definition: hevc_filter.c:254
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: filter.c:447
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:950
size
int size
Definition: twinvq_data.h:10344
ALF_BLOCK_SIZE
#define ALF_BLOCK_SIZE
Definition: ctu.h:74
CR
#define CR
Definition: hevc_filter.c:33
VVCRefPic::poc
int poc
Definition: dec.h:47
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:1050
H266RawSliceHeader::sh_alf_aps_id_chroma
uint8_t sh_alf_aps_id_chroma
Definition: cbs_h266.h:786
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)
Definition: filter.c:702
MvField
Definition: hevcdec.h:300
refs.h
frame.h
TAB_BS
#define TAB_BS(t, x, y)
Definition: filter.c:306
height
#define height
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
ff_vvc_get_ref_list
const RefPicList * ff_vvc_get_ref_list(const VVCFrameContext *fc, const VVCFrame *ref, int x0, int y0)
Definition: refs.c:69
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: ctu.h:463
H266RawSliceHeader
Definition: cbs_h266.h:769
flag
#define flag(name)
Definition: cbs_av1.c:466
VVCLocalContext::boundary_flags
int boundary_flags
Definition: ctu.h:430
MODE_INTRA
#define MODE_INTRA
Definition: vp3.c:84
ALF_NUM_COEFF_CHROMA
#define ALF_NUM_COEFF_CHROMA
Definition: ps.h:162
ff_vvc_alf_aps_class_to_filt_map
const uint8_t ff_vvc_alf_aps_class_to_filt_map[25]
Definition: data.c:1731
BOUNDARY_LEFT_SUBPIC
#define BOUNDARY_LEFT_SUBPIC
Definition: ctu.h:424
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
H266RawSliceHeader::sh_alf_aps_id_luma
uint8_t sh_alf_aps_id_luma[8]
Definition: cbs_h266.h:783
MAX_PB_SIZE
#define MAX_PB_SIZE
Definition: hevcdsp.h:32
alf_clip_from_idx
static int alf_clip_from_idx(const VVCFrameContext *fc, const int idx)
Definition: filter.c:1133
av_always_inline
#define av_always_inline
Definition: attributes.h:49
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
EDGE_EMU_BUFFER_STRIDE
#define EDGE_EMU_BUFFER_STRIDE
Definition: hevcdec.h:67
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:1276
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
ff_vvc_get_qPy
int ff_vvc_get_qPy(const VVCFrameContext *fc, const int xc, const int yc)
Definition: ctu.c:2542
stride
#define stride
Definition: h264pred_template.c:537
BOUNDARY_UPPER_SUBPIC
#define BOUNDARY_UPPER_SUBPIC
Definition: ctu.h:427
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: filter.c:1158
data.h
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
pos
unsigned int pos
Definition: spdifenc.c:414
get_qPc
static int get_qPc(const VVCFrameContext *fc, const int x0, const int y0, const int chroma)
Definition: filter.c:54
ALFParams::alf_ctb_filter_alt_idx
uint8_t alf_ctb_filter_alt_idx[2]
alf_ctb_filter_alt_idx[]
Definition: ctu.h:462
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
id
enum AVCodecID id
Definition: dts2pts.c:365
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
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: filter.c:409
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:984
ALFParams::ctb_filt_set_idx_y
uint8_t ctb_filt_set_idx_y
AlfCtbFiltSetIdxY.
Definition: ctu.h:461
pps
uint64_t pps
Definition: dovi_rpuenc.c:35
SAOParams::type_idx
uint8_t type_idx[3]
sao_type_idx
Definition: hevcdsp.h:44
ALF_BORDER_CHROMA
#define ALF_BORDER_CHROMA
Definition: ctu.h:77
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, const int rs)
Definition: filter.c:568
MAX_QP
#define MAX_QP
Definition: hevcdec.h:49
MvField::mv
Mv mv[2]
mvL0, vvL1
Definition: hevcdec.h:301
ALFParams
Definition: ctu.h:459
tc
#define tc
Definition: regdef.h:69
ff_vvc_alf_fix_filt_coeff
const int16_t ff_vvc_alf_fix_filt_coeff[64][12]
Definition: data.c:1644
Mv
Definition: hevcdec.h:295
MvField::ref_idx
int8_t ref_idx[2]
refIdxL0, refIdxL1
Definition: hevcdec.h:302
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:1175
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:1016
ALF_NUM_FILTERS_LUMA
#define ALF_NUM_FILTERS_LUMA
Definition: ps.h:157
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: filter.c:1117
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
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, const int rs)
Definition: filter.c:617
SliceContext::sh
VVCSH sh
Definition: dec.h:108
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
VVCFrameContext
Definition: dec.h:115
ALFParams::ctb_flag
uint8_t ctb_flag[3]
alf_ctb_flag[]
Definition: ctu.h:460
int32_t
int32_t
Definition: audioconvert.c:56
coeff
static const double coeff[2][5]
Definition: vf_owdenoise.c:80
h
h
Definition: vp9dsp_template.c:2038
ctu.h
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:744
BOUNDARY_LEFT_SLICE
#define BOUNDARY_LEFT_SLICE
Definition: hevcdec.h:435
ALF_VB_POS_ABOVE_CHROMA
#define ALF_VB_POS_ABOVE_CHROMA
Definition: ctu.h:80
SAOParams::band_position
uint8_t band_position[3]
sao_band_position
Definition: hevcdsp.h:38
LUMA
#define LUMA
Definition: hevc_filter.c:31
copy_pixel
static void copy_pixel(uint8_t *dst, const uint8_t *src, const int pixel_shift)
Definition: filter.c:73
MIN_TU_LOG2
#define MIN_TU_LOG2
MinTbLog2SizeY.
Definition: dec.h:39
VVCFrameContext::tab
struct VVCFrameContext::@249 tab
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: filter.c:1141