• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 SADMXN(m, n)                                                      \
39   unsigned int aom_sad##m##x##n##_c(const uint8_t *src, int src_stride,   \
40                                     const uint8_t *ref, int ref_stride) { \
41     return sad(src, src_stride, ref, ref_stride, m, n);                   \
42   }
43 
44 #define SADMXN_AVG(m, n)                                                    \
45   unsigned int aom_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride, \
46                                         const uint8_t *ref, int ref_stride, \
47                                         const uint8_t *second_pred) {       \
48     uint8_t comp_pred[m * n];                                               \
49     aom_comp_avg_pred(comp_pred, second_pred, m, n, ref, ref_stride);       \
50     return sad(src, src_stride, comp_pred, m, m, n);                        \
51   }
52 
53 #define SADMXN_SKIP(m, n)                                                     \
54   unsigned int aom_sad_skip_##m##x##n##_c(const uint8_t *src, int src_stride, \
55                                           const uint8_t *ref,                 \
56                                           int ref_stride) {                   \
57     return 2 * sad(src, 2 * src_stride, ref, 2 * ref_stride, (m), (n / 2));   \
58   }
59 
60 #define SADMXN_NO_SKIP(m, n) \
61   SADMXN(m, n)               \
62   SADMXN_AVG(m, n)
63 
64 #define SADMXN_NO_AVG(m, n) \
65   SADMXN(m, n)              \
66   SADMXN_SKIP(m, n)
67 
68 #define SADMXN_ALL(m, n) \
69   SADMXN(m, n)           \
70   SADMXN_AVG(m, n)       \
71   SADMXN_SKIP(m, n)
72 
73 // Calculate sad against 4 reference locations and store each in sad_array
74 #define SAD_MXNX4D_NO_SKIP(m, n)                                           \
75   void aom_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride,         \
76                                const uint8_t *const ref_array[4],          \
77                                int ref_stride, uint32_t sad_array[4]) {    \
78     int i;                                                                 \
79     for (i = 0; i < 4; ++i) {                                              \
80       sad_array[i] =                                                       \
81           aom_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \
82     }                                                                      \
83   }
84 
85 #define SAD_MXNX4D(m, n)                                                      \
86   SAD_MXNX4D_NO_SKIP(m, n)                                                    \
87   void aom_sad_skip_##m##x##n##x4d_c(const uint8_t *src, int src_stride,      \
88                                      const uint8_t *const ref_array[4],       \
89                                      int ref_stride, uint32_t sad_array[4]) { \
90     int i;                                                                    \
91     for (i = 0; i < 4; ++i) {                                                 \
92       sad_array[i] = 2 * sad(src, 2 * src_stride, ref_array[i],               \
93                              2 * ref_stride, (m), (n / 2));                   \
94     }                                                                         \
95   }
96 // Call SIMD version of aom_sad_mxnx4d if the 3d version is unavailable.
97 #define SAD_MXNX3D(m, n)                                                      \
98   void aom_sad##m##x##n##x3d_c(const uint8_t *src, int src_stride,            \
99                                const uint8_t *const ref_array[4],             \
100                                int ref_stride, uint32_t sad_array[4]) {       \
101     aom_sad##m##x##n##x4d(src, src_stride, ref_array, ref_stride, sad_array); \
102   }
103 
104 // 128x128
105 SADMXN_ALL(128, 128)
106 SAD_MXNX4D(128, 128)
107 SAD_MXNX3D(128, 128)
108 
109 // 128x64
110 SADMXN_ALL(128, 64)
111 SAD_MXNX4D(128, 64)
112 SAD_MXNX3D(128, 64)
113 
114 // 64x128
115 SADMXN_ALL(64, 128)
116 SAD_MXNX4D(64, 128)
117 SAD_MXNX3D(64, 128)
118 
119 // 64x64
120 SADMXN_ALL(64, 64)
121 SAD_MXNX4D(64, 64)
122 SAD_MXNX3D(64, 64)
123 
124 // 64x32
125 SADMXN_ALL(64, 32)
126 SAD_MXNX4D(64, 32)
127 SAD_MXNX3D(64, 32)
128 
129 // 32x64
130 SADMXN_ALL(32, 64)
131 SAD_MXNX4D(32, 64)
132 SAD_MXNX3D(32, 64)
133 
134 // 32x32
135 SADMXN_ALL(32, 32)
136 SAD_MXNX4D(32, 32)
137 SAD_MXNX3D(32, 32)
138 
139 // 32x16
140 SADMXN_ALL(32, 16)
141 SAD_MXNX4D(32, 16)
142 SAD_MXNX3D(32, 16)
143 
144 // 16x32
145 SADMXN_ALL(16, 32)
146 SAD_MXNX4D(16, 32)
147 SAD_MXNX3D(16, 32)
148 
149 // 16x16
150 SADMXN_ALL(16, 16)
151 SAD_MXNX4D(16, 16)
152 SAD_MXNX3D(16, 16)
153 
154 // 16x8
155 SADMXN_NO_SKIP(16, 8)
156 SAD_MXNX4D_NO_SKIP(16, 8)
157 SAD_MXNX3D(16, 8)
158 
159 // 8x16
160 SADMXN_ALL(8, 16)
161 SAD_MXNX4D(8, 16)
162 SAD_MXNX3D(8, 16)
163 
164 // 8x8
165 SADMXN_NO_SKIP(8, 8)
166 SAD_MXNX4D_NO_SKIP(8, 8)
167 SAD_MXNX3D(8, 8)
168 
169 // 8x4
170 SADMXN(8, 4)
171 SAD_MXNX4D_NO_SKIP(8, 4)
172 SAD_MXNX3D(8, 4)
173 
174 // 4x8
175 SADMXN(4, 8)
176 SAD_MXNX4D_NO_SKIP(4, 8)
177 SAD_MXNX3D(4, 8)
178 
179 // 4x4
180 SADMXN(4, 4)
181 SAD_MXNX4D_NO_SKIP(4, 4)
182 SAD_MXNX3D(4, 4)
183 
184 #if !CONFIG_REALTIME_ONLY
185 SADMXN_NO_AVG(4, 16)
186 SAD_MXNX4D(4, 16)
187 SADMXN(16, 4)
188 SAD_MXNX4D_NO_SKIP(16, 4)
189 SADMXN_ALL(8, 32)
190 SAD_MXNX4D(8, 32)
191 SADMXN_NO_SKIP(32, 8)
192 SAD_MXNX4D_NO_SKIP(32, 8)
193 SADMXN_ALL(16, 64)
194 SAD_MXNX4D(16, 64)
195 SADMXN_ALL(64, 16)
196 SAD_MXNX4D(64, 16)
197 SAD_MXNX3D(4, 16)
198 SAD_MXNX3D(16, 4)
199 SAD_MXNX3D(8, 32)
200 SAD_MXNX3D(32, 8)
201 SAD_MXNX3D(16, 64)
202 SAD_MXNX3D(64, 16)
203 #endif  // !CONFIG_REALTIME_ONLY
204 
205 #if CONFIG_AV1_HIGHBITDEPTH
highbd_sad(const uint8_t * a8,int a_stride,const uint8_t * b8,int b_stride,int width,int height)206 static inline unsigned int highbd_sad(const uint8_t *a8, int a_stride,
207                                       const uint8_t *b8, int b_stride,
208                                       int width, int height) {
209   int y, x;
210   unsigned int sad = 0;
211   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
212   const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
213   for (y = 0; y < height; y++) {
214     for (x = 0; x < width; x++) {
215       sad += abs(a[x] - b[x]);
216     }
217 
218     a += a_stride;
219     b += b_stride;
220   }
221   return sad;
222 }
223 
highbd_sadb(const uint8_t * a8,int a_stride,const uint8_t * b8,int b_stride,int width,int height)224 static inline unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
225                                        const uint8_t *b8, int b_stride,
226                                        int width, int height) {
227   int y, x;
228   unsigned int sad = 0;
229   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
230   const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
231   for (y = 0; y < height; y++) {
232     for (x = 0; x < width; x++) {
233       sad += abs(a[x] - b[x]);
234     }
235 
236     a += a_stride;
237     b += b_stride;
238   }
239   return sad;
240 }
241 
242 #define HIGHBD_SADMXN(m, n)                                                    \
243   unsigned int aom_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
244                                            const uint8_t *ref,                 \
245                                            int ref_stride) {                   \
246     return highbd_sad(src, src_stride, ref, ref_stride, m, n);                 \
247   }
248 
249 #define HIGHBD_SADMXN_AVG(m, n)                                               \
250   unsigned int aom_highbd_sad##m##x##n##_avg_c(                               \
251       const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride, \
252       const uint8_t *second_pred) {                                           \
253     uint16_t comp_pred[m * n];                                                \
254     uint8_t *const comp_pred8 = CONVERT_TO_BYTEPTR(comp_pred);                \
255     aom_highbd_comp_avg_pred(comp_pred8, second_pred, m, n, ref, ref_stride); \
256     return highbd_sadb(src, src_stride, comp_pred8, m, m, n);                 \
257   }
258 
259 #define HIGHBD_SADMXN_SKIP(m, n)                                               \
260   unsigned int aom_highbd_sad_skip_##m##x##n##_c(                              \
261       const uint8_t *src, int src_stride, const uint8_t *ref,                  \
262       int ref_stride) {                                                        \
263     return 2 *                                                                 \
264            highbd_sad(src, 2 * src_stride, ref, 2 * ref_stride, (m), (n / 2)); \
265   }
266 
267 #define HIGHBD_SADMXN_NO_SKIP(m, n) \
268   HIGHBD_SADMXN(m, n)               \
269   HIGHBD_SADMXN_AVG(m, n)
270 
271 #define HIGHBD_SADMXN_NO_AVG(m, n) \
272   HIGHBD_SADMXN(m, n)              \
273   HIGHBD_SADMXN_SKIP(m, n)
274 
275 #define HIGHBD_SADMXN_ALL(m, n) \
276   HIGHBD_SADMXN(m, n)           \
277   HIGHBD_SADMXN_AVG(m, n)       \
278   HIGHBD_SADMXN_SKIP(m, n)
279 
280 #define HIGHBD_SAD_MXNX4D_NO_SKIP(m, n)                                        \
281   void aom_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride,      \
282                                       const uint8_t *const ref_array[4],       \
283                                       int ref_stride, uint32_t sad_array[4]) { \
284     int i;                                                                     \
285     for (i = 0; i < 4; ++i) {                                                  \
286       sad_array[i] = aom_highbd_sad##m##x##n##_c(src, src_stride,              \
287                                                  ref_array[i], ref_stride);    \
288     }                                                                          \
289   }
290 
291 #define HIGHBD_SAD_MXNX4D(m, n)                                              \
292   HIGHBD_SAD_MXNX4D_NO_SKIP(m, n)                                            \
293   void aom_highbd_sad_skip_##m##x##n##x4d_c(                                 \
294       const uint8_t *src, int src_stride, const uint8_t *const ref_array[4], \
295       int ref_stride, uint32_t sad_array[4]) {                               \
296     int i;                                                                   \
297     for (i = 0; i < 4; ++i) {                                                \
298       sad_array[i] = 2 * highbd_sad(src, 2 * src_stride, ref_array[i],       \
299                                     2 * ref_stride, (m), (n / 2));           \
300     }                                                                        \
301   }
302 // Call SIMD version of aom_highbd_sad_mxnx4d if the 3d version is unavailable.
303 #define HIGHBD_SAD_MXNX3D(m, n)                                                \
304   void aom_highbd_sad##m##x##n##x3d_c(const uint8_t *src, int src_stride,      \
305                                       const uint8_t *const ref_array[4],       \
306                                       int ref_stride, uint32_t sad_array[4]) { \
307     aom_highbd_sad##m##x##n##x4d(src, src_stride, ref_array, ref_stride,       \
308                                  sad_array);                                   \
309   }
310 
311 // 128x128
312 HIGHBD_SADMXN_ALL(128, 128)
313 HIGHBD_SAD_MXNX4D(128, 128)
314 HIGHBD_SAD_MXNX3D(128, 128)
315 
316 // 128x64
317 HIGHBD_SADMXN_ALL(128, 64)
318 HIGHBD_SAD_MXNX4D(128, 64)
319 HIGHBD_SAD_MXNX3D(128, 64)
320 
321 // 64x128
322 HIGHBD_SADMXN_ALL(64, 128)
323 HIGHBD_SAD_MXNX4D(64, 128)
324 HIGHBD_SAD_MXNX3D(64, 128)
325 
326 // 64x64
327 HIGHBD_SADMXN_ALL(64, 64)
328 HIGHBD_SAD_MXNX4D(64, 64)
329 HIGHBD_SAD_MXNX3D(64, 64)
330 
331 // 64x32
332 HIGHBD_SADMXN_ALL(64, 32)
333 HIGHBD_SAD_MXNX4D(64, 32)
334 HIGHBD_SAD_MXNX3D(64, 32)
335 
336 // 32x64
337 HIGHBD_SADMXN_ALL(32, 64)
338 HIGHBD_SAD_MXNX4D(32, 64)
339 HIGHBD_SAD_MXNX3D(32, 64)
340 
341 // 32x32
342 HIGHBD_SADMXN_ALL(32, 32)
343 HIGHBD_SAD_MXNX4D(32, 32)
344 HIGHBD_SAD_MXNX3D(32, 32)
345 
346 // 32x16
347 HIGHBD_SADMXN_ALL(32, 16)
348 HIGHBD_SAD_MXNX4D(32, 16)
349 HIGHBD_SAD_MXNX3D(32, 16)
350 
351 // 16x32
352 HIGHBD_SADMXN_ALL(16, 32)
353 HIGHBD_SAD_MXNX4D(16, 32)
354 HIGHBD_SAD_MXNX3D(16, 32)
355 
356 // 16x16
357 HIGHBD_SADMXN_ALL(16, 16)
358 HIGHBD_SAD_MXNX4D(16, 16)
359 HIGHBD_SAD_MXNX3D(16, 16)
360 
361 // 16x8
362 HIGHBD_SADMXN_NO_SKIP(16, 8)
363 HIGHBD_SAD_MXNX4D_NO_SKIP(16, 8)
364 HIGHBD_SAD_MXNX3D(16, 8)
365 
366 // 8x16
367 HIGHBD_SADMXN_ALL(8, 16)
368 HIGHBD_SAD_MXNX4D(8, 16)
369 HIGHBD_SAD_MXNX3D(8, 16)
370 
371 // 8x8
372 HIGHBD_SADMXN_NO_SKIP(8, 8)
373 HIGHBD_SAD_MXNX4D_NO_SKIP(8, 8)
374 HIGHBD_SAD_MXNX3D(8, 8)
375 
376 // 8x4
377 HIGHBD_SADMXN(8, 4)
378 HIGHBD_SAD_MXNX4D_NO_SKIP(8, 4)
379 HIGHBD_SAD_MXNX3D(8, 4)
380 
381 // 4x8
382 HIGHBD_SADMXN(4, 8)
383 HIGHBD_SAD_MXNX4D_NO_SKIP(4, 8)
384 HIGHBD_SAD_MXNX3D(4, 8)
385 
386 // 4x4
387 HIGHBD_SADMXN(4, 4)
388 HIGHBD_SAD_MXNX4D_NO_SKIP(4, 4)
389 HIGHBD_SAD_MXNX3D(4, 4)
390 
391 #if !CONFIG_REALTIME_ONLY
392 HIGHBD_SADMXN_NO_AVG(4, 16)
393 HIGHBD_SAD_MXNX4D(4, 16)
394 HIGHBD_SADMXN(16, 4)
395 HIGHBD_SAD_MXNX4D_NO_SKIP(16, 4)
396 HIGHBD_SADMXN_ALL(8, 32)
397 HIGHBD_SAD_MXNX4D(8, 32)
398 HIGHBD_SADMXN_NO_SKIP(32, 8)
399 HIGHBD_SAD_MXNX4D_NO_SKIP(32, 8)
400 HIGHBD_SADMXN_ALL(16, 64)
401 HIGHBD_SAD_MXNX4D(16, 64)
402 HIGHBD_SADMXN_ALL(64, 16)
403 HIGHBD_SAD_MXNX4D(64, 16)
404 
405 HIGHBD_SAD_MXNX3D(4, 16)
406 HIGHBD_SAD_MXNX3D(16, 4)
407 HIGHBD_SAD_MXNX3D(8, 32)
408 HIGHBD_SAD_MXNX3D(32, 8)
409 HIGHBD_SAD_MXNX3D(16, 64)
410 HIGHBD_SAD_MXNX3D(64, 16)
411 #endif  // !CONFIG_REALTIME_ONLY
412 #endif  // CONFIG_AV1_HIGHBITDEPTH
413