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,
21 const uint8_t *b, int b_stride,
22 int width, int height) {
23 int y, x;
24 unsigned int sad = 0;
25
26 for (y = 0; y < height; y++) {
27 for (x = 0; x < width; x++)
28 sad += abs(a[x] - b[x]);
29
30 a += a_stride;
31 b += b_stride;
32 }
33 return sad;
34 }
35
36 // TODO(johannkoenig): this moved to vpx_dsp, should be able to clean this up.
37 /* Remove dependency on vp9 variance function by duplicating vp9_comp_avg_pred.
38 * The function averages every corresponding element of the buffers and stores
39 * the value in a third buffer, comp_pred.
40 * pred and comp_pred are assumed to have stride = width
41 * In the usage below comp_pred is a local array.
42 */
avg_pred(uint8_t * comp_pred,const uint8_t * pred,int width,int height,const uint8_t * ref,int ref_stride)43 static INLINE void avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,
44 int height, const uint8_t *ref, int ref_stride) {
45 int i, j;
46
47 for (i = 0; i < height; i++) {
48 for (j = 0; j < width; j++) {
49 const int tmp = pred[j] + ref[j];
50 comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
51 }
52 comp_pred += width;
53 pred += width;
54 ref += ref_stride;
55 }
56 }
57
58 #if CONFIG_VP9_HIGHBITDEPTH
highbd_avg_pred(uint16_t * comp_pred,const uint8_t * pred8,int width,int height,const uint8_t * ref8,int ref_stride)59 static INLINE void highbd_avg_pred(uint16_t *comp_pred, const uint8_t *pred8,
60 int width, int height, const uint8_t *ref8,
61 int ref_stride) {
62 int i, j;
63 uint16_t *pred = CONVERT_TO_SHORTPTR(pred8);
64 uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
65 for (i = 0; i < height; i++) {
66 for (j = 0; j < width; j++) {
67 const int tmp = pred[j] + ref[j];
68 comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
69 }
70 comp_pred += width;
71 pred += width;
72 ref += ref_stride;
73 }
74 }
75 #endif // CONFIG_VP9_HIGHBITDEPTH
76
77 #define sadMxN(m, n) \
78 unsigned int vpx_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
79 const uint8_t *ref, int ref_stride) { \
80 return sad(src, src_stride, ref, ref_stride, m, n); \
81 } \
82 unsigned int vpx_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride, \
83 const uint8_t *ref, int ref_stride, \
84 const uint8_t *second_pred) { \
85 uint8_t comp_pred[m * n]; \
86 avg_pred(comp_pred, second_pred, m, n, ref, ref_stride); \
87 return sad(src, src_stride, comp_pred, m, m, n); \
88 }
89
90 // depending on call sites, pass **ref_array to avoid & in subsequent call and
91 // de-dup with 4D below.
92 #define sadMxNxK(m, n, k) \
93 void vpx_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride, \
94 const uint8_t *ref_array, int ref_stride, \
95 uint32_t *sad_array) { \
96 int i; \
97 for (i = 0; i < k; ++i) \
98 sad_array[i] = vpx_sad##m##x##n##_c(src, src_stride, &ref_array[i], ref_stride); \
99 }
100
101 // This appears to be equivalent to the above when k == 4 and refs is const
102 #define sadMxNx4D(m, n) \
103 void vpx_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
104 const uint8_t *const ref_array[], int ref_stride, \
105 uint32_t *sad_array) { \
106 int i; \
107 for (i = 0; i < 4; ++i) \
108 sad_array[i] = vpx_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \
109 }
110
111 // 64x64
112 sadMxN(64, 64)
113 sadMxNxK(64, 64, 3)
114 sadMxNxK(64, 64, 8)
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 sadMxNxK(32, 32, 3)
128 sadMxNxK(32, 32, 8)
129 sadMxNx4D(32, 32)
130
131 // 32x16
132 sadMxN(32, 16)
133 sadMxNx4D(32, 16)
134
135 // 16x32
136 sadMxN(16, 32)
137 sadMxNx4D(16, 32)
138
139 // 16x16
140 sadMxN(16, 16)
141 sadMxNxK(16, 16, 3)
142 sadMxNxK(16, 16, 8)
143 sadMxNx4D(16, 16)
144
145 // 16x8
146 sadMxN(16, 8)
147 sadMxNxK(16, 8, 3)
148 sadMxNxK(16, 8, 8)
149 sadMxNx4D(16, 8)
150
151 // 8x16
152 sadMxN(8, 16)
153 sadMxNxK(8, 16, 3)
154 sadMxNxK(8, 16, 8)
155 sadMxNx4D(8, 16)
156
157 // 8x8
158 sadMxN(8, 8)
159 sadMxNxK(8, 8, 3)
160 sadMxNxK(8, 8, 8)
161 sadMxNx4D(8, 8)
162
163 // 8x4
164 sadMxN(8, 4)
165 sadMxNxK(8, 4, 8)
166 sadMxNx4D(8, 4)
167
168 // 4x8
169 sadMxN(4, 8)
170 sadMxNxK(4, 8, 8)
171 sadMxNx4D(4, 8)
172
173 // 4x4
174 sadMxN(4, 4)
175 sadMxNxK(4, 4, 3)
176 sadMxNxK(4, 4, 8)
177 sadMxNx4D(4, 4)
178
179 #if CONFIG_VP9_HIGHBITDEPTH
highbd_sad(const uint8_t * a8,int a_stride,const uint8_t * b8,int b_stride,int width,int height)180 static INLINE unsigned int highbd_sad(const uint8_t *a8, int a_stride,
181 const uint8_t *b8, int b_stride,
182 int width, int height) {
183 int y, x;
184 unsigned int sad = 0;
185 const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
186 const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
187 for (y = 0; y < height; y++) {
188 for (x = 0; x < width; x++)
189 sad += abs(a[x] - b[x]);
190
191 a += a_stride;
192 b += b_stride;
193 }
194 return sad;
195 }
196
highbd_sadb(const uint8_t * a8,int a_stride,const uint16_t * b,int b_stride,int width,int height)197 static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
198 const uint16_t *b, int b_stride,
199 int width, int height) {
200 int y, x;
201 unsigned int sad = 0;
202 const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
203 for (y = 0; y < height; y++) {
204 for (x = 0; x < width; x++)
205 sad += abs(a[x] - b[x]);
206
207 a += a_stride;
208 b += b_stride;
209 }
210 return sad;
211 }
212
213 #define highbd_sadMxN(m, n) \
214 unsigned int vpx_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
215 const uint8_t *ref, int ref_stride) { \
216 return highbd_sad(src, src_stride, ref, ref_stride, m, n); \
217 } \
218 unsigned int vpx_highbd_sad##m##x##n##_avg_c(const uint8_t *src, \
219 int src_stride, \
220 const uint8_t *ref, \
221 int ref_stride, \
222 const uint8_t *second_pred) { \
223 uint16_t comp_pred[m * n]; \
224 highbd_avg_pred(comp_pred, second_pred, m, n, ref, ref_stride); \
225 return highbd_sadb(src, src_stride, comp_pred, m, m, n); \
226 }
227
228 #define highbd_sadMxNxK(m, n, k) \
229 void vpx_highbd_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride, \
230 const uint8_t *ref_array, int ref_stride, \
231 uint32_t *sad_array) { \
232 int i; \
233 for (i = 0; i < k; ++i) { \
234 sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, &ref_array[i], \
235 ref_stride); \
236 } \
237 }
238
239 #define highbd_sadMxNx4D(m, n) \
240 void vpx_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
241 const uint8_t *const ref_array[], \
242 int ref_stride, uint32_t *sad_array) { \
243 int i; \
244 for (i = 0; i < 4; ++i) { \
245 sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, ref_array[i], \
246 ref_stride); \
247 } \
248 }
249
250 // 64x64
251 highbd_sadMxN(64, 64)
252 highbd_sadMxNxK(64, 64, 3)
253 highbd_sadMxNxK(64, 64, 8)
254 highbd_sadMxNx4D(64, 64)
255
256 // 64x32
257 highbd_sadMxN(64, 32)
258 highbd_sadMxNx4D(64, 32)
259
260 // 32x64
261 highbd_sadMxN(32, 64)
262 highbd_sadMxNx4D(32, 64)
263
264 // 32x32
265 highbd_sadMxN(32, 32)
266 highbd_sadMxNxK(32, 32, 3)
267 highbd_sadMxNxK(32, 32, 8)
268 highbd_sadMxNx4D(32, 32)
269
270 // 32x16
271 highbd_sadMxN(32, 16)
272 highbd_sadMxNx4D(32, 16)
273
274 // 16x32
275 highbd_sadMxN(16, 32)
276 highbd_sadMxNx4D(16, 32)
277
278 // 16x16
279 highbd_sadMxN(16, 16)
280 highbd_sadMxNxK(16, 16, 3)
281 highbd_sadMxNxK(16, 16, 8)
282 highbd_sadMxNx4D(16, 16)
283
284 // 16x8
285 highbd_sadMxN(16, 8)
286 highbd_sadMxNxK(16, 8, 3)
287 highbd_sadMxNxK(16, 8, 8)
288 highbd_sadMxNx4D(16, 8)
289
290 // 8x16
291 highbd_sadMxN(8, 16)
292 highbd_sadMxNxK(8, 16, 3)
293 highbd_sadMxNxK(8, 16, 8)
294 highbd_sadMxNx4D(8, 16)
295
296 // 8x8
297 highbd_sadMxN(8, 8)
298 highbd_sadMxNxK(8, 8, 3)
299 highbd_sadMxNxK(8, 8, 8)
300 highbd_sadMxNx4D(8, 8)
301
302 // 8x4
303 highbd_sadMxN(8, 4)
304 highbd_sadMxNxK(8, 4, 8)
305 highbd_sadMxNx4D(8, 4)
306
307 // 4x8
308 highbd_sadMxN(4, 8)
309 highbd_sadMxNxK(4, 8, 8)
310 highbd_sadMxNx4D(4, 8)
311
312 // 4x4
313 highbd_sadMxN(4, 4)
314 highbd_sadMxNxK(4, 4, 3)
315 highbd_sadMxNxK(4, 4, 8)
316 highbd_sadMxNx4D(4, 4)
317
318 #endif // CONFIG_VP9_HIGHBITDEPTH
319