Merge changes from topic 'missing-proto'
[aom.git] / vpx_dsp / sad.c
blobc0c3ff99645cb80752f746c54460ea991340fab8
1 /*
2 * Copyright (c) 2015 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.
9 */
11 #include <stdlib.h>
13 #include "./vpx_config.h"
14 #include "./vpx_dsp_rtcd.h"
16 #include "vpx/vpx_integer.h"
17 #include "vpx_ports/mem.h"
19 /* Sum the difference between every corresponding element of the buffers. */
20 static INLINE unsigned int sad(const uint8_t *a, int a_stride,
21 const uint8_t *b, int b_stride,
22 int width, int height) {
23 int y, x;
24 unsigned int sad = 0;
26 for (y = 0; y < height; y++) {
27 for (x = 0; x < width; x++)
28 sad += abs(a[x] - b[x]);
30 a += a_stride;
31 b += b_stride;
33 return sad;
36 // TODO(johannkoenig): this moved to vpx_dsp, should be able to clean this up.
37 /* Remove dependency on vp9 variance function by duplicating vp9_comp_avg_pred.
38 * The function averages every corresponding element of the buffers and stores
39 * the value in a third buffer, comp_pred.
40 * pred and comp_pred are assumed to have stride = width
41 * In the usage below comp_pred is a local array.
43 static INLINE void avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,
44 int height, const uint8_t *ref, int ref_stride) {
45 int i, j;
47 for (i = 0; i < height; i++) {
48 for (j = 0; j < width; j++) {
49 const int tmp = pred[j] + ref[j];
50 comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
52 comp_pred += width;
53 pred += width;
54 ref += ref_stride;
58 #if CONFIG_VP9_HIGHBITDEPTH
59 static INLINE void highbd_avg_pred(uint16_t *comp_pred, const uint8_t *pred8,
60 int width, int height, const uint8_t *ref8,
61 int ref_stride) {
62 int i, j;
63 uint16_t *pred = CONVERT_TO_SHORTPTR(pred8);
64 uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
65 for (i = 0; i < height; i++) {
66 for (j = 0; j < width; j++) {
67 const int tmp = pred[j] + ref[j];
68 comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
70 comp_pred += width;
71 pred += width;
72 ref += ref_stride;
75 #endif // CONFIG_VP9_HIGHBITDEPTH
77 #define sadMxN(m, n) \
78 unsigned int vpx_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
79 const uint8_t *ref, int ref_stride) { \
80 return sad(src, src_stride, ref, ref_stride, m, n); \
81 } \
82 unsigned int vpx_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride, \
83 const uint8_t *ref, int ref_stride, \
84 const uint8_t *second_pred) { \
85 uint8_t comp_pred[m * n]; \
86 avg_pred(comp_pred, second_pred, m, n, ref, ref_stride); \
87 return sad(src, src_stride, comp_pred, m, m, n); \
90 // depending on call sites, pass **ref_array to avoid & in subsequent call and
91 // de-dup with 4D below.
92 #define sadMxNxK(m, n, k) \
93 void vpx_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride, \
94 const uint8_t *ref_array, int ref_stride, \
95 uint32_t *sad_array) { \
96 int i; \
97 for (i = 0; i < k; ++i) \
98 sad_array[i] = vpx_sad##m##x##n##_c(src, src_stride, &ref_array[i], ref_stride); \
101 // This appears to be equivalent to the above when k == 4 and refs is const
102 #define sadMxNx4D(m, n) \
103 void vpx_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
104 const uint8_t *const ref_array[], int ref_stride, \
105 uint32_t *sad_array) { \
106 int i; \
107 for (i = 0; i < 4; ++i) \
108 sad_array[i] = vpx_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \
111 // 64x64
112 sadMxN(64, 64)
113 sadMxNxK(64, 64, 3)
114 sadMxNxK(64, 64, 8)
115 sadMxNx4D(64, 64)
117 // 64x32
118 sadMxN(64, 32)
119 sadMxNx4D(64, 32)
121 // 32x64
122 sadMxN(32, 64)
123 sadMxNx4D(32, 64)
125 // 32x32
126 sadMxN(32, 32)
127 sadMxNxK(32, 32, 3)
128 sadMxNxK(32, 32, 8)
129 sadMxNx4D(32, 32)
131 // 32x16
132 sadMxN(32, 16)
133 sadMxNx4D(32, 16)
135 // 16x32
136 sadMxN(16, 32)
137 sadMxNx4D(16, 32)
139 // 16x16
140 sadMxN(16, 16)
141 sadMxNxK(16, 16, 3)
142 sadMxNxK(16, 16, 8)
143 sadMxNx4D(16, 16)
145 // 16x8
146 sadMxN(16, 8)
147 sadMxNxK(16, 8, 3)
148 sadMxNxK(16, 8, 8)
149 sadMxNx4D(16, 8)
151 // 8x16
152 sadMxN(8, 16)
153 sadMxNxK(8, 16, 3)
154 sadMxNxK(8, 16, 8)
155 sadMxNx4D(8, 16)
157 // 8x8
158 sadMxN(8, 8)
159 sadMxNxK(8, 8, 3)
160 sadMxNxK(8, 8, 8)
161 sadMxNx4D(8, 8)
163 // 8x4
164 sadMxN(8, 4)
165 sadMxNxK(8, 4, 8)
166 sadMxNx4D(8, 4)
168 // 4x8
169 sadMxN(4, 8)
170 sadMxNxK(4, 8, 8)
171 sadMxNx4D(4, 8)
173 // 4x4
174 sadMxN(4, 4)
175 sadMxNxK(4, 4, 3)
176 sadMxNxK(4, 4, 8)
177 sadMxNx4D(4, 4)
179 #if CONFIG_VP9_HIGHBITDEPTH
180 static INLINE unsigned int highbd_sad(const uint8_t *a8, int a_stride,
181 const uint8_t *b8, int b_stride,
182 int width, int height) {
183 int y, x;
184 unsigned int sad = 0;
185 const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
186 const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
187 for (y = 0; y < height; y++) {
188 for (x = 0; x < width; x++)
189 sad += abs(a[x] - b[x]);
191 a += a_stride;
192 b += b_stride;
194 return sad;
197 static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
198 const uint16_t *b, int b_stride,
199 int width, int height) {
200 int y, x;
201 unsigned int sad = 0;
202 const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
203 for (y = 0; y < height; y++) {
204 for (x = 0; x < width; x++)
205 sad += abs(a[x] - b[x]);
207 a += a_stride;
208 b += b_stride;
210 return sad;
213 #define highbd_sadMxN(m, n) \
214 unsigned int vpx_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
215 const uint8_t *ref, int ref_stride) { \
216 return highbd_sad(src, src_stride, ref, ref_stride, m, n); \
218 unsigned int vpx_highbd_sad##m##x##n##_avg_c(const uint8_t *src, \
219 int src_stride, \
220 const uint8_t *ref, \
221 int ref_stride, \
222 const uint8_t *second_pred) { \
223 uint16_t comp_pred[m * n]; \
224 highbd_avg_pred(comp_pred, second_pred, m, n, ref, ref_stride); \
225 return highbd_sadb(src, src_stride, comp_pred, m, m, n); \
228 #define highbd_sadMxNxK(m, n, k) \
229 void vpx_highbd_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride, \
230 const uint8_t *ref_array, int ref_stride, \
231 uint32_t *sad_array) { \
232 int i; \
233 for (i = 0; i < k; ++i) { \
234 sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, &ref_array[i], \
235 ref_stride); \
239 #define highbd_sadMxNx4D(m, n) \
240 void vpx_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
241 const uint8_t *const ref_array[], \
242 int ref_stride, uint32_t *sad_array) { \
243 int i; \
244 for (i = 0; i < 4; ++i) { \
245 sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, ref_array[i], \
246 ref_stride); \
250 // 64x64
251 highbd_sadMxN(64, 64)
252 highbd_sadMxNxK(64, 64, 3)
253 highbd_sadMxNxK(64, 64, 8)
254 highbd_sadMxNx4D(64, 64)
256 // 64x32
257 highbd_sadMxN(64, 32)
258 highbd_sadMxNx4D(64, 32)
260 // 32x64
261 highbd_sadMxN(32, 64)
262 highbd_sadMxNx4D(32, 64)
264 // 32x32
265 highbd_sadMxN(32, 32)
266 highbd_sadMxNxK(32, 32, 3)
267 highbd_sadMxNxK(32, 32, 8)
268 highbd_sadMxNx4D(32, 32)
270 // 32x16
271 highbd_sadMxN(32, 16)
272 highbd_sadMxNx4D(32, 16)
274 // 16x32
275 highbd_sadMxN(16, 32)
276 highbd_sadMxNx4D(16, 32)
278 // 16x16
279 highbd_sadMxN(16, 16)
280 highbd_sadMxNxK(16, 16, 3)
281 highbd_sadMxNxK(16, 16, 8)
282 highbd_sadMxNx4D(16, 16)
284 // 16x8
285 highbd_sadMxN(16, 8)
286 highbd_sadMxNxK(16, 8, 3)
287 highbd_sadMxNxK(16, 8, 8)
288 highbd_sadMxNx4D(16, 8)
290 // 8x16
291 highbd_sadMxN(8, 16)
292 highbd_sadMxNxK(8, 16, 3)
293 highbd_sadMxNxK(8, 16, 8)
294 highbd_sadMxNx4D(8, 16)
296 // 8x8
297 highbd_sadMxN(8, 8)
298 highbd_sadMxNxK(8, 8, 3)
299 highbd_sadMxNxK(8, 8, 8)
300 highbd_sadMxNx4D(8, 8)
302 // 8x4
303 highbd_sadMxN(8, 4)
304 highbd_sadMxNxK(8, 4, 8)
305 highbd_sadMxNx4D(8, 4)
307 // 4x8
308 highbd_sadMxN(4, 8)
309 highbd_sadMxNxK(4, 8, 8)
310 highbd_sadMxNx4D(4, 8)
312 // 4x4
313 highbd_sadMxN(4, 4)
314 highbd_sadMxNxK(4, 4, 3)
315 highbd_sadMxNxK(4, 4, 8)
316 highbd_sadMxNx4D(4, 4)
318 #endif // CONFIG_VP9_HIGHBITDEPTH