sad.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. * Copyright (c) 2015 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 "./vpx_config.h"
  12. #include "./vpx_dsp_rtcd.h"
  13. #include "vpx/vpx_integer.h"
  14. #include "vpx_ports/mem.h"
  15. /* Sum the difference between every corresponding element of the buffers. */
  16. static INLINE unsigned int sad(const uint8_t *a, int a_stride,
  17. const uint8_t *b, int b_stride,
  18. int width, int height) {
  19. int y, x;
  20. unsigned int sad = 0;
  21. for (y = 0; y < height; y++) {
  22. for (x = 0; x < width; x++)
  23. sad += abs(a[x] - b[x]);
  24. a += a_stride;
  25. b += b_stride;
  26. }
  27. return sad;
  28. }
  29. // TODO(johannkoenig): this moved to vpx_dsp, should be able to clean this up.
  30. /* Remove dependency on vp9 variance function by duplicating vp9_comp_avg_pred.
  31. * The function averages every corresponding element of the buffers and stores
  32. * the value in a third buffer, comp_pred.
  33. * pred and comp_pred are assumed to have stride = width
  34. * In the usage below comp_pred is a local array.
  35. */
  36. static INLINE void avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,
  37. int height, const uint8_t *ref, int ref_stride) {
  38. int i, j;
  39. for (i = 0; i < height; i++) {
  40. for (j = 0; j < width; j++) {
  41. const int tmp = pred[j] + ref[j];
  42. comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
  43. }
  44. comp_pred += width;
  45. pred += width;
  46. ref += ref_stride;
  47. }
  48. }
  49. #if CONFIG_VP9_HIGHBITDEPTH
  50. static INLINE void highbd_avg_pred(uint16_t *comp_pred, const uint8_t *pred8,
  51. int width, int height, const uint8_t *ref8,
  52. int ref_stride) {
  53. int i, j;
  54. uint16_t *pred = CONVERT_TO_SHORTPTR(pred8);
  55. uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
  56. for (i = 0; i < height; i++) {
  57. for (j = 0; j < width; j++) {
  58. const int tmp = pred[j] + ref[j];
  59. comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
  60. }
  61. comp_pred += width;
  62. pred += width;
  63. ref += ref_stride;
  64. }
  65. }
  66. #endif // CONFIG_VP9_HIGHBITDEPTH
  67. #define sadMxN(m, n) \
  68. unsigned int vpx_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
  69. const uint8_t *ref, int ref_stride) { \
  70. return sad(src, src_stride, ref, ref_stride, m, n); \
  71. } \
  72. unsigned int vpx_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride, \
  73. const uint8_t *ref, int ref_stride, \
  74. const uint8_t *second_pred) { \
  75. uint8_t comp_pred[m * n]; \
  76. avg_pred(comp_pred, second_pred, m, n, ref, ref_stride); \
  77. return sad(src, src_stride, comp_pred, m, m, n); \
  78. }
  79. // depending on call sites, pass **ref_array to avoid & in subsequent call and
  80. // de-dup with 4D below.
  81. #define sadMxNxK(m, n, k) \
  82. void vpx_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride, \
  83. const uint8_t *ref_array, int ref_stride, \
  84. uint32_t *sad_array) { \
  85. int i; \
  86. for (i = 0; i < k; ++i) \
  87. sad_array[i] = vpx_sad##m##x##n##_c(src, src_stride, &ref_array[i], ref_stride); \
  88. }
  89. // This appears to be equivalent to the above when k == 4 and refs is const
  90. #define sadMxNx4D(m, n) \
  91. void vpx_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
  92. const uint8_t *const ref_array[], int ref_stride, \
  93. uint32_t *sad_array) { \
  94. int i; \
  95. for (i = 0; i < 4; ++i) \
  96. sad_array[i] = vpx_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \
  97. }
  98. // 64x64
  99. sadMxN(64, 64)
  100. sadMxNxK(64, 64, 3)
  101. sadMxNxK(64, 64, 8)
  102. sadMxNx4D(64, 64)
  103. // 64x32
  104. sadMxN(64, 32)
  105. sadMxNx4D(64, 32)
  106. // 32x64
  107. sadMxN(32, 64)
  108. sadMxNx4D(32, 64)
  109. // 32x32
  110. sadMxN(32, 32)
  111. sadMxNxK(32, 32, 3)
  112. sadMxNxK(32, 32, 8)
  113. sadMxNx4D(32, 32)
  114. // 32x16
  115. sadMxN(32, 16)
  116. sadMxNx4D(32, 16)
  117. // 16x32
  118. sadMxN(16, 32)
  119. sadMxNx4D(16, 32)
  120. // 16x16
  121. sadMxN(16, 16)
  122. sadMxNxK(16, 16, 3)
  123. sadMxNxK(16, 16, 8)
  124. sadMxNx4D(16, 16)
  125. // 16x8
  126. sadMxN(16, 8)
  127. sadMxNxK(16, 8, 3)
  128. sadMxNxK(16, 8, 8)
  129. sadMxNx4D(16, 8)
  130. // 8x16
  131. sadMxN(8, 16)
  132. sadMxNxK(8, 16, 3)
  133. sadMxNxK(8, 16, 8)
  134. sadMxNx4D(8, 16)
  135. // 8x8
  136. sadMxN(8, 8)
  137. sadMxNxK(8, 8, 3)
  138. sadMxNxK(8, 8, 8)
  139. sadMxNx4D(8, 8)
  140. // 8x4
  141. sadMxN(8, 4)
  142. sadMxNxK(8, 4, 8)
  143. sadMxNx4D(8, 4)
  144. // 4x8
  145. sadMxN(4, 8)
  146. sadMxNxK(4, 8, 8)
  147. sadMxNx4D(4, 8)
  148. // 4x4
  149. sadMxN(4, 4)
  150. sadMxNxK(4, 4, 3)
  151. sadMxNxK(4, 4, 8)
  152. sadMxNx4D(4, 4)
  153. #if CONFIG_VP9_HIGHBITDEPTH
  154. static INLINE unsigned int highbd_sad(const uint8_t *a8, int a_stride,
  155. const uint8_t *b8, int b_stride,
  156. int width, int height) {
  157. int y, x;
  158. unsigned int sad = 0;
  159. const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
  160. const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
  161. for (y = 0; y < height; y++) {
  162. for (x = 0; x < width; x++)
  163. sad += abs(a[x] - b[x]);
  164. a += a_stride;
  165. b += b_stride;
  166. }
  167. return sad;
  168. }
  169. static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
  170. const uint16_t *b, int b_stride,
  171. int width, int height) {
  172. int y, x;
  173. unsigned int sad = 0;
  174. const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
  175. for (y = 0; y < height; y++) {
  176. for (x = 0; x < width; x++)
  177. sad += abs(a[x] - b[x]);
  178. a += a_stride;
  179. b += b_stride;
  180. }
  181. return sad;
  182. }
  183. #define highbd_sadMxN(m, n) \
  184. unsigned int vpx_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
  185. const uint8_t *ref, int ref_stride) { \
  186. return highbd_sad(src, src_stride, ref, ref_stride, m, n); \
  187. } \
  188. unsigned int vpx_highbd_sad##m##x##n##_avg_c(const uint8_t *src, \
  189. int src_stride, \
  190. const uint8_t *ref, \
  191. int ref_stride, \
  192. const uint8_t *second_pred) { \
  193. uint16_t comp_pred[m * n]; \
  194. highbd_avg_pred(comp_pred, second_pred, m, n, ref, ref_stride); \
  195. return highbd_sadb(src, src_stride, comp_pred, m, m, n); \
  196. }
  197. #define highbd_sadMxNxK(m, n, k) \
  198. void vpx_highbd_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride, \
  199. const uint8_t *ref_array, int ref_stride, \
  200. uint32_t *sad_array) { \
  201. int i; \
  202. for (i = 0; i < k; ++i) { \
  203. sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, &ref_array[i], \
  204. ref_stride); \
  205. } \
  206. }
  207. #define highbd_sadMxNx4D(m, n) \
  208. void vpx_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
  209. const uint8_t *const ref_array[], \
  210. int ref_stride, uint32_t *sad_array) { \
  211. int i; \
  212. for (i = 0; i < 4; ++i) { \
  213. sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, ref_array[i], \
  214. ref_stride); \
  215. } \
  216. }
  217. // 64x64
  218. highbd_sadMxN(64, 64)
  219. highbd_sadMxNxK(64, 64, 3)
  220. highbd_sadMxNxK(64, 64, 8)
  221. highbd_sadMxNx4D(64, 64)
  222. // 64x32
  223. highbd_sadMxN(64, 32)
  224. highbd_sadMxNx4D(64, 32)
  225. // 32x64
  226. highbd_sadMxN(32, 64)
  227. highbd_sadMxNx4D(32, 64)
  228. // 32x32
  229. highbd_sadMxN(32, 32)
  230. highbd_sadMxNxK(32, 32, 3)
  231. highbd_sadMxNxK(32, 32, 8)
  232. highbd_sadMxNx4D(32, 32)
  233. // 32x16
  234. highbd_sadMxN(32, 16)
  235. highbd_sadMxNx4D(32, 16)
  236. // 16x32
  237. highbd_sadMxN(16, 32)
  238. highbd_sadMxNx4D(16, 32)
  239. // 16x16
  240. highbd_sadMxN(16, 16)
  241. highbd_sadMxNxK(16, 16, 3)
  242. highbd_sadMxNxK(16, 16, 8)
  243. highbd_sadMxNx4D(16, 16)
  244. // 16x8
  245. highbd_sadMxN(16, 8)
  246. highbd_sadMxNxK(16, 8, 3)
  247. highbd_sadMxNxK(16, 8, 8)
  248. highbd_sadMxNx4D(16, 8)
  249. // 8x16
  250. highbd_sadMxN(8, 16)
  251. highbd_sadMxNxK(8, 16, 3)
  252. highbd_sadMxNxK(8, 16, 8)
  253. highbd_sadMxNx4D(8, 16)
  254. // 8x8
  255. highbd_sadMxN(8, 8)
  256. highbd_sadMxNxK(8, 8, 3)
  257. highbd_sadMxNxK(8, 8, 8)
  258. highbd_sadMxNx4D(8, 8)
  259. // 8x4
  260. highbd_sadMxN(8, 4)
  261. highbd_sadMxNxK(8, 4, 8)
  262. highbd_sadMxNx4D(8, 4)
  263. // 4x8
  264. highbd_sadMxN(4, 8)
  265. highbd_sadMxNxK(4, 8, 8)
  266. highbd_sadMxNx4D(4, 8)
  267. // 4x4
  268. highbd_sadMxN(4, 4)
  269. highbd_sadMxNxK(4, 4, 3)
  270. highbd_sadMxNxK(4, 4, 8)
  271. highbd_sadMxNx4D(4, 4)
  272. #endif // CONFIG_VP9_HIGHBITDEPTH