bilinearpredict_neon.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. /*
  2. * Copyright (c) 2014 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 <arm_neon.h>
  11. static const uint8_t bifilter4_coeff[8][2] = {
  12. {128, 0},
  13. {112, 16},
  14. { 96, 32},
  15. { 80, 48},
  16. { 64, 64},
  17. { 48, 80},
  18. { 32, 96},
  19. { 16, 112}
  20. };
  21. void vp8_bilinear_predict8x4_neon(
  22. unsigned char *src_ptr,
  23. int src_pixels_per_line,
  24. int xoffset,
  25. int yoffset,
  26. unsigned char *dst_ptr,
  27. int dst_pitch) {
  28. uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8;
  29. uint8x8_t d7u8, d9u8, d11u8, d22u8, d23u8, d24u8, d25u8, d26u8;
  30. uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8;
  31. uint16x8_t q1u16, q2u16, q3u16, q4u16;
  32. uint16x8_t q6u16, q7u16, q8u16, q9u16, q10u16;
  33. if (xoffset == 0) { // skip_1stpass_filter
  34. d22u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  35. d23u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  36. d24u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  37. d25u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  38. d26u8 = vld1_u8(src_ptr);
  39. } else {
  40. q1u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  41. q2u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  42. q3u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  43. q4u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  44. q5u8 = vld1q_u8(src_ptr);
  45. d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
  46. d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
  47. q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
  48. q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
  49. q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
  50. q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
  51. q10u16 = vmull_u8(vget_low_u8(q5u8), d0u8);
  52. d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
  53. d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
  54. d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
  55. d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
  56. d11u8 = vext_u8(vget_low_u8(q5u8), vget_high_u8(q5u8), 1);
  57. q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
  58. q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
  59. q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
  60. q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
  61. q10u16 = vmlal_u8(q10u16, d11u8, d1u8);
  62. d22u8 = vqrshrn_n_u16(q6u16, 7);
  63. d23u8 = vqrshrn_n_u16(q7u16, 7);
  64. d24u8 = vqrshrn_n_u16(q8u16, 7);
  65. d25u8 = vqrshrn_n_u16(q9u16, 7);
  66. d26u8 = vqrshrn_n_u16(q10u16, 7);
  67. }
  68. // secondpass_filter
  69. if (yoffset == 0) { // skip_2ndpass_filter
  70. vst1_u8((uint8_t *)dst_ptr, d22u8); dst_ptr += dst_pitch;
  71. vst1_u8((uint8_t *)dst_ptr, d23u8); dst_ptr += dst_pitch;
  72. vst1_u8((uint8_t *)dst_ptr, d24u8); dst_ptr += dst_pitch;
  73. vst1_u8((uint8_t *)dst_ptr, d25u8);
  74. } else {
  75. d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
  76. d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
  77. q1u16 = vmull_u8(d22u8, d0u8);
  78. q2u16 = vmull_u8(d23u8, d0u8);
  79. q3u16 = vmull_u8(d24u8, d0u8);
  80. q4u16 = vmull_u8(d25u8, d0u8);
  81. q1u16 = vmlal_u8(q1u16, d23u8, d1u8);
  82. q2u16 = vmlal_u8(q2u16, d24u8, d1u8);
  83. q3u16 = vmlal_u8(q3u16, d25u8, d1u8);
  84. q4u16 = vmlal_u8(q4u16, d26u8, d1u8);
  85. d2u8 = vqrshrn_n_u16(q1u16, 7);
  86. d3u8 = vqrshrn_n_u16(q2u16, 7);
  87. d4u8 = vqrshrn_n_u16(q3u16, 7);
  88. d5u8 = vqrshrn_n_u16(q4u16, 7);
  89. vst1_u8((uint8_t *)dst_ptr, d2u8); dst_ptr += dst_pitch;
  90. vst1_u8((uint8_t *)dst_ptr, d3u8); dst_ptr += dst_pitch;
  91. vst1_u8((uint8_t *)dst_ptr, d4u8); dst_ptr += dst_pitch;
  92. vst1_u8((uint8_t *)dst_ptr, d5u8);
  93. }
  94. return;
  95. }
  96. void vp8_bilinear_predict8x8_neon(
  97. unsigned char *src_ptr,
  98. int src_pixels_per_line,
  99. int xoffset,
  100. int yoffset,
  101. unsigned char *dst_ptr,
  102. int dst_pitch) {
  103. uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8, d8u8, d9u8, d11u8;
  104. uint8x8_t d22u8, d23u8, d24u8, d25u8, d26u8, d27u8, d28u8, d29u8, d30u8;
  105. uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8;
  106. uint16x8_t q1u16, q2u16, q3u16, q4u16, q5u16;
  107. uint16x8_t q6u16, q7u16, q8u16, q9u16, q10u16;
  108. if (xoffset == 0) { // skip_1stpass_filter
  109. d22u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  110. d23u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  111. d24u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  112. d25u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  113. d26u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  114. d27u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  115. d28u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  116. d29u8 = vld1_u8(src_ptr); src_ptr += src_pixels_per_line;
  117. d30u8 = vld1_u8(src_ptr);
  118. } else {
  119. q1u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  120. q2u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  121. q3u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  122. q4u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  123. d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
  124. d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
  125. q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
  126. q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
  127. q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
  128. q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
  129. d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
  130. d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
  131. d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
  132. d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
  133. q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
  134. q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
  135. q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
  136. q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
  137. d22u8 = vqrshrn_n_u16(q6u16, 7);
  138. d23u8 = vqrshrn_n_u16(q7u16, 7);
  139. d24u8 = vqrshrn_n_u16(q8u16, 7);
  140. d25u8 = vqrshrn_n_u16(q9u16, 7);
  141. // first_pass filtering on the rest 5-line data
  142. q1u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  143. q2u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  144. q3u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  145. q4u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  146. q5u8 = vld1q_u8(src_ptr);
  147. q6u16 = vmull_u8(vget_low_u8(q1u8), d0u8);
  148. q7u16 = vmull_u8(vget_low_u8(q2u8), d0u8);
  149. q8u16 = vmull_u8(vget_low_u8(q3u8), d0u8);
  150. q9u16 = vmull_u8(vget_low_u8(q4u8), d0u8);
  151. q10u16 = vmull_u8(vget_low_u8(q5u8), d0u8);
  152. d3u8 = vext_u8(vget_low_u8(q1u8), vget_high_u8(q1u8), 1);
  153. d5u8 = vext_u8(vget_low_u8(q2u8), vget_high_u8(q2u8), 1);
  154. d7u8 = vext_u8(vget_low_u8(q3u8), vget_high_u8(q3u8), 1);
  155. d9u8 = vext_u8(vget_low_u8(q4u8), vget_high_u8(q4u8), 1);
  156. d11u8 = vext_u8(vget_low_u8(q5u8), vget_high_u8(q5u8), 1);
  157. q6u16 = vmlal_u8(q6u16, d3u8, d1u8);
  158. q7u16 = vmlal_u8(q7u16, d5u8, d1u8);
  159. q8u16 = vmlal_u8(q8u16, d7u8, d1u8);
  160. q9u16 = vmlal_u8(q9u16, d9u8, d1u8);
  161. q10u16 = vmlal_u8(q10u16, d11u8, d1u8);
  162. d26u8 = vqrshrn_n_u16(q6u16, 7);
  163. d27u8 = vqrshrn_n_u16(q7u16, 7);
  164. d28u8 = vqrshrn_n_u16(q8u16, 7);
  165. d29u8 = vqrshrn_n_u16(q9u16, 7);
  166. d30u8 = vqrshrn_n_u16(q10u16, 7);
  167. }
  168. // secondpass_filter
  169. if (yoffset == 0) { // skip_2ndpass_filter
  170. vst1_u8((uint8_t *)dst_ptr, d22u8); dst_ptr += dst_pitch;
  171. vst1_u8((uint8_t *)dst_ptr, d23u8); dst_ptr += dst_pitch;
  172. vst1_u8((uint8_t *)dst_ptr, d24u8); dst_ptr += dst_pitch;
  173. vst1_u8((uint8_t *)dst_ptr, d25u8); dst_ptr += dst_pitch;
  174. vst1_u8((uint8_t *)dst_ptr, d26u8); dst_ptr += dst_pitch;
  175. vst1_u8((uint8_t *)dst_ptr, d27u8); dst_ptr += dst_pitch;
  176. vst1_u8((uint8_t *)dst_ptr, d28u8); dst_ptr += dst_pitch;
  177. vst1_u8((uint8_t *)dst_ptr, d29u8);
  178. } else {
  179. d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
  180. d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
  181. q1u16 = vmull_u8(d22u8, d0u8);
  182. q2u16 = vmull_u8(d23u8, d0u8);
  183. q3u16 = vmull_u8(d24u8, d0u8);
  184. q4u16 = vmull_u8(d25u8, d0u8);
  185. q5u16 = vmull_u8(d26u8, d0u8);
  186. q6u16 = vmull_u8(d27u8, d0u8);
  187. q7u16 = vmull_u8(d28u8, d0u8);
  188. q8u16 = vmull_u8(d29u8, d0u8);
  189. q1u16 = vmlal_u8(q1u16, d23u8, d1u8);
  190. q2u16 = vmlal_u8(q2u16, d24u8, d1u8);
  191. q3u16 = vmlal_u8(q3u16, d25u8, d1u8);
  192. q4u16 = vmlal_u8(q4u16, d26u8, d1u8);
  193. q5u16 = vmlal_u8(q5u16, d27u8, d1u8);
  194. q6u16 = vmlal_u8(q6u16, d28u8, d1u8);
  195. q7u16 = vmlal_u8(q7u16, d29u8, d1u8);
  196. q8u16 = vmlal_u8(q8u16, d30u8, d1u8);
  197. d2u8 = vqrshrn_n_u16(q1u16, 7);
  198. d3u8 = vqrshrn_n_u16(q2u16, 7);
  199. d4u8 = vqrshrn_n_u16(q3u16, 7);
  200. d5u8 = vqrshrn_n_u16(q4u16, 7);
  201. d6u8 = vqrshrn_n_u16(q5u16, 7);
  202. d7u8 = vqrshrn_n_u16(q6u16, 7);
  203. d8u8 = vqrshrn_n_u16(q7u16, 7);
  204. d9u8 = vqrshrn_n_u16(q8u16, 7);
  205. vst1_u8((uint8_t *)dst_ptr, d2u8); dst_ptr += dst_pitch;
  206. vst1_u8((uint8_t *)dst_ptr, d3u8); dst_ptr += dst_pitch;
  207. vst1_u8((uint8_t *)dst_ptr, d4u8); dst_ptr += dst_pitch;
  208. vst1_u8((uint8_t *)dst_ptr, d5u8); dst_ptr += dst_pitch;
  209. vst1_u8((uint8_t *)dst_ptr, d6u8); dst_ptr += dst_pitch;
  210. vst1_u8((uint8_t *)dst_ptr, d7u8); dst_ptr += dst_pitch;
  211. vst1_u8((uint8_t *)dst_ptr, d8u8); dst_ptr += dst_pitch;
  212. vst1_u8((uint8_t *)dst_ptr, d9u8);
  213. }
  214. return;
  215. }
  216. void vp8_bilinear_predict16x16_neon(
  217. unsigned char *src_ptr,
  218. int src_pixels_per_line,
  219. int xoffset,
  220. int yoffset,
  221. unsigned char *dst_ptr,
  222. int dst_pitch) {
  223. int i;
  224. unsigned char tmp[272];
  225. unsigned char *tmpp;
  226. uint8x8_t d0u8, d1u8, d2u8, d3u8, d4u8, d5u8, d6u8, d7u8, d8u8, d9u8;
  227. uint8x8_t d10u8, d11u8, d12u8, d13u8, d14u8, d15u8, d16u8, d17u8, d18u8;
  228. uint8x8_t d19u8, d20u8, d21u8;
  229. uint8x16_t q1u8, q2u8, q3u8, q4u8, q5u8, q6u8, q7u8, q8u8, q9u8, q10u8;
  230. uint8x16_t q11u8, q12u8, q13u8, q14u8, q15u8;
  231. uint16x8_t q1u16, q2u16, q3u16, q4u16, q5u16, q6u16, q7u16, q8u16;
  232. uint16x8_t q9u16, q10u16, q11u16, q12u16, q13u16, q14u16;
  233. if (xoffset == 0) { // secondpass_bfilter16x16_only
  234. d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
  235. d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
  236. q11u8 = vld1q_u8(src_ptr);
  237. src_ptr += src_pixels_per_line;
  238. for (i = 4; i > 0; i--) {
  239. q12u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  240. q13u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  241. q14u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  242. q15u8 = vld1q_u8(src_ptr); src_ptr += src_pixels_per_line;
  243. q1u16 = vmull_u8(vget_low_u8(q11u8), d0u8);
  244. q2u16 = vmull_u8(vget_high_u8(q11u8), d0u8);
  245. q3u16 = vmull_u8(vget_low_u8(q12u8), d0u8);
  246. q4u16 = vmull_u8(vget_high_u8(q12u8), d0u8);
  247. q5u16 = vmull_u8(vget_low_u8(q13u8), d0u8);
  248. q6u16 = vmull_u8(vget_high_u8(q13u8), d0u8);
  249. q7u16 = vmull_u8(vget_low_u8(q14u8), d0u8);
  250. q8u16 = vmull_u8(vget_high_u8(q14u8), d0u8);
  251. q1u16 = vmlal_u8(q1u16, vget_low_u8(q12u8), d1u8);
  252. q2u16 = vmlal_u8(q2u16, vget_high_u8(q12u8), d1u8);
  253. q3u16 = vmlal_u8(q3u16, vget_low_u8(q13u8), d1u8);
  254. q4u16 = vmlal_u8(q4u16, vget_high_u8(q13u8), d1u8);
  255. q5u16 = vmlal_u8(q5u16, vget_low_u8(q14u8), d1u8);
  256. q6u16 = vmlal_u8(q6u16, vget_high_u8(q14u8), d1u8);
  257. q7u16 = vmlal_u8(q7u16, vget_low_u8(q15u8), d1u8);
  258. q8u16 = vmlal_u8(q8u16, vget_high_u8(q15u8), d1u8);
  259. d2u8 = vqrshrn_n_u16(q1u16, 7);
  260. d3u8 = vqrshrn_n_u16(q2u16, 7);
  261. d4u8 = vqrshrn_n_u16(q3u16, 7);
  262. d5u8 = vqrshrn_n_u16(q4u16, 7);
  263. d6u8 = vqrshrn_n_u16(q5u16, 7);
  264. d7u8 = vqrshrn_n_u16(q6u16, 7);
  265. d8u8 = vqrshrn_n_u16(q7u16, 7);
  266. d9u8 = vqrshrn_n_u16(q8u16, 7);
  267. q1u8 = vcombine_u8(d2u8, d3u8);
  268. q2u8 = vcombine_u8(d4u8, d5u8);
  269. q3u8 = vcombine_u8(d6u8, d7u8);
  270. q4u8 = vcombine_u8(d8u8, d9u8);
  271. q11u8 = q15u8;
  272. vst1q_u8((uint8_t *)dst_ptr, q1u8); dst_ptr += dst_pitch;
  273. vst1q_u8((uint8_t *)dst_ptr, q2u8); dst_ptr += dst_pitch;
  274. vst1q_u8((uint8_t *)dst_ptr, q3u8); dst_ptr += dst_pitch;
  275. vst1q_u8((uint8_t *)dst_ptr, q4u8); dst_ptr += dst_pitch;
  276. }
  277. return;
  278. }
  279. if (yoffset == 0) { // firstpass_bfilter16x16_only
  280. d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
  281. d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
  282. for (i = 4; i > 0 ; i--) {
  283. d2u8 = vld1_u8(src_ptr);
  284. d3u8 = vld1_u8(src_ptr + 8);
  285. d4u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  286. d5u8 = vld1_u8(src_ptr);
  287. d6u8 = vld1_u8(src_ptr + 8);
  288. d7u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  289. d8u8 = vld1_u8(src_ptr);
  290. d9u8 = vld1_u8(src_ptr + 8);
  291. d10u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  292. d11u8 = vld1_u8(src_ptr);
  293. d12u8 = vld1_u8(src_ptr + 8);
  294. d13u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  295. q7u16 = vmull_u8(d2u8, d0u8);
  296. q8u16 = vmull_u8(d3u8, d0u8);
  297. q9u16 = vmull_u8(d5u8, d0u8);
  298. q10u16 = vmull_u8(d6u8, d0u8);
  299. q11u16 = vmull_u8(d8u8, d0u8);
  300. q12u16 = vmull_u8(d9u8, d0u8);
  301. q13u16 = vmull_u8(d11u8, d0u8);
  302. q14u16 = vmull_u8(d12u8, d0u8);
  303. d2u8 = vext_u8(d2u8, d3u8, 1);
  304. d5u8 = vext_u8(d5u8, d6u8, 1);
  305. d8u8 = vext_u8(d8u8, d9u8, 1);
  306. d11u8 = vext_u8(d11u8, d12u8, 1);
  307. q7u16 = vmlal_u8(q7u16, d2u8, d1u8);
  308. q9u16 = vmlal_u8(q9u16, d5u8, d1u8);
  309. q11u16 = vmlal_u8(q11u16, d8u8, d1u8);
  310. q13u16 = vmlal_u8(q13u16, d11u8, d1u8);
  311. d3u8 = vext_u8(d3u8, d4u8, 1);
  312. d6u8 = vext_u8(d6u8, d7u8, 1);
  313. d9u8 = vext_u8(d9u8, d10u8, 1);
  314. d12u8 = vext_u8(d12u8, d13u8, 1);
  315. q8u16 = vmlal_u8(q8u16, d3u8, d1u8);
  316. q10u16 = vmlal_u8(q10u16, d6u8, d1u8);
  317. q12u16 = vmlal_u8(q12u16, d9u8, d1u8);
  318. q14u16 = vmlal_u8(q14u16, d12u8, d1u8);
  319. d14u8 = vqrshrn_n_u16(q7u16, 7);
  320. d15u8 = vqrshrn_n_u16(q8u16, 7);
  321. d16u8 = vqrshrn_n_u16(q9u16, 7);
  322. d17u8 = vqrshrn_n_u16(q10u16, 7);
  323. d18u8 = vqrshrn_n_u16(q11u16, 7);
  324. d19u8 = vqrshrn_n_u16(q12u16, 7);
  325. d20u8 = vqrshrn_n_u16(q13u16, 7);
  326. d21u8 = vqrshrn_n_u16(q14u16, 7);
  327. q7u8 = vcombine_u8(d14u8, d15u8);
  328. q8u8 = vcombine_u8(d16u8, d17u8);
  329. q9u8 = vcombine_u8(d18u8, d19u8);
  330. q10u8 =vcombine_u8(d20u8, d21u8);
  331. vst1q_u8((uint8_t *)dst_ptr, q7u8); dst_ptr += dst_pitch;
  332. vst1q_u8((uint8_t *)dst_ptr, q8u8); dst_ptr += dst_pitch;
  333. vst1q_u8((uint8_t *)dst_ptr, q9u8); dst_ptr += dst_pitch;
  334. vst1q_u8((uint8_t *)dst_ptr, q10u8); dst_ptr += dst_pitch;
  335. }
  336. return;
  337. }
  338. d0u8 = vdup_n_u8(bifilter4_coeff[xoffset][0]);
  339. d1u8 = vdup_n_u8(bifilter4_coeff[xoffset][1]);
  340. d2u8 = vld1_u8(src_ptr);
  341. d3u8 = vld1_u8(src_ptr + 8);
  342. d4u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  343. d5u8 = vld1_u8(src_ptr);
  344. d6u8 = vld1_u8(src_ptr + 8);
  345. d7u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  346. d8u8 = vld1_u8(src_ptr);
  347. d9u8 = vld1_u8(src_ptr + 8);
  348. d10u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  349. d11u8 = vld1_u8(src_ptr);
  350. d12u8 = vld1_u8(src_ptr + 8);
  351. d13u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  352. // First Pass: output_height lines x output_width columns (17x16)
  353. tmpp = tmp;
  354. for (i = 3; i > 0; i--) {
  355. q7u16 = vmull_u8(d2u8, d0u8);
  356. q8u16 = vmull_u8(d3u8, d0u8);
  357. q9u16 = vmull_u8(d5u8, d0u8);
  358. q10u16 = vmull_u8(d6u8, d0u8);
  359. q11u16 = vmull_u8(d8u8, d0u8);
  360. q12u16 = vmull_u8(d9u8, d0u8);
  361. q13u16 = vmull_u8(d11u8, d0u8);
  362. q14u16 = vmull_u8(d12u8, d0u8);
  363. d2u8 = vext_u8(d2u8, d3u8, 1);
  364. d5u8 = vext_u8(d5u8, d6u8, 1);
  365. d8u8 = vext_u8(d8u8, d9u8, 1);
  366. d11u8 = vext_u8(d11u8, d12u8, 1);
  367. q7u16 = vmlal_u8(q7u16, d2u8, d1u8);
  368. q9u16 = vmlal_u8(q9u16, d5u8, d1u8);
  369. q11u16 = vmlal_u8(q11u16, d8u8, d1u8);
  370. q13u16 = vmlal_u8(q13u16, d11u8, d1u8);
  371. d3u8 = vext_u8(d3u8, d4u8, 1);
  372. d6u8 = vext_u8(d6u8, d7u8, 1);
  373. d9u8 = vext_u8(d9u8, d10u8, 1);
  374. d12u8 = vext_u8(d12u8, d13u8, 1);
  375. q8u16 = vmlal_u8(q8u16, d3u8, d1u8);
  376. q10u16 = vmlal_u8(q10u16, d6u8, d1u8);
  377. q12u16 = vmlal_u8(q12u16, d9u8, d1u8);
  378. q14u16 = vmlal_u8(q14u16, d12u8, d1u8);
  379. d14u8 = vqrshrn_n_u16(q7u16, 7);
  380. d15u8 = vqrshrn_n_u16(q8u16, 7);
  381. d16u8 = vqrshrn_n_u16(q9u16, 7);
  382. d17u8 = vqrshrn_n_u16(q10u16, 7);
  383. d18u8 = vqrshrn_n_u16(q11u16, 7);
  384. d19u8 = vqrshrn_n_u16(q12u16, 7);
  385. d20u8 = vqrshrn_n_u16(q13u16, 7);
  386. d21u8 = vqrshrn_n_u16(q14u16, 7);
  387. d2u8 = vld1_u8(src_ptr);
  388. d3u8 = vld1_u8(src_ptr + 8);
  389. d4u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  390. d5u8 = vld1_u8(src_ptr);
  391. d6u8 = vld1_u8(src_ptr + 8);
  392. d7u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  393. d8u8 = vld1_u8(src_ptr);
  394. d9u8 = vld1_u8(src_ptr + 8);
  395. d10u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  396. d11u8 = vld1_u8(src_ptr);
  397. d12u8 = vld1_u8(src_ptr + 8);
  398. d13u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  399. q7u8 = vcombine_u8(d14u8, d15u8);
  400. q8u8 = vcombine_u8(d16u8, d17u8);
  401. q9u8 = vcombine_u8(d18u8, d19u8);
  402. q10u8 = vcombine_u8(d20u8, d21u8);
  403. vst1q_u8((uint8_t *)tmpp, q7u8); tmpp += 16;
  404. vst1q_u8((uint8_t *)tmpp, q8u8); tmpp += 16;
  405. vst1q_u8((uint8_t *)tmpp, q9u8); tmpp += 16;
  406. vst1q_u8((uint8_t *)tmpp, q10u8); tmpp += 16;
  407. }
  408. // First-pass filtering for rest 5 lines
  409. d14u8 = vld1_u8(src_ptr);
  410. d15u8 = vld1_u8(src_ptr + 8);
  411. d16u8 = vld1_u8(src_ptr + 16); src_ptr += src_pixels_per_line;
  412. q9u16 = vmull_u8(d2u8, d0u8);
  413. q10u16 = vmull_u8(d3u8, d0u8);
  414. q11u16 = vmull_u8(d5u8, d0u8);
  415. q12u16 = vmull_u8(d6u8, d0u8);
  416. q13u16 = vmull_u8(d8u8, d0u8);
  417. q14u16 = vmull_u8(d9u8, d0u8);
  418. d2u8 = vext_u8(d2u8, d3u8, 1);
  419. d5u8 = vext_u8(d5u8, d6u8, 1);
  420. d8u8 = vext_u8(d8u8, d9u8, 1);
  421. q9u16 = vmlal_u8(q9u16, d2u8, d1u8);
  422. q11u16 = vmlal_u8(q11u16, d5u8, d1u8);
  423. q13u16 = vmlal_u8(q13u16, d8u8, d1u8);
  424. d3u8 = vext_u8(d3u8, d4u8, 1);
  425. d6u8 = vext_u8(d6u8, d7u8, 1);
  426. d9u8 = vext_u8(d9u8, d10u8, 1);
  427. q10u16 = vmlal_u8(q10u16, d3u8, d1u8);
  428. q12u16 = vmlal_u8(q12u16, d6u8, d1u8);
  429. q14u16 = vmlal_u8(q14u16, d9u8, d1u8);
  430. q1u16 = vmull_u8(d11u8, d0u8);
  431. q2u16 = vmull_u8(d12u8, d0u8);
  432. q3u16 = vmull_u8(d14u8, d0u8);
  433. q4u16 = vmull_u8(d15u8, d0u8);
  434. d11u8 = vext_u8(d11u8, d12u8, 1);
  435. d14u8 = vext_u8(d14u8, d15u8, 1);
  436. q1u16 = vmlal_u8(q1u16, d11u8, d1u8);
  437. q3u16 = vmlal_u8(q3u16, d14u8, d1u8);
  438. d12u8 = vext_u8(d12u8, d13u8, 1);
  439. d15u8 = vext_u8(d15u8, d16u8, 1);
  440. q2u16 = vmlal_u8(q2u16, d12u8, d1u8);
  441. q4u16 = vmlal_u8(q4u16, d15u8, d1u8);
  442. d10u8 = vqrshrn_n_u16(q9u16, 7);
  443. d11u8 = vqrshrn_n_u16(q10u16, 7);
  444. d12u8 = vqrshrn_n_u16(q11u16, 7);
  445. d13u8 = vqrshrn_n_u16(q12u16, 7);
  446. d14u8 = vqrshrn_n_u16(q13u16, 7);
  447. d15u8 = vqrshrn_n_u16(q14u16, 7);
  448. d16u8 = vqrshrn_n_u16(q1u16, 7);
  449. d17u8 = vqrshrn_n_u16(q2u16, 7);
  450. d18u8 = vqrshrn_n_u16(q3u16, 7);
  451. d19u8 = vqrshrn_n_u16(q4u16, 7);
  452. q5u8 = vcombine_u8(d10u8, d11u8);
  453. q6u8 = vcombine_u8(d12u8, d13u8);
  454. q7u8 = vcombine_u8(d14u8, d15u8);
  455. q8u8 = vcombine_u8(d16u8, d17u8);
  456. q9u8 = vcombine_u8(d18u8, d19u8);
  457. vst1q_u8((uint8_t *)tmpp, q5u8); tmpp += 16;
  458. vst1q_u8((uint8_t *)tmpp, q6u8); tmpp += 16;
  459. vst1q_u8((uint8_t *)tmpp, q7u8); tmpp += 16;
  460. vst1q_u8((uint8_t *)tmpp, q8u8); tmpp += 16;
  461. vst1q_u8((uint8_t *)tmpp, q9u8);
  462. // secondpass_filter
  463. d0u8 = vdup_n_u8(bifilter4_coeff[yoffset][0]);
  464. d1u8 = vdup_n_u8(bifilter4_coeff[yoffset][1]);
  465. tmpp = tmp;
  466. q11u8 = vld1q_u8(tmpp);
  467. tmpp += 16;
  468. for (i = 4; i > 0; i--) {
  469. q12u8 = vld1q_u8(tmpp); tmpp += 16;
  470. q13u8 = vld1q_u8(tmpp); tmpp += 16;
  471. q14u8 = vld1q_u8(tmpp); tmpp += 16;
  472. q15u8 = vld1q_u8(tmpp); tmpp += 16;
  473. q1u16 = vmull_u8(vget_low_u8(q11u8), d0u8);
  474. q2u16 = vmull_u8(vget_high_u8(q11u8), d0u8);
  475. q3u16 = vmull_u8(vget_low_u8(q12u8), d0u8);
  476. q4u16 = vmull_u8(vget_high_u8(q12u8), d0u8);
  477. q5u16 = vmull_u8(vget_low_u8(q13u8), d0u8);
  478. q6u16 = vmull_u8(vget_high_u8(q13u8), d0u8);
  479. q7u16 = vmull_u8(vget_low_u8(q14u8), d0u8);
  480. q8u16 = vmull_u8(vget_high_u8(q14u8), d0u8);
  481. q1u16 = vmlal_u8(q1u16, vget_low_u8(q12u8), d1u8);
  482. q2u16 = vmlal_u8(q2u16, vget_high_u8(q12u8), d1u8);
  483. q3u16 = vmlal_u8(q3u16, vget_low_u8(q13u8), d1u8);
  484. q4u16 = vmlal_u8(q4u16, vget_high_u8(q13u8), d1u8);
  485. q5u16 = vmlal_u8(q5u16, vget_low_u8(q14u8), d1u8);
  486. q6u16 = vmlal_u8(q6u16, vget_high_u8(q14u8), d1u8);
  487. q7u16 = vmlal_u8(q7u16, vget_low_u8(q15u8), d1u8);
  488. q8u16 = vmlal_u8(q8u16, vget_high_u8(q15u8), d1u8);
  489. d2u8 = vqrshrn_n_u16(q1u16, 7);
  490. d3u8 = vqrshrn_n_u16(q2u16, 7);
  491. d4u8 = vqrshrn_n_u16(q3u16, 7);
  492. d5u8 = vqrshrn_n_u16(q4u16, 7);
  493. d6u8 = vqrshrn_n_u16(q5u16, 7);
  494. d7u8 = vqrshrn_n_u16(q6u16, 7);
  495. d8u8 = vqrshrn_n_u16(q7u16, 7);
  496. d9u8 = vqrshrn_n_u16(q8u16, 7);
  497. q1u8 = vcombine_u8(d2u8, d3u8);
  498. q2u8 = vcombine_u8(d4u8, d5u8);
  499. q3u8 = vcombine_u8(d6u8, d7u8);
  500. q4u8 = vcombine_u8(d8u8, d9u8);
  501. q11u8 = q15u8;
  502. vst1q_u8((uint8_t *)dst_ptr, q1u8); dst_ptr += dst_pitch;
  503. vst1q_u8((uint8_t *)dst_ptr, q2u8); dst_ptr += dst_pitch;
  504. vst1q_u8((uint8_t *)dst_ptr, q3u8); dst_ptr += dst_pitch;
  505. vst1q_u8((uint8_t *)dst_ptr, q4u8); dst_ptr += dst_pitch;
  506. }
  507. return;
  508. }