sad.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  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 *src_ptr, int src_stride,
  17. const uint8_t *ref_ptr, int ref_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++) sad += abs(src_ptr[x] - ref_ptr[x]);
  23. src_ptr += src_stride;
  24. ref_ptr += ref_stride;
  25. }
  26. return sad;
  27. }
  28. #define sadMxN(m, n) \
  29. unsigned int vpx_sad##m##x##n##_c(const uint8_t *src_ptr, int src_stride, \
  30. const uint8_t *ref_ptr, int ref_stride) { \
  31. return sad(src_ptr, src_stride, ref_ptr, ref_stride, m, n); \
  32. } \
  33. unsigned int vpx_sad##m##x##n##_avg_c( \
  34. const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, \
  35. int ref_stride, const uint8_t *second_pred) { \
  36. DECLARE_ALIGNED(16, uint8_t, comp_pred[m * n]); \
  37. vpx_comp_avg_pred_c(comp_pred, second_pred, m, n, ref_ptr, ref_stride); \
  38. return sad(src_ptr, src_stride, comp_pred, m, m, n); \
  39. }
  40. // depending on call sites, pass **ref_array to avoid & in subsequent call and
  41. // de-dup with 4D below.
  42. #define sadMxNxK(m, n, k) \
  43. void vpx_sad##m##x##n##x##k##_c(const uint8_t *src_ptr, int src_stride, \
  44. const uint8_t *ref_ptr, int ref_stride, \
  45. uint32_t *sad_array) { \
  46. int i; \
  47. for (i = 0; i < k; ++i) \
  48. sad_array[i] = \
  49. vpx_sad##m##x##n##_c(src_ptr, src_stride, &ref_ptr[i], ref_stride); \
  50. }
  51. // This appears to be equivalent to the above when k == 4 and refs is const
  52. #define sadMxNx4D(m, n) \
  53. void vpx_sad##m##x##n##x4d_c(const uint8_t *src_ptr, int src_stride, \
  54. const uint8_t *const ref_array[], \
  55. int ref_stride, uint32_t *sad_array) { \
  56. int i; \
  57. for (i = 0; i < 4; ++i) \
  58. sad_array[i] = \
  59. vpx_sad##m##x##n##_c(src_ptr, src_stride, ref_array[i], ref_stride); \
  60. }
  61. /* clang-format off */
  62. // 64x64
  63. sadMxN(64, 64)
  64. sadMxNx4D(64, 64)
  65. // 64x32
  66. sadMxN(64, 32)
  67. sadMxNx4D(64, 32)
  68. // 32x64
  69. sadMxN(32, 64)
  70. sadMxNx4D(32, 64)
  71. // 32x32
  72. sadMxN(32, 32)
  73. sadMxNx4D(32, 32)
  74. // 32x16
  75. sadMxN(32, 16)
  76. sadMxNx4D(32, 16)
  77. // 16x32
  78. sadMxN(16, 32)
  79. sadMxNx4D(16, 32)
  80. // 16x16
  81. sadMxN(16, 16)
  82. sadMxNxK(16, 16, 3)
  83. sadMxNxK(16, 16, 8)
  84. sadMxNx4D(16, 16)
  85. // 16x8
  86. sadMxN(16, 8)
  87. sadMxNxK(16, 8, 3)
  88. sadMxNxK(16, 8, 8)
  89. sadMxNx4D(16, 8)
  90. // 8x16
  91. sadMxN(8, 16)
  92. sadMxNxK(8, 16, 3)
  93. sadMxNxK(8, 16, 8)
  94. sadMxNx4D(8, 16)
  95. // 8x8
  96. sadMxN(8, 8)
  97. sadMxNxK(8, 8, 3)
  98. sadMxNxK(8, 8, 8)
  99. sadMxNx4D(8, 8)
  100. // 8x4
  101. sadMxN(8, 4)
  102. sadMxNx4D(8, 4)
  103. // 4x8
  104. sadMxN(4, 8)
  105. sadMxNx4D(4, 8)
  106. // 4x4
  107. sadMxN(4, 4)
  108. sadMxNxK(4, 4, 3)
  109. sadMxNxK(4, 4, 8)
  110. sadMxNx4D(4, 4)
  111. /* clang-format on */
  112. #if CONFIG_VP9_HIGHBITDEPTH
  113. static INLINE
  114. unsigned int highbd_sad(const uint8_t *src8_ptr, int src_stride,
  115. const uint8_t *ref8_ptr, int ref_stride, int width,
  116. int height) {
  117. int y, x;
  118. unsigned int sad = 0;
  119. const uint16_t *src = CONVERT_TO_SHORTPTR(src8_ptr);
  120. const uint16_t *ref_ptr = CONVERT_TO_SHORTPTR(ref8_ptr);
  121. for (y = 0; y < height; y++) {
  122. for (x = 0; x < width; x++) sad += abs(src[x] - ref_ptr[x]);
  123. src += src_stride;
  124. ref_ptr += ref_stride;
  125. }
  126. return sad;
  127. }
  128. static INLINE unsigned int highbd_sadb(const uint8_t *src8_ptr, int src_stride,
  129. const uint16_t *ref_ptr, int ref_stride,
  130. int width, int height) {
  131. int y, x;
  132. unsigned int sad = 0;
  133. const uint16_t *src = CONVERT_TO_SHORTPTR(src8_ptr);
  134. for (y = 0; y < height; y++) {
  135. for (x = 0; x < width; x++) sad += abs(src[x] - ref_ptr[x]);
  136. src += src_stride;
  137. ref_ptr += ref_stride;
  138. }
  139. return sad;
  140. }
  141. #define highbd_sadMxN(m, n) \
  142. unsigned int vpx_highbd_sad##m##x##n##_c( \
  143. const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, \
  144. int ref_stride) { \
  145. return highbd_sad(src_ptr, src_stride, ref_ptr, ref_stride, m, n); \
  146. } \
  147. unsigned int vpx_highbd_sad##m##x##n##_avg_c( \
  148. const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr, \
  149. int ref_stride, const uint8_t *second_pred) { \
  150. DECLARE_ALIGNED(16, uint16_t, comp_pred[m * n]); \
  151. vpx_highbd_comp_avg_pred_c(comp_pred, CONVERT_TO_SHORTPTR(second_pred), m, \
  152. n, CONVERT_TO_SHORTPTR(ref_ptr), ref_stride); \
  153. return highbd_sadb(src_ptr, src_stride, comp_pred, m, m, n); \
  154. }
  155. #define highbd_sadMxNx4D(m, n) \
  156. void vpx_highbd_sad##m##x##n##x4d_c(const uint8_t *src_ptr, int src_stride, \
  157. const uint8_t *const ref_array[], \
  158. int ref_stride, uint32_t *sad_array) { \
  159. int i; \
  160. for (i = 0; i < 4; ++i) { \
  161. sad_array[i] = vpx_highbd_sad##m##x##n##_c(src_ptr, src_stride, \
  162. ref_array[i], ref_stride); \
  163. } \
  164. }
  165. /* clang-format off */
  166. // 64x64
  167. highbd_sadMxN(64, 64)
  168. highbd_sadMxNx4D(64, 64)
  169. // 64x32
  170. highbd_sadMxN(64, 32)
  171. highbd_sadMxNx4D(64, 32)
  172. // 32x64
  173. highbd_sadMxN(32, 64)
  174. highbd_sadMxNx4D(32, 64)
  175. // 32x32
  176. highbd_sadMxN(32, 32)
  177. highbd_sadMxNx4D(32, 32)
  178. // 32x16
  179. highbd_sadMxN(32, 16)
  180. highbd_sadMxNx4D(32, 16)
  181. // 16x32
  182. highbd_sadMxN(16, 32)
  183. highbd_sadMxNx4D(16, 32)
  184. // 16x16
  185. highbd_sadMxN(16, 16)
  186. highbd_sadMxNx4D(16, 16)
  187. // 16x8
  188. highbd_sadMxN(16, 8)
  189. highbd_sadMxNx4D(16, 8)
  190. // 8x16
  191. highbd_sadMxN(8, 16)
  192. highbd_sadMxNx4D(8, 16)
  193. // 8x8
  194. highbd_sadMxN(8, 8)
  195. highbd_sadMxNx4D(8, 8)
  196. // 8x4
  197. highbd_sadMxN(8, 4)
  198. highbd_sadMxNx4D(8, 4)
  199. // 4x8
  200. highbd_sadMxN(4, 8)
  201. highbd_sadMxNx4D(4, 8)
  202. // 4x4
  203. highbd_sadMxN(4, 4)
  204. highbd_sadMxNx4D(4, 4)
  205. /* clang-format on */
  206. #endif // CONFIG_VP9_HIGHBITDEPTH