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