blob: 02c385cb4cfe0135db2270bc5b87fff1643b182a [file] [log] [blame]
Yaowu Xu2ab7ff02016-09-02 12:04:54 -07001/*
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 */
Yaowu Xu253c0012016-08-15 10:27:19 -070011#ifdef HAVE_CONFIG_H
clang-format21a0c2c2016-08-18 15:10:22 -070012#include "config.h"
Yaowu Xu253c0012016-08-15 10:27:19 -070013#endif
14
Jean-Marc Valina8ce2c92016-10-07 18:10:19 -040015// clang-format off
16
Yaowu Xu253c0012016-08-15 10:27:19 -070017#include <stdlib.h>
18#include <math.h>
19#include "dering.h"
Michael Bebenita7227b652016-10-06 14:27:34 -070020#include "./av1_rtcd.h"
Yaowu Xu253c0012016-08-15 10:27:19 -070021
22/* Generated from gen_filter_tables.c. */
23const int OD_DIRECTION_OFFSETS_TABLE[8][3] = {
clang-format21a0c2c2016-08-18 15:10:22 -070024 { -1 * OD_FILT_BSTRIDE + 1, -2 * OD_FILT_BSTRIDE + 2,
25 -3 * OD_FILT_BSTRIDE + 3 },
26 { 0 * OD_FILT_BSTRIDE + 1, -1 * OD_FILT_BSTRIDE + 2,
27 -1 * OD_FILT_BSTRIDE + 3 },
28 { 0 * OD_FILT_BSTRIDE + 1, 0 * OD_FILT_BSTRIDE + 2, 0 * OD_FILT_BSTRIDE + 3 },
29 { 0 * OD_FILT_BSTRIDE + 1, 1 * OD_FILT_BSTRIDE + 2, 1 * OD_FILT_BSTRIDE + 3 },
30 { 1 * OD_FILT_BSTRIDE + 1, 2 * OD_FILT_BSTRIDE + 2, 3 * OD_FILT_BSTRIDE + 3 },
31 { 1 * OD_FILT_BSTRIDE + 0, 2 * OD_FILT_BSTRIDE + 1, 3 * OD_FILT_BSTRIDE + 1 },
32 { 1 * OD_FILT_BSTRIDE + 0, 2 * OD_FILT_BSTRIDE + 0, 3 * OD_FILT_BSTRIDE + 0 },
33 { 1 * OD_FILT_BSTRIDE + 0, 2 * OD_FILT_BSTRIDE - 1, 3 * OD_FILT_BSTRIDE - 1 },
Yaowu Xu253c0012016-08-15 10:27:19 -070034};
35
Yaowu Xu253c0012016-08-15 10:27:19 -070036/* Detect direction. 0 means 45-degree up-right, 2 is horizontal, and so on.
37 The search minimizes the weighted variance along all the lines in a
38 particular direction, i.e. the squared error between the input and a
39 "predicted" block where each pixel is replaced by the average along a line
40 in a particular direction. Since each direction have the same sum(x^2) term,
41 that term is never computed. See Section 2, step 2, of:
42 http://jmvalin.ca/notes/intra_paint.pdf */
Michael Bebenita7227b652016-10-06 14:27:34 -070043int od_dir_find8_c(const od_dering_in *img, int stride, int32_t *var,
44 int coeff_shift) {
Yaowu Xu253c0012016-08-15 10:27:19 -070045 int i;
clang-format21a0c2c2016-08-18 15:10:22 -070046 int32_t cost[8] = { 0 };
47 int partial[8][15] = { { 0 } };
Yaowu Xu253c0012016-08-15 10:27:19 -070048 int32_t best_cost = 0;
49 int best_dir = 0;
50 /* Instead of dividing by n between 2 and 8, we multiply by 3*5*7*8/n.
51 The output is then 840 times larger, but we don't care for finding
52 the max. */
clang-format21a0c2c2016-08-18 15:10:22 -070053 static const int div_table[] = { 0, 840, 420, 280, 210, 168, 140, 120, 105 };
Yaowu Xu253c0012016-08-15 10:27:19 -070054 for (i = 0; i < 8; i++) {
55 int j;
56 for (j = 0; j < 8; j++) {
57 int x;
58 /* We subtract 128 here to reduce the maximum range of the squared
59 partial sums. */
clang-format21a0c2c2016-08-18 15:10:22 -070060 x = (img[i * stride + j] >> coeff_shift) - 128;
Yaowu Xu253c0012016-08-15 10:27:19 -070061 partial[0][i + j] += x;
clang-format21a0c2c2016-08-18 15:10:22 -070062 partial[1][i + j / 2] += x;
Yaowu Xu253c0012016-08-15 10:27:19 -070063 partial[2][i] += x;
clang-format21a0c2c2016-08-18 15:10:22 -070064 partial[3][3 + i - j / 2] += x;
Yaowu Xu253c0012016-08-15 10:27:19 -070065 partial[4][7 + i - j] += x;
clang-format21a0c2c2016-08-18 15:10:22 -070066 partial[5][3 - i / 2 + j] += x;
Yaowu Xu253c0012016-08-15 10:27:19 -070067 partial[6][j] += x;
clang-format21a0c2c2016-08-18 15:10:22 -070068 partial[7][i / 2 + j] += x;
Yaowu Xu253c0012016-08-15 10:27:19 -070069 }
70 }
71 for (i = 0; i < 8; i++) {
clang-format21a0c2c2016-08-18 15:10:22 -070072 cost[2] += partial[2][i] * partial[2][i];
73 cost[6] += partial[6][i] * partial[6][i];
Yaowu Xu253c0012016-08-15 10:27:19 -070074 }
75 cost[2] *= div_table[8];
76 cost[6] *= div_table[8];
77 for (i = 0; i < 7; i++) {
clang-format21a0c2c2016-08-18 15:10:22 -070078 cost[0] += (partial[0][i] * partial[0][i] +
79 partial[0][14 - i] * partial[0][14 - i]) *
80 div_table[i + 1];
81 cost[4] += (partial[4][i] * partial[4][i] +
82 partial[4][14 - i] * partial[4][14 - i]) *
83 div_table[i + 1];
Yaowu Xu253c0012016-08-15 10:27:19 -070084 }
clang-format21a0c2c2016-08-18 15:10:22 -070085 cost[0] += partial[0][7] * partial[0][7] * div_table[8];
86 cost[4] += partial[4][7] * partial[4][7] * div_table[8];
Yaowu Xu253c0012016-08-15 10:27:19 -070087 for (i = 1; i < 8; i += 2) {
88 int j;
89 for (j = 0; j < 4 + 1; j++) {
clang-format21a0c2c2016-08-18 15:10:22 -070090 cost[i] += partial[i][3 + j] * partial[i][3 + j];
Yaowu Xu253c0012016-08-15 10:27:19 -070091 }
92 cost[i] *= div_table[8];
93 for (j = 0; j < 4 - 1; j++) {
clang-format21a0c2c2016-08-18 15:10:22 -070094 cost[i] += (partial[i][j] * partial[i][j] +
95 partial[i][10 - j] * partial[i][10 - j]) *
96 div_table[2 * j + 2];
Yaowu Xu253c0012016-08-15 10:27:19 -070097 }
98 }
99 for (i = 0; i < 8; i++) {
100 if (cost[i] > best_cost) {
101 best_cost = cost[i];
102 best_dir = i;
103 }
104 }
105 /* Difference between the optimal variance and the variance along the
106 orthogonal direction. Again, the sum(x^2) terms cancel out. */
107 *var = best_cost - cost[(best_dir + 4) & 7];
108 /* We'd normally divide by 840, but dividing by 1024 is close enough
109 for what we're going to do with this. */
110 *var >>= 10;
111 return best_dir;
112}
113
Yaowu Xu253c0012016-08-15 10:27:19 -0700114/* Smooth in the direction detected. */
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400115int od_filter_dering_direction_8x8_c(int16_t *y, int ystride, const int16_t *in,
116 int threshold, int dir) {
Yaowu Xu253c0012016-08-15 10:27:19 -0700117 int i;
118 int j;
119 int k;
Yaowu Xu9c323bc2016-09-01 11:35:16 -0700120 static const int taps[3] = { 3, 2, 1 };
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400121 int total_abs = 0;
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400122 for (i = 0; i < 8; i++) {
123 for (j = 0; j < 8; j++) {
Yaowu Xu253c0012016-08-15 10:27:19 -0700124 int16_t sum;
125 int16_t xx;
126 int16_t yy;
clang-format21a0c2c2016-08-18 15:10:22 -0700127 xx = in[i * OD_FILT_BSTRIDE + j];
128 sum = 0;
Yaowu Xu253c0012016-08-15 10:27:19 -0700129 for (k = 0; k < 3; k++) {
130 int16_t p0;
131 int16_t p1;
clang-format21a0c2c2016-08-18 15:10:22 -0700132 p0 = in[i * OD_FILT_BSTRIDE + j + OD_DIRECTION_OFFSETS_TABLE[dir][k]] -
133 xx;
134 p1 = in[i * OD_FILT_BSTRIDE + j - OD_DIRECTION_OFFSETS_TABLE[dir][k]] -
135 xx;
136 if (abs(p0) < threshold) sum += taps[k] * p0;
137 if (abs(p1) < threshold) sum += taps[k] * p1;
Yaowu Xu253c0012016-08-15 10:27:19 -0700138 }
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400139 sum = (sum + 8) >> 4;
140 total_abs += abs(sum);
141 yy = xx + sum;
clang-format21a0c2c2016-08-18 15:10:22 -0700142 y[i * ystride + j] = yy;
Yaowu Xu253c0012016-08-15 10:27:19 -0700143 }
144 }
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400145 return (total_abs + 8) >> 4;
Yaowu Xu253c0012016-08-15 10:27:19 -0700146}
147
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400148/* Smooth in the direction detected. */
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400149int od_filter_dering_direction_4x4_c(int16_t *y, int ystride, const int16_t *in,
150 int threshold, int dir) {
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400151 int i;
152 int j;
153 int k;
154 static const int taps[2] = { 4, 1 };
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400155 int total_abs = 0;
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400156 for (i = 0; i < 4; i++) {
157 for (j = 0; j < 4; j++) {
158 int16_t sum;
159 int16_t xx;
160 int16_t yy;
161 xx = in[i * OD_FILT_BSTRIDE + j];
162 sum = 0;
163 for (k = 0; k < 2; k++) {
164 int16_t p0;
165 int16_t p1;
166 p0 = in[i * OD_FILT_BSTRIDE + j + OD_DIRECTION_OFFSETS_TABLE[dir][k]] -
167 xx;
168 p1 = in[i * OD_FILT_BSTRIDE + j - OD_DIRECTION_OFFSETS_TABLE[dir][k]] -
169 xx;
170 if (abs(p0) < threshold) sum += taps[k] * p0;
171 if (abs(p1) < threshold) sum += taps[k] * p1;
172 }
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400173 sum = (sum + 8) >> 4;
174 total_abs += abs(sum);
175 yy = xx + sum;
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400176 y[i * ystride + j] = yy;
177 }
178 }
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400179 return (total_abs + 2) >> 2;
Yaowu Xu253c0012016-08-15 10:27:19 -0700180}
181
182/* Smooth in the direction orthogonal to what was detected. */
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400183void od_filter_dering_orthogonal_8x8_c(int16_t *y, int ystride,
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400184 const int16_t *in, int threshold,
185 int dir) {
Yaowu Xu253c0012016-08-15 10:27:19 -0700186 int i;
187 int j;
188 int offset;
clang-format21a0c2c2016-08-18 15:10:22 -0700189 if (dir > 0 && dir < 4)
190 offset = OD_FILT_BSTRIDE;
191 else
192 offset = 1;
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400193 for (i = 0; i < 8; i++) {
194 for (j = 0; j < 8; j++) {
Yaowu Xu253c0012016-08-15 10:27:19 -0700195 int16_t yy;
196 int16_t sum;
197 int16_t p;
clang-format21a0c2c2016-08-18 15:10:22 -0700198 yy = in[i * OD_FILT_BSTRIDE + j];
Yaowu Xu253c0012016-08-15 10:27:19 -0700199 sum = 0;
clang-format21a0c2c2016-08-18 15:10:22 -0700200 p = in[i * OD_FILT_BSTRIDE + j + offset] - yy;
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400201 if (abs(p) < threshold) sum += p;
clang-format21a0c2c2016-08-18 15:10:22 -0700202 p = in[i * OD_FILT_BSTRIDE + j - offset] - yy;
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400203 if (abs(p) < threshold) sum += p;
clang-format21a0c2c2016-08-18 15:10:22 -0700204 p = in[i * OD_FILT_BSTRIDE + j + 2 * offset] - yy;
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400205 if (abs(p) < threshold) sum += p;
clang-format21a0c2c2016-08-18 15:10:22 -0700206 p = in[i * OD_FILT_BSTRIDE + j - 2 * offset] - yy;
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400207 if (abs(p) < threshold) sum += p;
clang-format21a0c2c2016-08-18 15:10:22 -0700208 y[i * ystride + j] = yy + ((3 * sum + 8) >> 4);
Yaowu Xu253c0012016-08-15 10:27:19 -0700209 }
210 }
211}
212
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400213/* Smooth in the direction orthogonal to what was detected. */
Yaowu Xu253c0012016-08-15 10:27:19 -0700214void od_filter_dering_orthogonal_4x4_c(int16_t *y, int ystride,
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400215 const int16_t *in, int threshold,
216 int dir) {
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400217 int i;
218 int j;
219 int offset;
220 if (dir > 0 && dir < 4)
221 offset = OD_FILT_BSTRIDE;
222 else
223 offset = 1;
224 for (i = 0; i < 4; i++) {
225 for (j = 0; j < 4; j++) {
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400226 int16_t yy;
227 int16_t sum;
228 int16_t p;
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400229 yy = in[i * OD_FILT_BSTRIDE + j];
230 sum = 0;
231 p = in[i * OD_FILT_BSTRIDE + j + offset] - yy;
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400232 if (abs(p) < threshold) sum += p;
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400233 p = in[i * OD_FILT_BSTRIDE + j - offset] - yy;
Jean-Marc Valin4713d8d2016-09-16 11:06:50 -0400234 if (abs(p) < threshold) sum += p;
Jean-Marc Valinea64c342016-09-15 16:23:12 -0400235 y[i * ystride + j] = yy + ((5 * sum + 8) >> 4);
236 }
237 }
Yaowu Xu253c0012016-08-15 10:27:19 -0700238}
239
240/* This table approximates x^0.16 with the index being log2(x). It is clamped
241 to [-.5, 3]. The table is computed as:
242 round(256*min(3, max(.5, 1.08*(sqrt(2)*2.^([0:17]+8)/256/256).^.16))) */
243static const int16_t OD_THRESH_TABLE_Q8[18] = {
clang-format21a0c2c2016-08-18 15:10:22 -0700244 128, 134, 150, 168, 188, 210, 234, 262, 292,
245 327, 365, 408, 455, 509, 569, 635, 710, 768,
Yaowu Xu253c0012016-08-15 10:27:19 -0700246};
247
Jean-Marc Valina8ce2c92016-10-07 18:10:19 -0400248/* Compute deringing filter threshold for an 8x8 block based on the
Yaowu Xu253c0012016-08-15 10:27:19 -0700249 directional variance difference. A high variance difference means that we
250 have a highly directional pattern (e.g. a high contrast edge), so we can
251 apply more deringing. A low variance means that we either have a low
252 contrast edge, or a non-directional texture, so we want to be careful not
253 to blur. */
Jean-Marc Valina8ce2c92016-10-07 18:10:19 -0400254static INLINE int od_adjust_thresh(int threshold, int32_t var) {
255 int v1;
256 /* We use the variance of 8x8 blocks to adjust the threshold. */
257 v1 = OD_MINI(32767, var >> 6);
258 return (threshold * OD_THRESH_TABLE_Q8[OD_ILOG(v1)] + 128) >> 8;
Yaowu Xu253c0012016-08-15 10:27:19 -0700259}
260
Jean-Marc Valincf23aef2016-10-11 17:47:36 -0400261static INLINE void copy_8x8_16bit(int16_t *dst, int dstride, int16_t *src, int sstride) {
262 int i, j;
263 for (i = 0; i < 8; i++)
264 for (j = 0; j < 8; j++)
265 dst[i * dstride + j] = src[i * sstride + j];
266}
267
268static INLINE void copy_4x4_16bit(int16_t *dst, int dstride, int16_t *src, int sstride) {
269 int i, j;
270 for (i = 0; i < 4; i++)
271 for (j = 0; j < 4; j++)
272 dst[i * dstride + j] = src[i * sstride + j];
273}
274
275/* TODO: Optimize this function for SSE. */
Jean-Marc Valin82c65fc2016-10-12 18:09:48 -0400276void copy_blocks_16bit(int16_t *dst, int dstride, int16_t *src,
Jean-Marc Valine0465032016-10-18 15:56:37 -0400277 dering_list *dlist, int dering_count, int bsize)
Jean-Marc Valincf23aef2016-10-11 17:47:36 -0400278{
279 int bi, bx, by;
280 if (bsize == 3) {
281 for (bi = 0; bi < dering_count; bi++) {
Jean-Marc Valine0465032016-10-18 15:56:37 -0400282 by = dlist[bi].by;
283 bx = dlist[bi].bx;
Jean-Marc Valincf23aef2016-10-11 17:47:36 -0400284 copy_8x8_16bit(&dst[(by << 3) * dstride + (bx << 3)],
285 dstride,
Jean-Marc Valin82c65fc2016-10-12 18:09:48 -0400286 &src[bi << 2*bsize], 1 << bsize);
Jean-Marc Valincf23aef2016-10-11 17:47:36 -0400287 }
288 } else {
289 for (bi = 0; bi < dering_count; bi++) {
Jean-Marc Valine0465032016-10-18 15:56:37 -0400290 by = dlist[bi].by;
291 bx = dlist[bi].bx;
Jean-Marc Valincf23aef2016-10-11 17:47:36 -0400292 copy_4x4_16bit(&dst[(by << 2) * dstride + (bx << 2)],
293 dstride,
Jean-Marc Valin82c65fc2016-10-12 18:09:48 -0400294 &src[bi << 2*bsize], 1 << bsize);
Jean-Marc Valincf23aef2016-10-11 17:47:36 -0400295 }
296 }
297}
298
Jean-Marc Valinca1eb5d2016-10-13 15:24:39 -0400299void od_dering(int16_t *y, int16_t *in, int xdec,
Yaowu Xu3e90f842016-11-02 08:22:02 -0700300 int dir[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS], int pli,
Jean-Marc Valine0465032016-10-18 15:56:37 -0400301 dering_list *dlist, int dering_count, int threshold,
Jean-Marc Valin2c616e62016-08-23 02:45:43 -0400302 int coeff_shift) {
Jean-Marc Valin3e44bcc2016-10-11 16:53:59 -0400303 int bi;
Yaowu Xu253c0012016-08-15 10:27:19 -0700304 int bx;
305 int by;
Yaowu Xu3e90f842016-11-02 08:22:02 -0700306 int bsize;
Jean-Marc Valina8ce2c92016-10-07 18:10:19 -0400307 int filter2_thresh[OD_DERING_NBLOCKS][OD_DERING_NBLOCKS];
Michael Bebenita7227b652016-10-06 14:27:34 -0700308 od_filter_dering_direction_func filter_dering_direction[OD_DERINGSIZES] = {
Yaowu Xu3e90f842016-11-02 08:22:02 -0700309 od_filter_dering_direction_4x4, od_filter_dering_direction_8x8
Michael Bebenita7227b652016-10-06 14:27:34 -0700310 };
311 od_filter_dering_orthogonal_func filter_dering_orthogonal[OD_DERINGSIZES] = {
Yaowu Xu3e90f842016-11-02 08:22:02 -0700312 od_filter_dering_orthogonal_4x4, od_filter_dering_orthogonal_8x8
Michael Bebenita7227b652016-10-06 14:27:34 -0700313 };
Yaowu Xu3e90f842016-11-02 08:22:02 -0700314 bsize = 3 - xdec;
Yaowu Xu253c0012016-08-15 10:27:19 -0700315 if (pli == 0) {
Jean-Marc Valin3e44bcc2016-10-11 16:53:59 -0400316 for (bi = 0; bi < dering_count; bi++) {
Jean-Marc Valin643902d2016-10-12 17:45:07 -0400317 int32_t var;
Jean-Marc Valine0465032016-10-18 15:56:37 -0400318 by = dlist[bi].by;
319 bx = dlist[bi].bx;
Jean-Marc Valineab77ea2016-10-13 14:18:49 -0400320 dir[by][bx] = od_dir_find8(&in[8 * by * OD_FILT_BSTRIDE + 8 * bx], OD_FILT_BSTRIDE,
Jean-Marc Valin643902d2016-10-12 17:45:07 -0400321 &var, coeff_shift);
Jean-Marc Valin3e44bcc2016-10-11 16:53:59 -0400322 /* Deringing orthogonal to the direction uses a tighter threshold
323 because we want to be conservative. We've presumably already
324 achieved some deringing, so the amount of change is expected
325 to be low. Also, since we might be filtering across an edge, we
326 want to make sure not to blur it. That being said, we might want
327 to be a little bit more aggressive on pure horizontal/vertical
328 since the ringing there tends to be directional, so it doesn't
329 get removed by the directional filtering. */
330 filter2_thresh[by][bx] = (filter_dering_direction[bsize - OD_LOG_BSIZE0])(
Jean-Marc Valin82c65fc2016-10-12 18:09:48 -0400331 &y[bi << 2*bsize], 1 << bsize,
Jean-Marc Valin3e44bcc2016-10-11 16:53:59 -0400332 &in[(by * OD_FILT_BSTRIDE << bsize) + (bx << bsize)],
Jean-Marc Valin643902d2016-10-12 17:45:07 -0400333 od_adjust_thresh(threshold, var), dir[by][bx]);
Yaowu Xu253c0012016-08-15 10:27:19 -0700334 }
clang-format21a0c2c2016-08-18 15:10:22 -0700335 } else {
Jean-Marc Valin3e44bcc2016-10-11 16:53:59 -0400336 for (bi = 0; bi < dering_count; bi++) {
Jean-Marc Valine0465032016-10-18 15:56:37 -0400337 by = dlist[bi].by;
338 bx = dlist[bi].bx;
Jean-Marc Valin3e44bcc2016-10-11 16:53:59 -0400339 filter2_thresh[by][bx] = (filter_dering_direction[bsize - OD_LOG_BSIZE0])(
Jean-Marc Valin82c65fc2016-10-12 18:09:48 -0400340 &y[bi << 2*bsize], 1 << bsize,
Jean-Marc Valin3e44bcc2016-10-11 16:53:59 -0400341 &in[(by * OD_FILT_BSTRIDE << bsize) + (bx << bsize)], threshold,
342 dir[by][bx]);
Yaowu Xu253c0012016-08-15 10:27:19 -0700343 }
344 }
Jean-Marc Valine0465032016-10-18 15:56:37 -0400345 copy_blocks_16bit(in, OD_FILT_BSTRIDE, y, dlist, dering_count,
Jean-Marc Valincf23aef2016-10-11 17:47:36 -0400346 bsize);
Jean-Marc Valin3e44bcc2016-10-11 16:53:59 -0400347 for (bi = 0; bi < dering_count; bi++) {
Jean-Marc Valine0465032016-10-18 15:56:37 -0400348 by = dlist[bi].by;
349 bx = dlist[bi].bx;
Jean-Marc Valin3e44bcc2016-10-11 16:53:59 -0400350 if (filter2_thresh[by][bx] == 0) continue;
351 (filter_dering_orthogonal[bsize - OD_LOG_BSIZE0])(
Jean-Marc Valin82c65fc2016-10-12 18:09:48 -0400352 &y[bi << 2*bsize], 1 << bsize,
Jean-Marc Valin3e44bcc2016-10-11 16:53:59 -0400353 &in[(by * OD_FILT_BSTRIDE << bsize) + (bx << bsize)], filter2_thresh[by][bx],
354 dir[by][bx]);
Yaowu Xu253c0012016-08-15 10:27:19 -0700355 }
356}