1 /*
2 * Copyright (c) 2015 The WebM project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11 #include <stdlib.h>
12
13 #include "./vpx_config.h"
14 #include "./vpx_dsp_rtcd.h"
15
16 #include "vpx/vpx_integer.h"
17 #include "vpx_ports/mem.h"
18
19 /* 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)20 static INLINE unsigned int sad(const uint8_t *a, int a_stride, const uint8_t *b,
21 int b_stride, int width, int height) {
22 int y, x;
23 unsigned int sad = 0;
24
25 for (y = 0; y < height; y++) {
26 for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
27
28 a += a_stride;
29 b += b_stride;
30 }
31 return sad;
32 }
33
34 #define sadMxN(m, n) \
35 unsigned int vpx_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
36 const uint8_t *ref, int ref_stride) { \
37 return sad(src, src_stride, ref, ref_stride, m, n); \
38 } \
39 unsigned int vpx_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride, \
40 const uint8_t *ref, int ref_stride, \
41 const uint8_t *second_pred) { \
42 DECLARE_ALIGNED(16, uint8_t, comp_pred[m * n]); \
43 vpx_comp_avg_pred_c(comp_pred, second_pred, m, n, ref, ref_stride); \
44 return sad(src, src_stride, comp_pred, m, m, n); \
45 }
46
47 // depending on call sites, pass **ref_array to avoid & in subsequent call and
48 // de-dup with 4D below.
49 #define sadMxNxK(m, n, k) \
50 void vpx_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride, \
51 const uint8_t *ref_array, int ref_stride, \
52 uint32_t *sad_array) { \
53 int i; \
54 for (i = 0; i < k; ++i) \
55 sad_array[i] = \
56 vpx_sad##m##x##n##_c(src, src_stride, &ref_array[i], ref_stride); \
57 }
58
59 // This appears to be equivalent to the above when k == 4 and refs is const
60 #define sadMxNx4D(m, n) \
61 void vpx_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
62 const uint8_t *const ref_array[], \
63 int ref_stride, uint32_t *sad_array) { \
64 int i; \
65 for (i = 0; i < 4; ++i) \
66 sad_array[i] = \
67 vpx_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \
68 }
69
70 /* clang-format off */
71 // 64x64
72 sadMxN(64, 64)
73 sadMxNxK(64, 64, 3)
74 sadMxNxK(64, 64, 8)
75 sadMxNx4D(64, 64)
76
77 // 64x32
78 sadMxN(64, 32)
79 sadMxNx4D(64, 32)
80
81 // 32x64
82 sadMxN(32, 64)
83 sadMxNx4D(32, 64)
84
85 // 32x32
86 sadMxN(32, 32)
87 sadMxNxK(32, 32, 3)
88 sadMxNxK(32, 32, 8)
89 sadMxNx4D(32, 32)
90
91 // 32x16
92 sadMxN(32, 16)
93 sadMxNx4D(32, 16)
94
95 // 16x32
96 sadMxN(16, 32)
97 sadMxNx4D(16, 32)
98
99 // 16x16
100 sadMxN(16, 16)
101 sadMxNxK(16, 16, 3)
102 sadMxNxK(16, 16, 8)
103 sadMxNx4D(16, 16)
104
105 // 16x8
106 sadMxN(16, 8)
107 sadMxNxK(16, 8, 3)
108 sadMxNxK(16, 8, 8)
109 sadMxNx4D(16, 8)
110
111 // 8x16
112 sadMxN(8, 16)
113 sadMxNxK(8, 16, 3)
114 sadMxNxK(8, 16, 8)
115 sadMxNx4D(8, 16)
116
117 // 8x8
118 sadMxN(8, 8)
119 sadMxNxK(8, 8, 3)
120 sadMxNxK(8, 8, 8)
121 sadMxNx4D(8, 8)
122
123 // 8x4
124 sadMxN(8, 4)
125 sadMxNxK(8, 4, 8)
126 sadMxNx4D(8, 4)
127
128 // 4x8
129 sadMxN(4, 8)
130 sadMxNxK(4, 8, 8)
131 sadMxNx4D(4, 8)
132
133 // 4x4
134 sadMxN(4, 4)
135 sadMxNxK(4, 4, 3)
136 sadMxNxK(4, 4, 8)
137 sadMxNx4D(4, 4)
138 /* clang-format on */
139
140 #if CONFIG_VP9_HIGHBITDEPTH
141 static INLINE
highbd_sad(const uint8_t * a8,int a_stride,const uint8_t * b8,int b_stride,int width,int height)142 unsigned int highbd_sad(const uint8_t *a8, int a_stride, const uint8_t *b8,
143 int b_stride, int width, int height) {
144 int y, x;
145 unsigned int sad = 0;
146 const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
147 const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
148 for (y = 0; y < height; y++) {
149 for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
150
151 a += a_stride;
152 b += b_stride;
153 }
154 return sad;
155 }
156
highbd_sadb(const uint8_t * a8,int a_stride,const uint16_t * b,int b_stride,int width,int height)157 static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
158 const uint16_t *b, int b_stride,
159 int width, int height) {
160 int y, x;
161 unsigned int sad = 0;
162 const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
163 for (y = 0; y < height; y++) {
164 for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
165
166 a += a_stride;
167 b += b_stride;
168 }
169 return sad;
170 }
171
172 #define highbd_sadMxN(m, n) \
173 unsigned int vpx_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
174 const uint8_t *ref, \
175 int ref_stride) { \
176 return highbd_sad(src, src_stride, ref, ref_stride, m, n); \
177 } \
178 unsigned int vpx_highbd_sad##m##x##n##_avg_c( \
179 const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride, \
180 const uint8_t *second_pred) { \
181 DECLARE_ALIGNED(16, uint16_t, comp_pred[m * n]); \
182 vpx_highbd_comp_avg_pred_c(comp_pred, second_pred, m, n, ref, ref_stride); \
183 return highbd_sadb(src, src_stride, comp_pred, m, m, n); \
184 }
185
186 #define highbd_sadMxNxK(m, n, k) \
187 void vpx_highbd_sad##m##x##n##x##k##_c( \
188 const uint8_t *src, int src_stride, const uint8_t *ref_array, \
189 int ref_stride, uint32_t *sad_array) { \
190 int i; \
191 for (i = 0; i < k; ++i) { \
192 sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, \
193 &ref_array[i], ref_stride); \
194 } \
195 }
196
197 #define highbd_sadMxNx4D(m, n) \
198 void vpx_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
199 const uint8_t *const ref_array[], \
200 int ref_stride, uint32_t *sad_array) { \
201 int i; \
202 for (i = 0; i < 4; ++i) { \
203 sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, \
204 ref_array[i], ref_stride); \
205 } \
206 }
207
208 /* clang-format off */
209 // 64x64
210 highbd_sadMxN(64, 64)
211 highbd_sadMxNxK(64, 64, 3)
212 highbd_sadMxNxK(64, 64, 8)
213 highbd_sadMxNx4D(64, 64)
214
215 // 64x32
216 highbd_sadMxN(64, 32)
217 highbd_sadMxNx4D(64, 32)
218
219 // 32x64
220 highbd_sadMxN(32, 64)
221 highbd_sadMxNx4D(32, 64)
222
223 // 32x32
224 highbd_sadMxN(32, 32)
225 highbd_sadMxNxK(32, 32, 3)
226 highbd_sadMxNxK(32, 32, 8)
227 highbd_sadMxNx4D(32, 32)
228
229 // 32x16
230 highbd_sadMxN(32, 16)
231 highbd_sadMxNx4D(32, 16)
232
233 // 16x32
234 highbd_sadMxN(16, 32)
235 highbd_sadMxNx4D(16, 32)
236
237 // 16x16
238 highbd_sadMxN(16, 16)
239 highbd_sadMxNxK(16, 16, 3)
240 highbd_sadMxNxK(16, 16, 8)
241 highbd_sadMxNx4D(16, 16)
242
243 // 16x8
244 highbd_sadMxN(16, 8)
245 highbd_sadMxNxK(16, 8, 3)
246 highbd_sadMxNxK(16, 8, 8)
247 highbd_sadMxNx4D(16, 8)
248
249 // 8x16
250 highbd_sadMxN(8, 16)
251 highbd_sadMxNxK(8, 16, 3)
252 highbd_sadMxNxK(8, 16, 8)
253 highbd_sadMxNx4D(8, 16)
254
255 // 8x8
256 highbd_sadMxN(8, 8)
257 highbd_sadMxNxK(8, 8, 3)
258 highbd_sadMxNxK(8, 8, 8)
259 highbd_sadMxNx4D(8, 8)
260
261 // 8x4
262 highbd_sadMxN(8, 4)
263 highbd_sadMxNxK(8, 4, 8)
264 highbd_sadMxNx4D(8, 4)
265
266 // 4x8
267 highbd_sadMxN(4, 8)
268 highbd_sadMxNxK(4, 8, 8)
269 highbd_sadMxNx4D(4, 8)
270
271 // 4x4
272 highbd_sadMxN(4, 4)
273 highbd_sadMxNxK(4, 4, 3)
274 highbd_sadMxNxK(4, 4, 8)
275 highbd_sadMxNx4D(4, 4)
276 /* clang-format on */
277
278 #endif // CONFIG_VP9_HIGHBITDEPTH
279