Line data Source code
1 : /*
2 : * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3 : *
4 : * This source code is subject to the terms of the BSD 2 Clause License and
5 : * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 : * was not distributed with this source code in the LICENSE file, you can
7 : * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 : * Media Patent License 1.0 was not distributed with this source code in the
9 : * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 : */
11 :
12 : #include <assert.h>
13 : #include <math.h>
14 : #include <string.h>
15 :
16 : #include "./aom_scale_rtcd.h"
17 : #include "aom/aom_integer.h"
18 : #include "av1/common/cdef.h"
19 : #include "av1/common/od_dering.h"
20 : #include "av1/common/onyxc_int.h"
21 : #include "av1/common/reconinter.h"
22 :
23 0 : int sb_all_skip(const AV1_COMMON *const cm, int mi_row, int mi_col) {
24 : int r, c;
25 : int maxc, maxr;
26 0 : int skip = 1;
27 0 : maxc = cm->mi_cols - mi_col;
28 0 : maxr = cm->mi_rows - mi_row;
29 :
30 0 : maxr = AOMMIN(maxr, cm->mib_size);
31 0 : maxc = AOMMIN(maxc, cm->mib_size);
32 :
33 0 : for (r = 0; r < maxr; r++) {
34 0 : for (c = 0; c < maxc; c++) {
35 0 : skip = skip &&
36 0 : cm->mi_grid_visible[(mi_row + r) * cm->mi_stride + mi_col + c]
37 0 : ->mbmi.skip;
38 : }
39 : }
40 0 : return skip;
41 : }
42 :
43 0 : static int is_8x8_block_skip(MODE_INFO **grid, int mi_row, int mi_col,
44 : int mi_stride) {
45 0 : int is_skip = 1;
46 0 : for (int r = 0; r < mi_size_high[BLOCK_8X8]; ++r)
47 0 : for (int c = 0; c < mi_size_wide[BLOCK_8X8]; ++c)
48 0 : is_skip &= grid[(mi_row + r) * mi_stride + (mi_col + c)]->mbmi.skip;
49 :
50 0 : return is_skip;
51 : }
52 :
53 0 : int sb_compute_dering_list(const AV1_COMMON *const cm, int mi_row, int mi_col,
54 : dering_list *dlist, int filter_skip) {
55 : int r, c;
56 : int maxc, maxr;
57 : MODE_INFO **grid;
58 0 : int count = 0;
59 0 : grid = cm->mi_grid_visible;
60 0 : maxc = cm->mi_cols - mi_col;
61 0 : maxr = cm->mi_rows - mi_row;
62 :
63 0 : maxr = AOMMIN(maxr, cm->mib_size);
64 0 : maxc = AOMMIN(maxc, cm->mib_size);
65 :
66 0 : const int r_step = mi_size_high[BLOCK_8X8];
67 0 : const int c_step = mi_size_wide[BLOCK_8X8];
68 0 : const int r_shift = (r_step == 2);
69 0 : const int c_shift = (c_step == 2);
70 :
71 0 : assert(r_step == 1 || r_step == 2);
72 0 : assert(c_step == 1 || c_step == 2);
73 :
74 0 : if (filter_skip) {
75 0 : for (r = 0; r < maxr; r += r_step) {
76 0 : for (c = 0; c < maxc; c += c_step) {
77 0 : dlist[count].by = r >> r_shift;
78 0 : dlist[count].bx = c >> c_shift;
79 0 : dlist[count].skip =
80 0 : is_8x8_block_skip(grid, mi_row + r, mi_col + c, cm->mi_stride);
81 0 : count++;
82 : }
83 : }
84 : } else {
85 0 : for (r = 0; r < maxr; r += r_step) {
86 0 : for (c = 0; c < maxc; c += c_step) {
87 0 : if (!is_8x8_block_skip(grid, mi_row + r, mi_col + c, cm->mi_stride)) {
88 0 : dlist[count].by = r >> r_shift;
89 0 : dlist[count].bx = c >> c_shift;
90 0 : dlist[count].skip = 0;
91 0 : count++;
92 : }
93 : }
94 : }
95 : }
96 0 : return count;
97 : }
98 :
99 0 : void copy_rect8_8bit_to_16bit_c(uint16_t *dst, int dstride, const uint8_t *src,
100 : int sstride, int v, int h) {
101 : int i, j;
102 0 : for (i = 0; i < v; i++) {
103 0 : for (j = 0; j < h; j++) {
104 0 : dst[i * dstride + j] = src[i * sstride + j];
105 : }
106 : }
107 0 : }
108 :
109 0 : void copy_rect8_16bit_to_16bit_c(uint16_t *dst, int dstride,
110 : const uint16_t *src, int sstride, int v,
111 : int h) {
112 : int i, j;
113 0 : for (i = 0; i < v; i++) {
114 0 : for (j = 0; j < h; j++) {
115 0 : dst[i * dstride + j] = src[i * sstride + j];
116 : }
117 : }
118 0 : }
119 :
120 0 : void copy_sb8_16(UNUSED AV1_COMMON *cm, uint16_t *dst, int dstride,
121 : const uint8_t *src, int src_voffset, int src_hoffset,
122 : int sstride, int vsize, int hsize) {
123 : #if CONFIG_HIGHBITDEPTH
124 0 : if (cm->use_highbitdepth) {
125 0 : const uint16_t *base =
126 0 : &CONVERT_TO_SHORTPTR(src)[src_voffset * sstride + src_hoffset];
127 0 : copy_rect8_16bit_to_16bit(dst, dstride, base, sstride, vsize, hsize);
128 : } else {
129 : #endif
130 0 : const uint8_t *base = &src[src_voffset * sstride + src_hoffset];
131 0 : copy_rect8_8bit_to_16bit(dst, dstride, base, sstride, vsize, hsize);
132 : #if CONFIG_HIGHBITDEPTH
133 : }
134 : #endif
135 0 : }
136 :
137 0 : static INLINE void fill_rect(uint16_t *dst, int dstride, int v, int h,
138 : uint16_t x) {
139 : int i, j;
140 0 : for (i = 0; i < v; i++) {
141 0 : for (j = 0; j < h; j++) {
142 0 : dst[i * dstride + j] = x;
143 : }
144 : }
145 0 : }
146 :
147 0 : static INLINE void copy_rect(uint16_t *dst, int dstride, const uint16_t *src,
148 : int sstride, int v, int h) {
149 : int i, j;
150 0 : for (i = 0; i < v; i++) {
151 0 : for (j = 0; j < h; j++) {
152 0 : dst[i * dstride + j] = src[i * sstride + j];
153 : }
154 : }
155 0 : }
156 :
157 0 : void av1_cdef_frame(YV12_BUFFER_CONFIG *frame, AV1_COMMON *cm,
158 : MACROBLOCKD *xd) {
159 : int sbr, sbc;
160 : int nhsb, nvsb;
161 : uint16_t src[OD_DERING_INBUF_SIZE];
162 : uint16_t *linebuf[3];
163 : uint16_t *colbuf[3];
164 : dering_list dlist[MAX_MIB_SIZE * MAX_MIB_SIZE];
165 : unsigned char *row_dering, *prev_row_dering, *curr_row_dering;
166 : int dering_count;
167 0 : int dir[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS] = { { 0 } };
168 0 : int var[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS] = { { 0 } };
169 : int stride;
170 : int mi_wide_l2[3];
171 : int mi_high_l2[3];
172 : int xdec[3];
173 : int ydec[3];
174 : int pli;
175 : int dering_left;
176 0 : int coeff_shift = AOMMAX(cm->bit_depth - 8, 0);
177 0 : int nplanes = 3;
178 0 : int chroma_dering =
179 0 : xd->plane[1].subsampling_x == xd->plane[1].subsampling_y &&
180 0 : xd->plane[2].subsampling_x == xd->plane[2].subsampling_y;
181 0 : nvsb = (cm->mi_rows + MAX_MIB_SIZE - 1) / MAX_MIB_SIZE;
182 0 : nhsb = (cm->mi_cols + MAX_MIB_SIZE - 1) / MAX_MIB_SIZE;
183 0 : av1_setup_dst_planes(xd->plane, cm->sb_size, frame, 0, 0);
184 0 : row_dering = aom_malloc(sizeof(*row_dering) * (nhsb + 2) * 2);
185 0 : memset(row_dering, 1, sizeof(*row_dering) * (nhsb + 2) * 2);
186 0 : prev_row_dering = row_dering + 1;
187 0 : curr_row_dering = prev_row_dering + nhsb + 2;
188 0 : for (pli = 0; pli < nplanes; pli++) {
189 0 : xdec[pli] = xd->plane[pli].subsampling_x;
190 0 : ydec[pli] = xd->plane[pli].subsampling_y;
191 0 : mi_wide_l2[pli] = MI_SIZE_LOG2 - xd->plane[pli].subsampling_x;
192 0 : mi_high_l2[pli] = MI_SIZE_LOG2 - xd->plane[pli].subsampling_y;
193 : }
194 0 : stride = (cm->mi_cols << MI_SIZE_LOG2) + 2 * OD_FILT_HBORDER;
195 0 : for (pli = 0; pli < nplanes; pli++) {
196 0 : linebuf[pli] = aom_malloc(sizeof(*linebuf) * OD_FILT_VBORDER * stride);
197 0 : colbuf[pli] =
198 0 : aom_malloc(sizeof(*colbuf) *
199 0 : ((MAX_SB_SIZE << mi_high_l2[pli]) + 2 * OD_FILT_VBORDER) *
200 : OD_FILT_HBORDER);
201 : }
202 0 : for (sbr = 0; sbr < nvsb; sbr++) {
203 0 : for (pli = 0; pli < nplanes; pli++) {
204 0 : const int block_height =
205 0 : (MAX_MIB_SIZE << mi_high_l2[pli]) + 2 * OD_FILT_VBORDER;
206 0 : fill_rect(colbuf[pli], OD_FILT_HBORDER, block_height, OD_FILT_HBORDER,
207 : OD_DERING_VERY_LARGE);
208 : }
209 0 : dering_left = 1;
210 0 : for (sbc = 0; sbc < nhsb; sbc++) {
211 : int level, clpf_strength;
212 : int uv_level, uv_clpf_strength;
213 : int nhb, nvb;
214 0 : int cstart = 0;
215 0 : curr_row_dering[sbc] = 0;
216 0 : if (cm->mi_grid_visible[MAX_MIB_SIZE * sbr * cm->mi_stride +
217 0 : MAX_MIB_SIZE * sbc] == NULL ||
218 0 : cm->mi_grid_visible[MAX_MIB_SIZE * sbr * cm->mi_stride +
219 : MAX_MIB_SIZE * sbc]
220 0 : ->mbmi.cdef_strength == -1) {
221 0 : dering_left = 0;
222 0 : continue;
223 : }
224 0 : if (!dering_left) cstart = -OD_FILT_HBORDER;
225 0 : nhb = AOMMIN(MAX_MIB_SIZE, cm->mi_cols - MAX_MIB_SIZE * sbc);
226 0 : nvb = AOMMIN(MAX_MIB_SIZE, cm->mi_rows - MAX_MIB_SIZE * sbr);
227 : int tile_top, tile_left, tile_bottom, tile_right;
228 0 : int mi_idx = MAX_MIB_SIZE * sbr * cm->mi_stride + MAX_MIB_SIZE * sbc;
229 0 : BOUNDARY_TYPE boundary_tl =
230 0 : cm->mi_grid_visible[MAX_MIB_SIZE * sbr * cm->mi_stride +
231 : MAX_MIB_SIZE * sbc]
232 : ->mbmi.boundary_info;
233 0 : tile_top = boundary_tl & TILE_ABOVE_BOUNDARY;
234 0 : tile_left = boundary_tl & TILE_LEFT_BOUNDARY;
235 : /* Right and bottom information appear unreliable, so we use the top
236 : and left flags for the next superblocks. */
237 0 : if (sbr != nvsb - 1 &&
238 0 : cm->mi_grid_visible[mi_idx + MAX_MIB_SIZE * cm->mi_stride])
239 0 : tile_bottom = cm->mi_grid_visible[mi_idx + MAX_MIB_SIZE * cm->mi_stride]
240 0 : ->mbmi.boundary_info &
241 : TILE_ABOVE_BOUNDARY;
242 : else
243 0 : tile_bottom = 1;
244 0 : if (sbc != nhsb - 1 && cm->mi_grid_visible[mi_idx + MAX_MIB_SIZE])
245 0 : tile_right =
246 0 : cm->mi_grid_visible[mi_idx + MAX_MIB_SIZE]->mbmi.boundary_info &
247 : TILE_LEFT_BOUNDARY;
248 : else
249 0 : tile_right = 1;
250 0 : const int mbmi_cdef_strength =
251 0 : cm->mi_grid_visible[MAX_MIB_SIZE * sbr * cm->mi_stride +
252 : MAX_MIB_SIZE * sbc]
253 0 : ->mbmi.cdef_strength;
254 0 : level = cm->cdef_strengths[mbmi_cdef_strength] / CLPF_STRENGTHS;
255 0 : clpf_strength = cm->cdef_strengths[mbmi_cdef_strength] % CLPF_STRENGTHS;
256 0 : clpf_strength += clpf_strength == 3;
257 0 : uv_level = cm->cdef_uv_strengths[mbmi_cdef_strength] / CLPF_STRENGTHS;
258 0 : uv_clpf_strength =
259 0 : cm->cdef_uv_strengths[mbmi_cdef_strength] % CLPF_STRENGTHS;
260 0 : uv_clpf_strength += uv_clpf_strength == 3;
261 0 : if ((level == 0 && clpf_strength == 0 && uv_level == 0 &&
262 0 : uv_clpf_strength == 0) ||
263 0 : (dering_count = sb_compute_dering_list(
264 : cm, sbr * MAX_MIB_SIZE, sbc * MAX_MIB_SIZE, dlist,
265 0 : get_filter_skip(level) || get_filter_skip(uv_level))) == 0) {
266 0 : dering_left = 0;
267 0 : continue;
268 : }
269 :
270 0 : curr_row_dering[sbc] = 1;
271 0 : for (pli = 0; pli < nplanes; pli++) {
272 : uint16_t dst[MAX_SB_SIZE * MAX_SB_SIZE];
273 : int coffset;
274 : int rend, cend;
275 0 : int clpf_damping = cm->cdef_clpf_damping;
276 0 : int dering_damping = cm->cdef_dering_damping;
277 0 : int hsize = nhb << mi_wide_l2[pli];
278 0 : int vsize = nvb << mi_high_l2[pli];
279 :
280 0 : if (pli) {
281 0 : if (chroma_dering)
282 0 : level = uv_level;
283 : else
284 0 : level = 0;
285 0 : clpf_strength = uv_clpf_strength;
286 : }
287 :
288 0 : if (sbc == nhsb - 1)
289 0 : cend = hsize;
290 : else
291 0 : cend = hsize + OD_FILT_HBORDER;
292 :
293 0 : if (sbr == nvsb - 1)
294 0 : rend = vsize;
295 : else
296 0 : rend = vsize + OD_FILT_VBORDER;
297 :
298 0 : coffset = sbc * MAX_MIB_SIZE << mi_wide_l2[pli];
299 0 : if (sbc == nhsb - 1) {
300 : /* On the last superblock column, fill in the right border with
301 : OD_DERING_VERY_LARGE to avoid filtering with the outside. */
302 0 : fill_rect(&src[cend + OD_FILT_HBORDER], OD_FILT_BSTRIDE,
303 0 : rend + OD_FILT_VBORDER, hsize + OD_FILT_HBORDER - cend,
304 : OD_DERING_VERY_LARGE);
305 : }
306 0 : if (sbr == nvsb - 1) {
307 : /* On the last superblock row, fill in the bottom border with
308 : OD_DERING_VERY_LARGE to avoid filtering with the outside. */
309 0 : fill_rect(&src[(rend + OD_FILT_VBORDER) * OD_FILT_BSTRIDE],
310 : OD_FILT_BSTRIDE, OD_FILT_VBORDER,
311 : hsize + 2 * OD_FILT_HBORDER, OD_DERING_VERY_LARGE);
312 : }
313 : /* Copy in the pixels we need from the current superblock for
314 : deringing.*/
315 0 : copy_sb8_16(
316 : cm,
317 0 : &src[OD_FILT_VBORDER * OD_FILT_BSTRIDE + OD_FILT_HBORDER + cstart],
318 0 : OD_FILT_BSTRIDE, xd->plane[pli].dst.buf,
319 0 : (MAX_MIB_SIZE << mi_high_l2[pli]) * sbr, coffset + cstart,
320 : xd->plane[pli].dst.stride, rend, cend - cstart);
321 0 : if (!prev_row_dering[sbc]) {
322 0 : copy_sb8_16(cm, &src[OD_FILT_HBORDER], OD_FILT_BSTRIDE,
323 0 : xd->plane[pli].dst.buf,
324 0 : (MAX_MIB_SIZE << mi_high_l2[pli]) * sbr - OD_FILT_VBORDER,
325 : coffset, xd->plane[pli].dst.stride, OD_FILT_VBORDER,
326 : hsize);
327 0 : } else if (sbr > 0) {
328 0 : copy_rect(&src[OD_FILT_HBORDER], OD_FILT_BSTRIDE,
329 0 : &linebuf[pli][coffset], stride, OD_FILT_VBORDER, hsize);
330 : } else {
331 0 : fill_rect(&src[OD_FILT_HBORDER], OD_FILT_BSTRIDE, OD_FILT_VBORDER,
332 : hsize, OD_DERING_VERY_LARGE);
333 : }
334 0 : if (!prev_row_dering[sbc - 1]) {
335 0 : copy_sb8_16(cm, src, OD_FILT_BSTRIDE, xd->plane[pli].dst.buf,
336 0 : (MAX_MIB_SIZE << mi_high_l2[pli]) * sbr - OD_FILT_VBORDER,
337 : coffset - OD_FILT_HBORDER, xd->plane[pli].dst.stride,
338 : OD_FILT_VBORDER, OD_FILT_HBORDER);
339 0 : } else if (sbr > 0 && sbc > 0) {
340 0 : copy_rect(src, OD_FILT_BSTRIDE,
341 0 : &linebuf[pli][coffset - OD_FILT_HBORDER], stride,
342 : OD_FILT_VBORDER, OD_FILT_HBORDER);
343 : } else {
344 0 : fill_rect(src, OD_FILT_BSTRIDE, OD_FILT_VBORDER, OD_FILT_HBORDER,
345 : OD_DERING_VERY_LARGE);
346 : }
347 0 : if (!prev_row_dering[sbc + 1]) {
348 0 : copy_sb8_16(cm, &src[OD_FILT_HBORDER + (nhb << mi_wide_l2[pli])],
349 0 : OD_FILT_BSTRIDE, xd->plane[pli].dst.buf,
350 0 : (MAX_MIB_SIZE << mi_high_l2[pli]) * sbr - OD_FILT_VBORDER,
351 : coffset + hsize, xd->plane[pli].dst.stride,
352 : OD_FILT_VBORDER, OD_FILT_HBORDER);
353 0 : } else if (sbr > 0 && sbc < nhsb - 1) {
354 0 : copy_rect(&src[hsize + OD_FILT_HBORDER], OD_FILT_BSTRIDE,
355 0 : &linebuf[pli][coffset + hsize], stride, OD_FILT_VBORDER,
356 : OD_FILT_HBORDER);
357 : } else {
358 0 : fill_rect(&src[hsize + OD_FILT_HBORDER], OD_FILT_BSTRIDE,
359 : OD_FILT_VBORDER, OD_FILT_HBORDER, OD_DERING_VERY_LARGE);
360 : }
361 0 : if (dering_left) {
362 : /* If we deringed the superblock on the left then we need to copy in
363 : saved pixels. */
364 0 : copy_rect(src, OD_FILT_BSTRIDE, colbuf[pli], OD_FILT_HBORDER,
365 : rend + OD_FILT_VBORDER, OD_FILT_HBORDER);
366 : }
367 : /* Saving pixels in case we need to dering the superblock on the
368 : right. */
369 0 : copy_rect(colbuf[pli], OD_FILT_HBORDER, src + hsize, OD_FILT_BSTRIDE,
370 : rend + OD_FILT_VBORDER, OD_FILT_HBORDER);
371 0 : copy_sb8_16(
372 0 : cm, &linebuf[pli][coffset], stride, xd->plane[pli].dst.buf,
373 0 : (MAX_MIB_SIZE << mi_high_l2[pli]) * (sbr + 1) - OD_FILT_VBORDER,
374 : coffset, xd->plane[pli].dst.stride, OD_FILT_VBORDER, hsize);
375 :
376 0 : if (tile_top) {
377 0 : fill_rect(src, OD_FILT_BSTRIDE, OD_FILT_VBORDER,
378 : hsize + 2 * OD_FILT_HBORDER, OD_DERING_VERY_LARGE);
379 : }
380 0 : if (tile_left) {
381 0 : fill_rect(src, OD_FILT_BSTRIDE, vsize + 2 * OD_FILT_VBORDER,
382 : OD_FILT_HBORDER, OD_DERING_VERY_LARGE);
383 : }
384 0 : if (tile_bottom) {
385 0 : fill_rect(&src[(vsize + OD_FILT_VBORDER) * OD_FILT_BSTRIDE],
386 : OD_FILT_BSTRIDE, OD_FILT_VBORDER,
387 : hsize + 2 * OD_FILT_HBORDER, OD_DERING_VERY_LARGE);
388 : }
389 0 : if (tile_right) {
390 0 : fill_rect(&src[hsize + OD_FILT_HBORDER], OD_FILT_BSTRIDE,
391 : vsize + 2 * OD_FILT_VBORDER, OD_FILT_HBORDER,
392 : OD_DERING_VERY_LARGE);
393 : }
394 : #if CONFIG_HIGHBITDEPTH
395 0 : if (cm->use_highbitdepth) {
396 0 : od_dering(
397 0 : (uint8_t *)&CONVERT_TO_SHORTPTR(
398 : xd->plane[pli]
399 0 : .dst.buf)[xd->plane[pli].dst.stride *
400 0 : (MAX_MIB_SIZE * sbr << mi_high_l2[pli]) +
401 0 : (sbc * MAX_MIB_SIZE << mi_wide_l2[pli])],
402 : xd->plane[pli].dst.stride, dst,
403 : &src[OD_FILT_VBORDER * OD_FILT_BSTRIDE + OD_FILT_HBORDER],
404 : xdec[pli], ydec[pli], dir, NULL, var, pli, dlist, dering_count,
405 : level, clpf_strength, clpf_damping, dering_damping, coeff_shift,
406 : 0, 1);
407 : } else {
408 : #endif
409 0 : od_dering(&xd->plane[pli]
410 0 : .dst.buf[xd->plane[pli].dst.stride *
411 0 : (MAX_MIB_SIZE * sbr << mi_high_l2[pli]) +
412 0 : (sbc * MAX_MIB_SIZE << mi_wide_l2[pli])],
413 : xd->plane[pli].dst.stride, dst,
414 : &src[OD_FILT_VBORDER * OD_FILT_BSTRIDE + OD_FILT_HBORDER],
415 : xdec[pli], ydec[pli], dir, NULL, var, pli, dlist,
416 : dering_count, level, clpf_strength, clpf_damping,
417 : dering_damping, coeff_shift, 0, 0);
418 :
419 : #if CONFIG_HIGHBITDEPTH
420 : }
421 : #endif
422 : }
423 0 : dering_left = 1;
424 : }
425 : {
426 : unsigned char *tmp;
427 0 : tmp = prev_row_dering;
428 0 : prev_row_dering = curr_row_dering;
429 0 : curr_row_dering = tmp;
430 : }
431 : }
432 0 : aom_free(row_dering);
433 0 : for (pli = 0; pli < nplanes; pli++) {
434 0 : aom_free(linebuf[pli]);
435 0 : aom_free(colbuf[pli]);
436 : }
437 0 : }
|