/media/libvpx/vp8/common/loopfilter_filters.c

http://github.com/zpao/v8monkey · C · 359 lines · 260 code · 60 blank · 39 comment · 6 complexity · 0a0f942189cbf127f3bb798c34d78862 MD5 · raw file

  1. /*
  2. * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
  3. *
  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.
  9. */
  10. #include <stdlib.h>
  11. #include "loopfilter.h"
  12. #include "onyxc_int.h"
  13. #ifdef __SUNPRO_C
  14. #define __inline inline
  15. #endif
  16. typedef unsigned char uc;
  17. static __inline signed char vp8_signed_char_clamp(int t)
  18. {
  19. t = (t < -128 ? -128 : t);
  20. t = (t > 127 ? 127 : t);
  21. return (signed char) t;
  22. }
  23. /* should we apply any filter at all ( 11111111 yes, 00000000 no) */
  24. static __inline signed char vp8_filter_mask(uc limit, uc blimit,
  25. uc p3, uc p2, uc p1, uc p0,
  26. uc q0, uc q1, uc q2, uc q3)
  27. {
  28. signed char mask = 0;
  29. mask |= (abs(p3 - p2) > limit) * -1;
  30. mask |= (abs(p2 - p1) > limit) * -1;
  31. mask |= (abs(p1 - p0) > limit) * -1;
  32. mask |= (abs(q1 - q0) > limit) * -1;
  33. mask |= (abs(q2 - q1) > limit) * -1;
  34. mask |= (abs(q3 - q2) > limit) * -1;
  35. mask |= (abs(p0 - q0) * 2 + abs(p1 - q1) / 2 > blimit) * -1;
  36. mask = ~mask;
  37. return mask;
  38. }
  39. /* is there high variance internal edge ( 11111111 yes, 00000000 no) */
  40. static __inline signed char vp8_hevmask(uc thresh, uc p1, uc p0, uc q0, uc q1)
  41. {
  42. signed char hev = 0;
  43. hev |= (abs(p1 - p0) > thresh) * -1;
  44. hev |= (abs(q1 - q0) > thresh) * -1;
  45. return hev;
  46. }
  47. static __inline void vp8_filter(signed char mask, uc hev, uc *op1,
  48. uc *op0, uc *oq0, uc *oq1)
  49. {
  50. signed char ps0, qs0;
  51. signed char ps1, qs1;
  52. signed char vp8_filter, Filter1, Filter2;
  53. signed char u;
  54. ps1 = (signed char) * op1 ^ 0x80;
  55. ps0 = (signed char) * op0 ^ 0x80;
  56. qs0 = (signed char) * oq0 ^ 0x80;
  57. qs1 = (signed char) * oq1 ^ 0x80;
  58. /* add outer taps if we have high edge variance */
  59. vp8_filter = vp8_signed_char_clamp(ps1 - qs1);
  60. vp8_filter &= hev;
  61. /* inner taps */
  62. vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (qs0 - ps0));
  63. vp8_filter &= mask;
  64. /* save bottom 3 bits so that we round one side +4 and the other +3
  65. * if it equals 4 we'll set to adjust by -1 to account for the fact
  66. * we'd round 3 the other way
  67. */
  68. Filter1 = vp8_signed_char_clamp(vp8_filter + 4);
  69. Filter2 = vp8_signed_char_clamp(vp8_filter + 3);
  70. Filter1 >>= 3;
  71. Filter2 >>= 3;
  72. u = vp8_signed_char_clamp(qs0 - Filter1);
  73. *oq0 = u ^ 0x80;
  74. u = vp8_signed_char_clamp(ps0 + Filter2);
  75. *op0 = u ^ 0x80;
  76. vp8_filter = Filter1;
  77. /* outer tap adjustments */
  78. vp8_filter += 1;
  79. vp8_filter >>= 1;
  80. vp8_filter &= ~hev;
  81. u = vp8_signed_char_clamp(qs1 - vp8_filter);
  82. *oq1 = u ^ 0x80;
  83. u = vp8_signed_char_clamp(ps1 + vp8_filter);
  84. *op1 = u ^ 0x80;
  85. }
  86. void vp8_loop_filter_horizontal_edge_c
  87. (
  88. unsigned char *s,
  89. int p, /* pitch */
  90. const unsigned char *blimit,
  91. const unsigned char *limit,
  92. const unsigned char *thresh,
  93. int count
  94. )
  95. {
  96. int hev = 0; /* high edge variance */
  97. signed char mask = 0;
  98. int i = 0;
  99. /* loop filter designed to work using chars so that we can make maximum use
  100. * of 8 bit simd instructions.
  101. */
  102. do
  103. {
  104. mask = vp8_filter_mask(limit[0], blimit[0],
  105. s[-4*p], s[-3*p], s[-2*p], s[-1*p],
  106. s[0*p], s[1*p], s[2*p], s[3*p]);
  107. hev = vp8_hevmask(thresh[0], s[-2*p], s[-1*p], s[0*p], s[1*p]);
  108. vp8_filter(mask, hev, s - 2 * p, s - 1 * p, s, s + 1 * p);
  109. ++s;
  110. }
  111. while (++i < count * 8);
  112. }
  113. void vp8_loop_filter_vertical_edge_c
  114. (
  115. unsigned char *s,
  116. int p,
  117. const unsigned char *blimit,
  118. const unsigned char *limit,
  119. const unsigned char *thresh,
  120. int count
  121. )
  122. {
  123. int hev = 0; /* high edge variance */
  124. signed char mask = 0;
  125. int i = 0;
  126. /* loop filter designed to work using chars so that we can make maximum use
  127. * of 8 bit simd instructions.
  128. */
  129. do
  130. {
  131. mask = vp8_filter_mask(limit[0], blimit[0],
  132. s[-4], s[-3], s[-2], s[-1], s[0], s[1], s[2], s[3]);
  133. hev = vp8_hevmask(thresh[0], s[-2], s[-1], s[0], s[1]);
  134. vp8_filter(mask, hev, s - 2, s - 1, s, s + 1);
  135. s += p;
  136. }
  137. while (++i < count * 8);
  138. }
  139. static __inline void vp8_mbfilter(signed char mask, uc hev,
  140. uc *op2, uc *op1, uc *op0, uc *oq0, uc *oq1, uc *oq2)
  141. {
  142. signed char s, u;
  143. signed char vp8_filter, Filter1, Filter2;
  144. signed char ps2 = (signed char) * op2 ^ 0x80;
  145. signed char ps1 = (signed char) * op1 ^ 0x80;
  146. signed char ps0 = (signed char) * op0 ^ 0x80;
  147. signed char qs0 = (signed char) * oq0 ^ 0x80;
  148. signed char qs1 = (signed char) * oq1 ^ 0x80;
  149. signed char qs2 = (signed char) * oq2 ^ 0x80;
  150. /* add outer taps if we have high edge variance */
  151. vp8_filter = vp8_signed_char_clamp(ps1 - qs1);
  152. vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (qs0 - ps0));
  153. vp8_filter &= mask;
  154. Filter2 = vp8_filter;
  155. Filter2 &= hev;
  156. /* save bottom 3 bits so that we round one side +4 and the other +3 */
  157. Filter1 = vp8_signed_char_clamp(Filter2 + 4);
  158. Filter2 = vp8_signed_char_clamp(Filter2 + 3);
  159. Filter1 >>= 3;
  160. Filter2 >>= 3;
  161. qs0 = vp8_signed_char_clamp(qs0 - Filter1);
  162. ps0 = vp8_signed_char_clamp(ps0 + Filter2);
  163. /* only apply wider filter if not high edge variance */
  164. vp8_filter &= ~hev;
  165. Filter2 = vp8_filter;
  166. /* roughly 3/7th difference across boundary */
  167. u = vp8_signed_char_clamp((63 + Filter2 * 27) >> 7);
  168. s = vp8_signed_char_clamp(qs0 - u);
  169. *oq0 = s ^ 0x80;
  170. s = vp8_signed_char_clamp(ps0 + u);
  171. *op0 = s ^ 0x80;
  172. /* roughly 2/7th difference across boundary */
  173. u = vp8_signed_char_clamp((63 + Filter2 * 18) >> 7);
  174. s = vp8_signed_char_clamp(qs1 - u);
  175. *oq1 = s ^ 0x80;
  176. s = vp8_signed_char_clamp(ps1 + u);
  177. *op1 = s ^ 0x80;
  178. /* roughly 1/7th difference across boundary */
  179. u = vp8_signed_char_clamp((63 + Filter2 * 9) >> 7);
  180. s = vp8_signed_char_clamp(qs2 - u);
  181. *oq2 = s ^ 0x80;
  182. s = vp8_signed_char_clamp(ps2 + u);
  183. *op2 = s ^ 0x80;
  184. }
  185. void vp8_mbloop_filter_horizontal_edge_c
  186. (
  187. unsigned char *s,
  188. int p,
  189. const unsigned char *blimit,
  190. const unsigned char *limit,
  191. const unsigned char *thresh,
  192. int count
  193. )
  194. {
  195. signed char hev = 0; /* high edge variance */
  196. signed char mask = 0;
  197. int i = 0;
  198. /* loop filter designed to work using chars so that we can make maximum use
  199. * of 8 bit simd instructions.
  200. */
  201. do
  202. {
  203. mask = vp8_filter_mask(limit[0], blimit[0],
  204. s[-4*p], s[-3*p], s[-2*p], s[-1*p],
  205. s[0*p], s[1*p], s[2*p], s[3*p]);
  206. hev = vp8_hevmask(thresh[0], s[-2*p], s[-1*p], s[0*p], s[1*p]);
  207. vp8_mbfilter(mask, hev, s - 3 * p, s - 2 * p, s - 1 * p, s, s + 1 * p, s + 2 * p);
  208. ++s;
  209. }
  210. while (++i < count * 8);
  211. }
  212. void vp8_mbloop_filter_vertical_edge_c
  213. (
  214. unsigned char *s,
  215. int p,
  216. const unsigned char *blimit,
  217. const unsigned char *limit,
  218. const unsigned char *thresh,
  219. int count
  220. )
  221. {
  222. signed char hev = 0; /* high edge variance */
  223. signed char mask = 0;
  224. int i = 0;
  225. do
  226. {
  227. mask = vp8_filter_mask(limit[0], blimit[0],
  228. s[-4], s[-3], s[-2], s[-1], s[0], s[1], s[2], s[3]);
  229. hev = vp8_hevmask(thresh[0], s[-2], s[-1], s[0], s[1]);
  230. vp8_mbfilter(mask, hev, s - 3, s - 2, s - 1, s, s + 1, s + 2);
  231. s += p;
  232. }
  233. while (++i < count * 8);
  234. }
  235. /* should we apply any filter at all ( 11111111 yes, 00000000 no) */
  236. static __inline signed char vp8_simple_filter_mask(uc blimit, uc p1, uc p0, uc q0, uc q1)
  237. {
  238. /* Why does this cause problems for win32?
  239. * error C2143: syntax error : missing ';' before 'type'
  240. * (void) limit;
  241. */
  242. signed char mask = (abs(p0 - q0) * 2 + abs(p1 - q1) / 2 <= blimit) * -1;
  243. return mask;
  244. }
  245. static __inline void vp8_simple_filter(signed char mask, uc *op1, uc *op0, uc *oq0, uc *oq1)
  246. {
  247. signed char vp8_filter, Filter1, Filter2;
  248. signed char p1 = (signed char) * op1 ^ 0x80;
  249. signed char p0 = (signed char) * op0 ^ 0x80;
  250. signed char q0 = (signed char) * oq0 ^ 0x80;
  251. signed char q1 = (signed char) * oq1 ^ 0x80;
  252. signed char u;
  253. vp8_filter = vp8_signed_char_clamp(p1 - q1);
  254. vp8_filter = vp8_signed_char_clamp(vp8_filter + 3 * (q0 - p0));
  255. vp8_filter &= mask;
  256. /* save bottom 3 bits so that we round one side +4 and the other +3 */
  257. Filter1 = vp8_signed_char_clamp(vp8_filter + 4);
  258. Filter1 >>= 3;
  259. u = vp8_signed_char_clamp(q0 - Filter1);
  260. *oq0 = u ^ 0x80;
  261. Filter2 = vp8_signed_char_clamp(vp8_filter + 3);
  262. Filter2 >>= 3;
  263. u = vp8_signed_char_clamp(p0 + Filter2);
  264. *op0 = u ^ 0x80;
  265. }
  266. void vp8_loop_filter_simple_horizontal_edge_c
  267. (
  268. unsigned char *s,
  269. int p,
  270. const unsigned char *blimit
  271. )
  272. {
  273. signed char mask = 0;
  274. int i = 0;
  275. do
  276. {
  277. mask = vp8_simple_filter_mask(blimit[0], s[-2*p], s[-1*p], s[0*p], s[1*p]);
  278. vp8_simple_filter(mask, s - 2 * p, s - 1 * p, s, s + 1 * p);
  279. ++s;
  280. }
  281. while (++i < 16);
  282. }
  283. void vp8_loop_filter_simple_vertical_edge_c
  284. (
  285. unsigned char *s,
  286. int p,
  287. const unsigned char *blimit
  288. )
  289. {
  290. signed char mask = 0;
  291. int i = 0;
  292. do
  293. {
  294. mask = vp8_simple_filter_mask(blimit[0], s[-2], s[-1], s[0], s[1]);
  295. vp8_simple_filter(mask, s - 2, s - 1, s, s + 1);
  296. s += p;
  297. }
  298. while (++i < 16);
  299. }