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