1 /*
2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 2 Clause License and
5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6 * was not distributed with this source code in the LICENSE file, you can
7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8 * Media Patent License 1.0 was not distributed with this source code in the
9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10 */
11
12 #include <stdlib.h>
13
14 #include "config/aom_config.h"
15 #include "config/aom_dsp_rtcd.h"
16
17 #include "aom/aom_integer.h"
18 #include "aom_ports/mem.h"
19 #include "aom_dsp/blend.h"
20
21 /* Sum the difference between every corresponding element of the buffers. */
sad(const uint8_t * a,int a_stride,const uint8_t * b,int b_stride,int width,int height)22 static INLINE unsigned int sad(const uint8_t *a, int a_stride, const uint8_t *b,
23 int b_stride, int width, int height) {
24 int y, x;
25 unsigned int sad = 0;
26
27 for (y = 0; y < height; y++) {
28 for (x = 0; x < width; x++) {
29 sad += abs(a[x] - b[x]);
30 }
31
32 a += a_stride;
33 b += b_stride;
34 }
35 return sad;
36 }
37
38 #define sadMxh(m) \
39 unsigned int aom_sad##m##xh_c(const uint8_t *a, int a_stride, \
40 const uint8_t *b, int b_stride, int width, \
41 int height) { \
42 return sad(a, a_stride, b, b_stride, width, height); \
43 }
44
45 #define sadMxN(m, n) \
46 unsigned int aom_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
47 const uint8_t *ref, int ref_stride) { \
48 return sad(src, src_stride, ref, ref_stride, m, n); \
49 } \
50 unsigned int aom_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride, \
51 const uint8_t *ref, int ref_stride, \
52 const uint8_t *second_pred) { \
53 uint8_t comp_pred[m * n]; \
54 aom_comp_avg_pred(comp_pred, second_pred, m, n, ref, ref_stride); \
55 return sad(src, src_stride, comp_pred, m, m, n); \
56 } \
57 unsigned int aom_dist_wtd_sad##m##x##n##_avg_c( \
58 const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride, \
59 const uint8_t *second_pred, const DIST_WTD_COMP_PARAMS *jcp_param) { \
60 uint8_t comp_pred[m * n]; \
61 aom_dist_wtd_comp_avg_pred_c(comp_pred, second_pred, m, n, ref, \
62 ref_stride, jcp_param); \
63 return sad(src, src_stride, comp_pred, m, m, n); \
64 } \
65 unsigned int aom_sad_skip_##m##x##n##_c(const uint8_t *src, int src_stride, \
66 const uint8_t *ref, \
67 int ref_stride) { \
68 return 2 * sad(src, 2 * src_stride, ref, 2 * ref_stride, (m), (n / 2)); \
69 }
70
71 // Calculate sad against 4 reference locations and store each in sad_array
72 #define sadMxNx4D(m, n) \
73 void aom_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
74 const uint8_t *const ref_array[], \
75 int ref_stride, uint32_t *sad_array) { \
76 int i; \
77 for (i = 0; i < 4; ++i) { \
78 sad_array[i] = \
79 aom_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \
80 } \
81 } \
82 void aom_sad##m##x##n##x4d_avg_c( \
83 const uint8_t *src, int src_stride, const uint8_t *const ref_array[], \
84 int ref_stride, const uint8_t *second_pred, uint32_t *sad_array) { \
85 int i; \
86 for (i = 0; i < 4; ++i) { \
87 sad_array[i] = aom_sad##m##x##n##_avg_c(src, src_stride, ref_array[i], \
88 ref_stride, second_pred); \
89 } \
90 } \
91 void aom_sad_skip_##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
92 const uint8_t *const ref_array[], \
93 int ref_stride, uint32_t *sad_array) { \
94 int i; \
95 for (i = 0; i < 4; ++i) { \
96 sad_array[i] = 2 * sad(src, 2 * src_stride, ref_array[i], \
97 2 * ref_stride, (m), (n / 2)); \
98 } \
99 }
100
101 // 128x128
102 sadMxN(128, 128);
103 sadMxNx4D(128, 128);
104
105 // 128x64
106 sadMxN(128, 64);
107 sadMxNx4D(128, 64);
108
109 // 64x128
110 sadMxN(64, 128);
111 sadMxNx4D(64, 128);
112
113 // 64x64
114 sadMxN(64, 64);
115 sadMxNx4D(64, 64);
116
117 // 64x32
118 sadMxN(64, 32);
119 sadMxNx4D(64, 32);
120
121 // 32x64
122 sadMxN(32, 64);
123 sadMxNx4D(32, 64);
124
125 // 32x32
126 sadMxN(32, 32);
127 sadMxNx4D(32, 32);
128
129 // 32x16
130 sadMxN(32, 16);
131 sadMxNx4D(32, 16);
132
133 // 16x32
134 sadMxN(16, 32);
135 sadMxNx4D(16, 32);
136
137 // 16x16
138 sadMxN(16, 16);
139 sadMxNx4D(16, 16);
140
141 // 16x8
142 sadMxN(16, 8);
143 sadMxNx4D(16, 8);
144
145 // 8x16
146 sadMxN(8, 16);
147 sadMxNx4D(8, 16);
148
149 // 8x8
150 sadMxN(8, 8);
151 sadMxNx4D(8, 8);
152
153 // 8x4
154 sadMxN(8, 4);
155 sadMxNx4D(8, 4);
156
157 // 4x8
158 sadMxN(4, 8);
159 sadMxNx4D(4, 8);
160
161 // 4x4
162 sadMxN(4, 4);
163 sadMxNx4D(4, 4);
164
165 sadMxh(128);
166 sadMxh(64);
167 sadMxh(32);
168 sadMxh(16);
169 sadMxh(8);
170 sadMxh(4);
171
172 sadMxN(4, 16);
173 sadMxNx4D(4, 16);
174 sadMxN(16, 4);
175 sadMxNx4D(16, 4);
176 sadMxN(8, 32);
177 sadMxNx4D(8, 32);
178 sadMxN(32, 8);
179 sadMxNx4D(32, 8);
180 sadMxN(16, 64);
181 sadMxNx4D(16, 64);
182 sadMxN(64, 16);
183 sadMxNx4D(64, 16);
184
185 #if CONFIG_AV1_HIGHBITDEPTH
highbd_sad(const uint8_t * a8,int a_stride,const uint8_t * b8,int b_stride,int width,int height)186 static INLINE unsigned int highbd_sad(const uint8_t *a8, int a_stride,
187 const uint8_t *b8, int b_stride,
188 int width, int height) {
189 int y, x;
190 unsigned int sad = 0;
191 const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
192 const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
193 for (y = 0; y < height; y++) {
194 for (x = 0; x < width; x++) {
195 sad += abs(a[x] - b[x]);
196 }
197
198 a += a_stride;
199 b += b_stride;
200 }
201 return sad;
202 }
203
highbd_sadb(const uint8_t * a8,int a_stride,const uint8_t * b8,int b_stride,int width,int height)204 static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
205 const uint8_t *b8, int b_stride,
206 int width, int height) {
207 int y, x;
208 unsigned int sad = 0;
209 const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
210 const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
211 for (y = 0; y < height; y++) {
212 for (x = 0; x < width; x++) {
213 sad += abs(a[x] - b[x]);
214 }
215
216 a += a_stride;
217 b += b_stride;
218 }
219 return sad;
220 }
221
222 #define highbd_sadMxN(m, n) \
223 unsigned int aom_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
224 const uint8_t *ref, \
225 int ref_stride) { \
226 return highbd_sad(src, src_stride, ref, ref_stride, m, n); \
227 } \
228 unsigned int aom_highbd_sad##m##x##n##_avg_c( \
229 const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride, \
230 const uint8_t *second_pred) { \
231 uint16_t comp_pred[m * n]; \
232 uint8_t *const comp_pred8 = CONVERT_TO_BYTEPTR(comp_pred); \
233 aom_highbd_comp_avg_pred(comp_pred8, second_pred, m, n, ref, ref_stride); \
234 return highbd_sadb(src, src_stride, comp_pred8, m, m, n); \
235 } \
236 unsigned int aom_highbd_dist_wtd_sad##m##x##n##_avg_c( \
237 const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride, \
238 const uint8_t *second_pred, const DIST_WTD_COMP_PARAMS *jcp_param) { \
239 uint16_t comp_pred[m * n]; \
240 uint8_t *const comp_pred8 = CONVERT_TO_BYTEPTR(comp_pred); \
241 aom_highbd_dist_wtd_comp_avg_pred(comp_pred8, second_pred, m, n, ref, \
242 ref_stride, jcp_param); \
243 return highbd_sadb(src, src_stride, comp_pred8, m, m, n); \
244 } \
245 unsigned int aom_highbd_sad_skip_##m##x##n##_c( \
246 const uint8_t *src, int src_stride, const uint8_t *ref, \
247 int ref_stride) { \
248 return 2 * \
249 highbd_sad(src, 2 * src_stride, ref, 2 * ref_stride, (m), (n / 2)); \
250 }
251
252 #define highbd_sadMxNx4D(m, n) \
253 void aom_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
254 const uint8_t *const ref_array[], \
255 int ref_stride, uint32_t *sad_array) { \
256 int i; \
257 for (i = 0; i < 4; ++i) { \
258 sad_array[i] = aom_highbd_sad##m##x##n##_c(src, src_stride, \
259 ref_array[i], ref_stride); \
260 } \
261 } \
262 void aom_highbd_sad_skip_##m##x##n##x4d_c( \
263 const uint8_t *src, int src_stride, const uint8_t *const ref_array[], \
264 int ref_stride, uint32_t *sad_array) { \
265 int i; \
266 for (i = 0; i < 4; ++i) { \
267 sad_array[i] = 2 * highbd_sad(src, 2 * src_stride, ref_array[i], \
268 2 * ref_stride, (m), (n / 2)); \
269 } \
270 }
271
272 // 128x128
273 highbd_sadMxN(128, 128);
274 highbd_sadMxNx4D(128, 128);
275
276 // 128x64
277 highbd_sadMxN(128, 64);
278 highbd_sadMxNx4D(128, 64);
279
280 // 64x128
281 highbd_sadMxN(64, 128);
282 highbd_sadMxNx4D(64, 128);
283
284 // 64x64
285 highbd_sadMxN(64, 64);
286 highbd_sadMxNx4D(64, 64);
287
288 // 64x32
289 highbd_sadMxN(64, 32);
290 highbd_sadMxNx4D(64, 32);
291
292 // 32x64
293 highbd_sadMxN(32, 64);
294 highbd_sadMxNx4D(32, 64);
295
296 // 32x32
297 highbd_sadMxN(32, 32);
298 highbd_sadMxNx4D(32, 32);
299
300 // 32x16
301 highbd_sadMxN(32, 16);
302 highbd_sadMxNx4D(32, 16);
303
304 // 16x32
305 highbd_sadMxN(16, 32);
306 highbd_sadMxNx4D(16, 32);
307
308 // 16x16
309 highbd_sadMxN(16, 16);
310 highbd_sadMxNx4D(16, 16);
311
312 // 16x8
313 highbd_sadMxN(16, 8);
314 highbd_sadMxNx4D(16, 8);
315
316 // 8x16
317 highbd_sadMxN(8, 16);
318 highbd_sadMxNx4D(8, 16);
319
320 // 8x8
321 highbd_sadMxN(8, 8);
322 highbd_sadMxNx4D(8, 8);
323
324 // 8x4
325 highbd_sadMxN(8, 4);
326 highbd_sadMxNx4D(8, 4);
327
328 // 4x8
329 highbd_sadMxN(4, 8);
330 highbd_sadMxNx4D(4, 8);
331
332 // 4x4
333 highbd_sadMxN(4, 4);
334 highbd_sadMxNx4D(4, 4);
335
336 highbd_sadMxN(4, 16);
337 highbd_sadMxNx4D(4, 16);
338 highbd_sadMxN(16, 4);
339 highbd_sadMxNx4D(16, 4);
340 highbd_sadMxN(8, 32);
341 highbd_sadMxNx4D(8, 32);
342 highbd_sadMxN(32, 8);
343 highbd_sadMxNx4D(32, 8);
344 highbd_sadMxN(16, 64);
345 highbd_sadMxNx4D(16, 64);
346 highbd_sadMxN(64, 16);
347 highbd_sadMxNx4D(64, 16);
348 #endif // CONFIG_AV1_HIGHBITDEPTH
349