2 * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
13 #include "loopfilter.h"
14 #include "onyxc_int.h"
16 typedef unsigned char uc;
18 static signed char vp8_signed_char_clamp(int t)
20 t = (t < -128 ? -128 : t);
21 t = (t > 127 ? 127 : t);
22 return (signed char) t;
26 /* should we apply any filter at all ( 11111111 yes, 00000000 no) */
27 static signed char vp8_filter_mask(uc limit, uc blimit,
28 uc p3, uc p2, uc p1, uc p0,
29 uc q0, uc q1, uc q2, uc q3)
32 mask |= (abs(p3 - p2) > limit);
33 mask |= (abs(p2 - p1) > limit);
34 mask |= (abs(p1 - p0) > limit);
35 mask |= (abs(q1 - q0) > limit);
36 mask |= (abs(q2 - q1) > limit);
37 mask |= (abs(q3 - q2) > limit);
38 mask |= (abs(p0 - q0) * 2 + abs(p1 - q1) / 2 > blimit);
42 /* is there high variance internal edge ( 11111111 yes, 00000000 no) */
43 static signed char vp8_hevmask(uc thresh, uc p1, uc p0, uc q0, uc q1)
46 hev |= (abs(p1 - p0) > thresh) * -1;
47 hev |= (abs(q1 - q0) > thresh) * -1;
51 static void vp8_filter(signed char mask, uc hev, uc *op1,
52 uc *op0, uc *oq0, uc *oq1)
57 signed char vp8_filter, Filter1, Filter2;
60 ps1 = (signed char) * op1 ^ 0x80;
61 ps0 = (signed char) * op0 ^ 0x80;
62 qs0 = (signed char) * oq0 ^ 0x80;
63 qs1 = (signed char) * oq1 ^ 0x80;
65 /* add outer taps if we have high edge variance */
66 vp8_filter = vp8_signed_char_clamp(ps1 - qs1);
70 vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (qs0 - ps0));
73 /* save bottom 3 bits so that we round one side +4 and the other +3
74 * if it equals 4 we'll set to adjust by -1 to account for the fact
75 * we'd round 3 the other way
77 Filter1 = vp8_signed_char_clamp(vp8_filter + 4);
78 Filter2 = vp8_signed_char_clamp(vp8_filter + 3);
81 u = vp8_signed_char_clamp(qs0 - Filter1);
83 u = vp8_signed_char_clamp(ps0 + Filter2);
87 /* outer tap adjustments */
92 u = vp8_signed_char_clamp(qs1 - vp8_filter);
94 u = vp8_signed_char_clamp(ps1 + vp8_filter);
98 void vp8_loop_filter_horizontal_edge_c
102 const unsigned char *blimit,
103 const unsigned char *limit,
104 const unsigned char *thresh,
108 int hev = 0; /* high edge variance */
109 signed char mask = 0;
112 /* loop filter designed to work using chars so that we can make maximum use
113 * of 8 bit simd instructions.
117 mask = vp8_filter_mask(limit[0], blimit[0],
118 s[-4*p], s[-3*p], s[-2*p], s[-1*p],
119 s[0*p], s[1*p], s[2*p], s[3*p]);
121 hev = vp8_hevmask(thresh[0], s[-2*p], s[-1*p], s[0*p], s[1*p]);
123 vp8_filter(mask, hev, s - 2 * p, s - 1 * p, s, s + 1 * p);
127 while (++i < count * 8);
130 void vp8_loop_filter_vertical_edge_c
134 const unsigned char *blimit,
135 const unsigned char *limit,
136 const unsigned char *thresh,
140 int hev = 0; /* high edge variance */
141 signed char mask = 0;
144 /* loop filter designed to work using chars so that we can make maximum use
145 * of 8 bit simd instructions.
149 mask = vp8_filter_mask(limit[0], blimit[0],
150 s[-4], s[-3], s[-2], s[-1], s[0], s[1], s[2], s[3]);
152 hev = vp8_hevmask(thresh[0], s[-2], s[-1], s[0], s[1]);
154 vp8_filter(mask, hev, s - 2, s - 1, s, s + 1);
158 while (++i < count * 8);
161 static void vp8_mbfilter(signed char mask, uc hev,
162 uc *op2, uc *op1, uc *op0, uc *oq0, uc *oq1, uc *oq2)
165 signed char vp8_filter, Filter1, Filter2;
166 signed char ps2 = (signed char) * op2 ^ 0x80;
167 signed char ps1 = (signed char) * op1 ^ 0x80;
168 signed char ps0 = (signed char) * op0 ^ 0x80;
169 signed char qs0 = (signed char) * oq0 ^ 0x80;
170 signed char qs1 = (signed char) * oq1 ^ 0x80;
171 signed char qs2 = (signed char) * oq2 ^ 0x80;
173 /* add outer taps if we have high edge variance */
174 vp8_filter = vp8_signed_char_clamp(ps1 - qs1);
175 vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (qs0 - ps0));
178 Filter2 = vp8_filter;
181 /* save bottom 3 bits so that we round one side +4 and the other +3 */
182 Filter1 = vp8_signed_char_clamp(Filter2 + 4);
183 Filter2 = vp8_signed_char_clamp(Filter2 + 3);
186 qs0 = vp8_signed_char_clamp(qs0 - Filter1);
187 ps0 = vp8_signed_char_clamp(ps0 + Filter2);
190 /* only apply wider filter if not high edge variance */
192 Filter2 = vp8_filter;
194 /* roughly 3/7th difference across boundary */
195 u = vp8_signed_char_clamp((63 + Filter2 * 27) >> 7);
196 s = vp8_signed_char_clamp(qs0 - u);
198 s = vp8_signed_char_clamp(ps0 + u);
201 /* roughly 2/7th difference across boundary */
202 u = vp8_signed_char_clamp((63 + Filter2 * 18) >> 7);
203 s = vp8_signed_char_clamp(qs1 - u);
205 s = vp8_signed_char_clamp(ps1 + u);
208 /* roughly 1/7th difference across boundary */
209 u = vp8_signed_char_clamp((63 + Filter2 * 9) >> 7);
210 s = vp8_signed_char_clamp(qs2 - u);
212 s = vp8_signed_char_clamp(ps2 + u);
216 void vp8_mbloop_filter_horizontal_edge_c
220 const unsigned char *blimit,
221 const unsigned char *limit,
222 const unsigned char *thresh,
226 signed char hev = 0; /* high edge variance */
227 signed char mask = 0;
230 /* loop filter designed to work using chars so that we can make maximum use
231 * of 8 bit simd instructions.
236 mask = vp8_filter_mask(limit[0], blimit[0],
237 s[-4*p], s[-3*p], s[-2*p], s[-1*p],
238 s[0*p], s[1*p], s[2*p], s[3*p]);
240 hev = vp8_hevmask(thresh[0], s[-2*p], s[-1*p], s[0*p], s[1*p]);
242 vp8_mbfilter(mask, hev, s - 3 * p, s - 2 * p, s - 1 * p, s, s + 1 * p, s + 2 * p);
246 while (++i < count * 8);
251 void vp8_mbloop_filter_vertical_edge_c
255 const unsigned char *blimit,
256 const unsigned char *limit,
257 const unsigned char *thresh,
261 signed char hev = 0; /* high edge variance */
262 signed char mask = 0;
268 mask = vp8_filter_mask(limit[0], blimit[0],
269 s[-4], s[-3], s[-2], s[-1], s[0], s[1], s[2], s[3]);
271 hev = vp8_hevmask(thresh[0], s[-2], s[-1], s[0], s[1]);
273 vp8_mbfilter(mask, hev, s - 3, s - 2, s - 1, s, s + 1, s + 2);
277 while (++i < count * 8);
281 /* should we apply any filter at all ( 11111111 yes, 00000000 no) */
282 static signed char vp8_simple_filter_mask(uc blimit, uc p1, uc p0, uc q0, uc q1)
284 /* Why does this cause problems for win32?
285 * error C2143: syntax error : missing ';' before 'type'
288 signed char mask = (abs(p0 - q0) * 2 + abs(p1 - q1) / 2 <= blimit) * -1;
292 static void vp8_simple_filter(signed char mask, uc *op1, uc *op0, uc *oq0, uc *oq1)
294 signed char vp8_filter, Filter1, Filter2;
295 signed char p1 = (signed char) * op1 ^ 0x80;
296 signed char p0 = (signed char) * op0 ^ 0x80;
297 signed char q0 = (signed char) * oq0 ^ 0x80;
298 signed char q1 = (signed char) * oq1 ^ 0x80;
301 vp8_filter = vp8_signed_char_clamp(p1 - q1);
302 vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (q0 - p0));
305 /* save bottom 3 bits so that we round one side +4 and the other +3 */
306 Filter1 = vp8_signed_char_clamp(vp8_filter + 4);
308 u = vp8_signed_char_clamp(q0 - Filter1);
311 Filter2 = vp8_signed_char_clamp(vp8_filter + 3);
313 u = vp8_signed_char_clamp(p0 + Filter2);
317 void vp8_loop_filter_simple_horizontal_edge_c
321 const unsigned char *blimit
324 signed char mask = 0;
329 mask = vp8_simple_filter_mask(blimit[0], s[-2*p], s[-1*p], s[0*p], s[1*p]);
330 vp8_simple_filter(mask, s - 2 * p, s - 1 * p, s, s + 1 * p);
336 void vp8_loop_filter_simple_vertical_edge_c
340 const unsigned char *blimit
343 signed char mask = 0;
348 mask = vp8_simple_filter_mask(blimit[0], s[-2], s[-1], s[0], s[1]);
349 vp8_simple_filter(mask, s - 2, s - 1, s, s + 1);
356 /* Horizontal MB filtering */
357 void vp8_loop_filter_mbh_c(unsigned char *y_ptr, unsigned char *u_ptr,
358 unsigned char *v_ptr, int y_stride, int uv_stride,
359 loop_filter_info *lfi)
361 vp8_mbloop_filter_horizontal_edge_c(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
364 vp8_mbloop_filter_horizontal_edge_c(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
367 vp8_mbloop_filter_horizontal_edge_c(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
370 /* Vertical MB Filtering */
371 void vp8_loop_filter_mbv_c(unsigned char *y_ptr, unsigned char *u_ptr,
372 unsigned char *v_ptr, int y_stride, int uv_stride,
373 loop_filter_info *lfi)
375 vp8_mbloop_filter_vertical_edge_c(y_ptr, y_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 2);
378 vp8_mbloop_filter_vertical_edge_c(u_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
381 vp8_mbloop_filter_vertical_edge_c(v_ptr, uv_stride, lfi->mblim, lfi->lim, lfi->hev_thr, 1);
384 /* Horizontal B Filtering */
385 void vp8_loop_filter_bh_c(unsigned char *y_ptr, unsigned char *u_ptr,
386 unsigned char *v_ptr, int y_stride, int uv_stride,
387 loop_filter_info *lfi)
389 vp8_loop_filter_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
390 vp8_loop_filter_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
391 vp8_loop_filter_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
394 vp8_loop_filter_horizontal_edge_c(u_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
397 vp8_loop_filter_horizontal_edge_c(v_ptr + 4 * uv_stride, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
400 void vp8_loop_filter_bhs_c(unsigned char *y_ptr, int y_stride,
401 const unsigned char *blimit)
403 vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 4 * y_stride, y_stride, blimit);
404 vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 8 * y_stride, y_stride, blimit);
405 vp8_loop_filter_simple_horizontal_edge_c(y_ptr + 12 * y_stride, y_stride, blimit);
408 /* Vertical B Filtering */
409 void vp8_loop_filter_bv_c(unsigned char *y_ptr, unsigned char *u_ptr,
410 unsigned char *v_ptr, int y_stride, int uv_stride,
411 loop_filter_info *lfi)
413 vp8_loop_filter_vertical_edge_c(y_ptr + 4, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
414 vp8_loop_filter_vertical_edge_c(y_ptr + 8, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
415 vp8_loop_filter_vertical_edge_c(y_ptr + 12, y_stride, lfi->blim, lfi->lim, lfi->hev_thr, 2);
418 vp8_loop_filter_vertical_edge_c(u_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
421 vp8_loop_filter_vertical_edge_c(v_ptr + 4, uv_stride, lfi->blim, lfi->lim, lfi->hev_thr, 1);
424 void vp8_loop_filter_bvs_c(unsigned char *y_ptr, int y_stride,
425 const unsigned char *blimit)
427 vp8_loop_filter_simple_vertical_edge_c(y_ptr + 4, y_stride, blimit);
428 vp8_loop_filter_simple_vertical_edge_c(y_ptr + 8, y_stride, blimit);
429 vp8_loop_filter_simple_vertical_edge_c(y_ptr + 12, y_stride, blimit);