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++) sad += abs(a[x] - b[x]);
29 
30     a += a_stride;
31     b += b_stride;
32   }
33   return sad;
34 }
35 
36 #define sadMxh(m)                                                          \
37   unsigned int aom_sad##m##xh_c(const uint8_t *a, int a_stride,            \
38                                 const uint8_t *b, int b_stride, int width, \
39                                 int height) {                              \
40     return sad(a, a_stride, b, b_stride, width, height);                   \
41   }
42 
43 #define sadMxN(m, n)                                                          \
44   unsigned int aom_sad##m##x##n##_c(const uint8_t *src, int src_stride,       \
45                                     const uint8_t *ref, int ref_stride) {     \
46     return sad(src, src_stride, ref, ref_stride, m, n);                       \
47   }                                                                           \
48   unsigned int aom_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride,   \
49                                         const uint8_t *ref, int ref_stride,   \
50                                         const uint8_t *second_pred) {         \
51     uint8_t comp_pred[m * n];                                                 \
52     aom_comp_avg_pred(comp_pred, second_pred, m, n, ref, ref_stride);         \
53     return sad(src, src_stride, comp_pred, m, m, n);                          \
54   }                                                                           \
55   unsigned int aom_jnt_sad##m##x##n##_avg_c(                                  \
56       const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride, \
57       const uint8_t *second_pred, const JNT_COMP_PARAMS *jcp_param) {         \
58     uint8_t comp_pred[m * n];                                                 \
59     aom_jnt_comp_avg_pred_c(comp_pred, second_pred, m, n, ref, ref_stride,    \
60                             jcp_param);                                       \
61     return sad(src, src_stride, comp_pred, m, m, n);                          \
62   }
63 
64 // Calculate sad against 4 reference locations and store each in sad_array
65 #define sadMxNx4D(m, n)                                                    \
66   void aom_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride,         \
67                                const uint8_t *const ref_array[],           \
68                                int ref_stride, uint32_t *sad_array) {      \
69     int i;                                                                 \
70     for (i = 0; i < 4; ++i)                                                \
71       sad_array[i] =                                                       \
72           aom_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \
73   }
74 
75 /* clang-format off */
76 // 128x128
77 sadMxN(128, 128)
78 sadMxNx4D(128, 128)
79 
80 // 128x64
81 sadMxN(128, 64)
82 sadMxNx4D(128, 64)
83 
84 // 64x128
85 sadMxN(64, 128)
86 sadMxNx4D(64, 128)
87 
88 // 64x64
89 sadMxN(64, 64)
90 sadMxNx4D(64, 64)
91 
92 // 64x32
93 sadMxN(64, 32)
94 sadMxNx4D(64, 32)
95 
96 // 32x64
97 sadMxN(32, 64)
98 sadMxNx4D(32, 64)
99 
100 // 32x32
101 sadMxN(32, 32)
102 sadMxNx4D(32, 32)
103 
104 // 32x16
105 sadMxN(32, 16)
106 sadMxNx4D(32, 16)
107 
108 // 16x32
109 sadMxN(16, 32)
110 sadMxNx4D(16, 32)
111 
112 // 16x16
113 sadMxN(16, 16)
114 sadMxNx4D(16, 16)
115 
116 // 16x8
117 sadMxN(16, 8)
118 sadMxNx4D(16, 8)
119 
120 // 8x16
121 sadMxN(8, 16)
122 sadMxNx4D(8, 16)
123 
124 // 8x8
125 sadMxN(8, 8)
126 sadMxNx4D(8, 8)
127 
128 // 8x4
129 sadMxN(8, 4)
130 sadMxNx4D(8, 4)
131 
132 // 4x8
133 sadMxN(4, 8)
134 sadMxNx4D(4, 8)
135 
136 // 4x4
137 sadMxN(4, 4)
138 sadMxNx4D(4, 4)
139 
140 sadMxh(128);
141 sadMxh(64);
142 sadMxh(32);
143 sadMxh(16);
144 sadMxh(8);
145 sadMxh(4);
146 
147 sadMxN(4, 16)
148 sadMxNx4D(4, 16)
149 sadMxN(16, 4)
150 sadMxNx4D(16, 4)
151 sadMxN(8, 32)
152 sadMxNx4D(8, 32)
153 sadMxN(32, 8)
154 sadMxNx4D(32, 8)
155 sadMxN(16, 64)
156 sadMxNx4D(16, 64)
157 sadMxN(64, 16)
158 sadMxNx4D(64, 16)
159 
160     /* clang-format on */
161 
162     static INLINE
highbd_sad(const uint8_t * a8,int a_stride,const uint8_t * b8,int b_stride,int width,int height)163     unsigned int highbd_sad(const uint8_t *a8, int a_stride, const uint8_t *b8,
164                             int b_stride, int width, int height) {
165   int y, x;
166   unsigned int sad = 0;
167   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
168   const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
169   for (y = 0; y < height; y++) {
170     for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
171 
172     a += a_stride;
173     b += b_stride;
174   }
175   return sad;
176 }
177 
highbd_sadb(const uint8_t * a8,int a_stride,const uint16_t * b,int b_stride,int width,int height)178 static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
179                                        const uint16_t *b, int b_stride,
180                                        int width, int height) {
181   int y, x;
182   unsigned int sad = 0;
183   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
184   for (y = 0; y < height; y++) {
185     for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
186 
187     a += a_stride;
188     b += b_stride;
189   }
190   return sad;
191 }
192 
193 #define highbd_sadMxN(m, n)                                                    \
194   unsigned int aom_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
195                                            const uint8_t *ref,                 \
196                                            int ref_stride) {                   \
197     return highbd_sad(src, src_stride, ref, ref_stride, m, n);                 \
198   }                                                                            \
199   unsigned int aom_highbd_sad##m##x##n##_avg_c(                                \
200       const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride,  \
201       const uint8_t *second_pred) {                                            \
202     uint16_t comp_pred[m * n];                                                 \
203     aom_highbd_comp_avg_pred(CONVERT_TO_BYTEPTR(comp_pred), second_pred, m, n, \
204                              ref, ref_stride);                                 \
205     return highbd_sadb(src, src_stride, comp_pred, m, m, n);                   \
206   }                                                                            \
207   unsigned int aom_highbd_jnt_sad##m##x##n##_avg_c(                            \
208       const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride,  \
209       const uint8_t *second_pred, const JNT_COMP_PARAMS *jcp_param) {          \
210     uint16_t comp_pred[m * n];                                                 \
211     aom_highbd_jnt_comp_avg_pred(CONVERT_TO_BYTEPTR(comp_pred), second_pred,   \
212                                  m, n, ref, ref_stride, jcp_param);            \
213     return highbd_sadb(src, src_stride, comp_pred, m, m, n);                   \
214   }
215 
216 #define highbd_sadMxNx4D(m, n)                                               \
217   void aom_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride,    \
218                                       const uint8_t *const ref_array[],      \
219                                       int ref_stride, uint32_t *sad_array) { \
220     int i;                                                                   \
221     for (i = 0; i < 4; ++i) {                                                \
222       sad_array[i] = aom_highbd_sad##m##x##n##_c(src, src_stride,            \
223                                                  ref_array[i], ref_stride);  \
224     }                                                                        \
225   }
226 
227 /* clang-format off */
228 // 128x128
229 highbd_sadMxN(128, 128)
230 highbd_sadMxNx4D(128, 128)
231 
232 // 128x64
233 highbd_sadMxN(128, 64)
234 highbd_sadMxNx4D(128, 64)
235 
236 // 64x128
237 highbd_sadMxN(64, 128)
238 highbd_sadMxNx4D(64, 128)
239 
240 // 64x64
241 highbd_sadMxN(64, 64)
242 highbd_sadMxNx4D(64, 64)
243 
244 // 64x32
245 highbd_sadMxN(64, 32)
246 highbd_sadMxNx4D(64, 32)
247 
248 // 32x64
249 highbd_sadMxN(32, 64)
250 highbd_sadMxNx4D(32, 64)
251 
252 // 32x32
253 highbd_sadMxN(32, 32)
254 highbd_sadMxNx4D(32, 32)
255 
256 // 32x16
257 highbd_sadMxN(32, 16)
258 highbd_sadMxNx4D(32, 16)
259 
260 // 16x32
261 highbd_sadMxN(16, 32)
262 highbd_sadMxNx4D(16, 32)
263 
264 // 16x16
265 highbd_sadMxN(16, 16)
266 highbd_sadMxNx4D(16, 16)
267 
268 // 16x8
269 highbd_sadMxN(16, 8)
270 highbd_sadMxNx4D(16, 8)
271 
272 // 8x16
273 highbd_sadMxN(8, 16)
274 highbd_sadMxNx4D(8, 16)
275 
276 // 8x8
277 highbd_sadMxN(8, 8)
278 highbd_sadMxNx4D(8, 8)
279 
280 // 8x4
281 highbd_sadMxN(8, 4)
282 highbd_sadMxNx4D(8, 4)
283 
284 // 4x8
285 highbd_sadMxN(4, 8)
286 highbd_sadMxNx4D(4, 8)
287 
288 // 4x4
289 highbd_sadMxN(4, 4)
290 highbd_sadMxNx4D(4, 4)
291 
292 highbd_sadMxN(4, 16)
293 highbd_sadMxNx4D(4, 16)
294 highbd_sadMxN(16, 4)
295 highbd_sadMxNx4D(16, 4)
296 highbd_sadMxN(8, 32)
297 highbd_sadMxNx4D(8, 32)
298 highbd_sadMxN(32, 8)
299 highbd_sadMxNx4D(32, 8)
300 highbd_sadMxN(16, 64)
301 highbd_sadMxNx4D(16, 64)
302 highbd_sadMxN(64, 16)
303 highbd_sadMxNx4D(64, 16)
304     /* clang-format on */
305