Line data Source code
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 "./aom_config.h"
15 : #include "./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. */
22 0 : 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 0 : unsigned int sad = 0;
26 :
27 0 : for (y = 0; y < height; y++) {
28 0 : for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
29 :
30 0 : a += a_stride;
31 0 : b += b_stride;
32 : }
33 0 : return sad;
34 : }
35 :
36 : #define sadMxN(m, n) \
37 : unsigned int aom_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
38 : const uint8_t *ref, int ref_stride) { \
39 : return sad(src, src_stride, ref, ref_stride, m, n); \
40 : } \
41 : unsigned int aom_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride, \
42 : const uint8_t *ref, int ref_stride, \
43 : const uint8_t *second_pred) { \
44 : uint8_t comp_pred[m * n]; \
45 : aom_comp_avg_pred_c(comp_pred, second_pred, m, n, ref, ref_stride); \
46 : return sad(src, src_stride, comp_pred, m, m, n); \
47 : }
48 :
49 : // depending on call sites, pass **ref_array to avoid & in subsequent call and
50 : // de-dup with 4D below.
51 : #define sadMxNxK(m, n, k) \
52 : void aom_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride, \
53 : const uint8_t *ref_array, int ref_stride, \
54 : uint32_t *sad_array) { \
55 : int i; \
56 : for (i = 0; i < k; ++i) \
57 : sad_array[i] = \
58 : aom_sad##m##x##n##_c(src, src_stride, &ref_array[i], ref_stride); \
59 : }
60 :
61 : // This appears to be equivalent to the above when k == 4 and refs is const
62 : #define sadMxNx4D(m, n) \
63 : void aom_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
64 : const uint8_t *const ref_array[], \
65 : int ref_stride, uint32_t *sad_array) { \
66 : int i; \
67 : for (i = 0; i < 4; ++i) \
68 : sad_array[i] = \
69 : aom_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \
70 : }
71 :
72 : /* clang-format off */
73 : #if CONFIG_AV1 && CONFIG_EXT_PARTITION
74 : // 128x128
75 : sadMxN(128, 128)
76 : sadMxNxK(128, 128, 3)
77 : sadMxNxK(128, 128, 8)
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 : #endif // CONFIG_AV1 && CONFIG_EXT_PARTITION
88 :
89 : // 64x64
90 0 : sadMxN(64, 64)
91 0 : sadMxNxK(64, 64, 3)
92 0 : sadMxNxK(64, 64, 8)
93 0 : sadMxNx4D(64, 64)
94 :
95 : // 64x32
96 0 : sadMxN(64, 32)
97 0 : sadMxNx4D(64, 32)
98 :
99 : // 32x64
100 0 : sadMxN(32, 64)
101 0 : sadMxNx4D(32, 64)
102 :
103 : // 32x32
104 0 : sadMxN(32, 32)
105 0 : sadMxNxK(32, 32, 3)
106 0 : sadMxNxK(32, 32, 8)
107 0 : sadMxNx4D(32, 32)
108 :
109 : // 32x16
110 0 : sadMxN(32, 16)
111 0 : sadMxNx4D(32, 16)
112 :
113 : // 16x32
114 0 : sadMxN(16, 32)
115 0 : sadMxNx4D(16, 32)
116 :
117 : // 16x16
118 0 : sadMxN(16, 16)
119 0 : sadMxNxK(16, 16, 3)
120 0 : sadMxNxK(16, 16, 8)
121 0 : sadMxNx4D(16, 16)
122 :
123 : // 16x8
124 0 : sadMxN(16, 8)
125 0 : sadMxNxK(16, 8, 3)
126 0 : sadMxNxK(16, 8, 8)
127 0 : sadMxNx4D(16, 8)
128 :
129 : // 8x16
130 0 : sadMxN(8, 16)
131 0 : sadMxNxK(8, 16, 3)
132 0 : sadMxNxK(8, 16, 8)
133 0 : sadMxNx4D(8, 16)
134 :
135 : // 8x8
136 0 : sadMxN(8, 8)
137 0 : sadMxNxK(8, 8, 3)
138 0 : sadMxNxK(8, 8, 8)
139 0 : sadMxNx4D(8, 8)
140 :
141 : // 8x4
142 0 : sadMxN(8, 4)
143 0 : sadMxNxK(8, 4, 8)
144 0 : sadMxNx4D(8, 4)
145 :
146 : // 4x8
147 0 : sadMxN(4, 8)
148 0 : sadMxNxK(4, 8, 8)
149 0 : sadMxNx4D(4, 8)
150 :
151 : // 4x4
152 0 : sadMxN(4, 4)
153 0 : sadMxNxK(4, 4, 3)
154 0 : sadMxNxK(4, 4, 8)
155 0 : sadMxNx4D(4, 4)
156 : /* clang-format on */
157 :
158 : #if CONFIG_HIGHBITDEPTH
159 : static INLINE
160 0 : unsigned int highbd_sad(const uint8_t *a8, int a_stride, const uint8_t *b8,
161 : int b_stride, int width, int height) {
162 : int y, x;
163 0 : unsigned int sad = 0;
164 0 : const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
165 0 : const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
166 0 : for (y = 0; y < height; y++) {
167 0 : for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
168 :
169 0 : a += a_stride;
170 0 : b += b_stride;
171 : }
172 0 : return sad;
173 : }
174 :
175 0 : static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
176 : const uint16_t *b, int b_stride,
177 : int width, int height) {
178 : int y, x;
179 0 : unsigned int sad = 0;
180 0 : const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
181 0 : for (y = 0; y < height; y++) {
182 0 : for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
183 :
184 0 : a += a_stride;
185 0 : b += b_stride;
186 : }
187 0 : return sad;
188 : }
189 :
190 : #define highbd_sadMxN(m, n) \
191 : unsigned int aom_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
192 : const uint8_t *ref, \
193 : int ref_stride) { \
194 : return highbd_sad(src, src_stride, ref, ref_stride, m, n); \
195 : } \
196 : unsigned int aom_highbd_sad##m##x##n##_avg_c( \
197 : const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride, \
198 : const uint8_t *second_pred) { \
199 : uint16_t comp_pred[m * n]; \
200 : aom_highbd_comp_avg_pred_c(comp_pred, second_pred, m, n, ref, ref_stride); \
201 : return highbd_sadb(src, src_stride, comp_pred, m, m, n); \
202 : }
203 :
204 : #define highbd_sadMxNxK(m, n, k) \
205 : void aom_highbd_sad##m##x##n##x##k##_c( \
206 : const uint8_t *src, int src_stride, const uint8_t *ref_array, \
207 : int ref_stride, uint32_t *sad_array) { \
208 : int i; \
209 : for (i = 0; i < k; ++i) { \
210 : sad_array[i] = aom_highbd_sad##m##x##n##_c(src, src_stride, \
211 : &ref_array[i], ref_stride); \
212 : } \
213 : }
214 :
215 : #define highbd_sadMxNx4D(m, n) \
216 : void aom_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
217 : const uint8_t *const ref_array[], \
218 : int ref_stride, uint32_t *sad_array) { \
219 : int i; \
220 : for (i = 0; i < 4; ++i) { \
221 : sad_array[i] = aom_highbd_sad##m##x##n##_c(src, src_stride, \
222 : ref_array[i], ref_stride); \
223 : } \
224 : }
225 :
226 : /* clang-format off */
227 : #if CONFIG_AV1 && CONFIG_EXT_PARTITION
228 : // 128x128
229 : highbd_sadMxN(128, 128)
230 : highbd_sadMxNxK(128, 128, 3)
231 : highbd_sadMxNxK(128, 128, 8)
232 : highbd_sadMxNx4D(128, 128)
233 :
234 : // 128x64
235 : highbd_sadMxN(128, 64)
236 : highbd_sadMxNx4D(128, 64)
237 :
238 : // 64x128
239 : highbd_sadMxN(64, 128)
240 : highbd_sadMxNx4D(64, 128)
241 : #endif // CONFIG_AV1 && CONFIG_EXT_PARTITION
242 :
243 : // 64x64
244 0 : highbd_sadMxN(64, 64)
245 0 : highbd_sadMxNxK(64, 64, 3)
246 0 : highbd_sadMxNxK(64, 64, 8)
247 0 : highbd_sadMxNx4D(64, 64)
248 :
249 : // 64x32
250 0 : highbd_sadMxN(64, 32)
251 0 : highbd_sadMxNx4D(64, 32)
252 :
253 : // 32x64
254 0 : highbd_sadMxN(32, 64)
255 0 : highbd_sadMxNx4D(32, 64)
256 :
257 : // 32x32
258 0 : highbd_sadMxN(32, 32)
259 0 : highbd_sadMxNxK(32, 32, 3)
260 0 : highbd_sadMxNxK(32, 32, 8)
261 0 : highbd_sadMxNx4D(32, 32)
262 :
263 : // 32x16
264 0 : highbd_sadMxN(32, 16)
265 0 : highbd_sadMxNx4D(32, 16)
266 :
267 : // 16x32
268 0 : highbd_sadMxN(16, 32)
269 0 : highbd_sadMxNx4D(16, 32)
270 :
271 : // 16x16
272 0 : highbd_sadMxN(16, 16)
273 0 : highbd_sadMxNxK(16, 16, 3)
274 0 : highbd_sadMxNxK(16, 16, 8)
275 0 : highbd_sadMxNx4D(16, 16)
276 :
277 : // 16x8
278 0 : highbd_sadMxN(16, 8)
279 0 : highbd_sadMxNxK(16, 8, 3)
280 0 : highbd_sadMxNxK(16, 8, 8)
281 0 : highbd_sadMxNx4D(16, 8)
282 :
283 : // 8x16
284 0 : highbd_sadMxN(8, 16)
285 0 : highbd_sadMxNxK(8, 16, 3)
286 0 : highbd_sadMxNxK(8, 16, 8)
287 0 : highbd_sadMxNx4D(8, 16)
288 :
289 : // 8x8
290 0 : highbd_sadMxN(8, 8)
291 0 : highbd_sadMxNxK(8, 8, 3)
292 0 : highbd_sadMxNxK(8, 8, 8)
293 0 : highbd_sadMxNx4D(8, 8)
294 :
295 : // 8x4
296 0 : highbd_sadMxN(8, 4)
297 0 : highbd_sadMxNxK(8, 4, 8)
298 0 : highbd_sadMxNx4D(8, 4)
299 :
300 : // 4x8
301 0 : highbd_sadMxN(4, 8)
302 0 : highbd_sadMxNxK(4, 8, 8)
303 0 : highbd_sadMxNx4D(4, 8)
304 :
305 : // 4x4
306 0 : highbd_sadMxN(4, 4)
307 0 : highbd_sadMxNxK(4, 4, 3)
308 0 : highbd_sadMxNxK(4, 4, 8)
309 0 : highbd_sadMxNx4D(4, 4)
310 : /* clang-format on */
311 : #endif // CONFIG_HIGHBITDEPTH
312 :
313 : #if CONFIG_AV1 && CONFIG_EXT_INTER
314 : static INLINE
315 0 : unsigned int masked_sad(const uint8_t *src, int src_stride,
316 : const uint8_t *a, int a_stride, const uint8_t *b,
317 : int b_stride, const uint8_t *m, int m_stride,
318 : int width, int height) {
319 : int y, x;
320 0 : unsigned int sad = 0;
321 :
322 0 : for (y = 0; y < height; y++) {
323 0 : for (x = 0; x < width; x++) {
324 0 : const uint8_t pred = AOM_BLEND_A64(m[x], a[x], b[x]);
325 0 : sad += abs(pred - src[x]);
326 : }
327 :
328 0 : src += src_stride;
329 0 : a += a_stride;
330 0 : b += b_stride;
331 0 : m += m_stride;
332 : }
333 0 : sad = (sad + 31) >> 6;
334 :
335 0 : return sad;
336 : }
337 :
338 : #define MASKSADMxN(m, n) \
339 : unsigned int aom_masked_sad##m##x##n##_c( \
340 : const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride, \
341 : const uint8_t *second_pred, const uint8_t *msk, int msk_stride, \
342 : int invert_mask) { \
343 : if (!invert_mask) \
344 : return masked_sad(src, src_stride, ref, ref_stride, second_pred, m, msk, \
345 : msk_stride, m, n); \
346 : else \
347 : return masked_sad(src, src_stride, second_pred, m, ref, ref_stride, msk, \
348 : msk_stride, m, n); \
349 : }
350 :
351 : /* clang-format off */
352 : #if CONFIG_EXT_PARTITION
353 : MASKSADMxN(128, 128)
354 : MASKSADMxN(128, 64)
355 : MASKSADMxN(64, 128)
356 : #endif // CONFIG_EXT_PARTITION
357 0 : MASKSADMxN(64, 64)
358 0 : MASKSADMxN(64, 32)
359 0 : MASKSADMxN(32, 64)
360 0 : MASKSADMxN(32, 32)
361 0 : MASKSADMxN(32, 16)
362 0 : MASKSADMxN(16, 32)
363 0 : MASKSADMxN(16, 16)
364 0 : MASKSADMxN(16, 8)
365 0 : MASKSADMxN(8, 16)
366 0 : MASKSADMxN(8, 8)
367 0 : MASKSADMxN(8, 4)
368 0 : MASKSADMxN(4, 8)
369 0 : MASKSADMxN(4, 4)
370 : /* clang-format on */
371 :
372 : #if CONFIG_HIGHBITDEPTH
373 : static INLINE
374 0 : unsigned int highbd_masked_sad(const uint8_t *src8, int src_stride,
375 : const uint8_t *a8, int a_stride,
376 : const uint8_t *b8, int b_stride,
377 : const uint8_t *m, int m_stride, int width,
378 : int height) {
379 : int y, x;
380 0 : unsigned int sad = 0;
381 0 : const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
382 0 : const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
383 0 : const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
384 :
385 0 : for (y = 0; y < height; y++) {
386 0 : for (x = 0; x < width; x++) {
387 0 : const uint16_t pred = AOM_BLEND_A64(m[x], a[x], b[x]);
388 0 : sad += abs(pred - src[x]);
389 : }
390 :
391 0 : src += src_stride;
392 0 : a += a_stride;
393 0 : b += b_stride;
394 0 : m += m_stride;
395 : }
396 0 : sad = (sad + 31) >> 6;
397 :
398 0 : return sad;
399 : }
400 :
401 : #define HIGHBD_MASKSADMXN(m, n) \
402 : unsigned int aom_highbd_masked_sad##m##x##n##_c( \
403 : const uint8_t *src8, int src_stride, const uint8_t *ref8, \
404 : int ref_stride, const uint8_t *second_pred8, const uint8_t *msk, \
405 : int msk_stride, int invert_mask) { \
406 : if (!invert_mask) \
407 : return highbd_masked_sad(src8, src_stride, ref8, ref_stride, \
408 : second_pred8, m, msk, msk_stride, m, n); \
409 : else \
410 : return highbd_masked_sad(src8, src_stride, second_pred8, m, ref8, \
411 : ref_stride, msk, msk_stride, m, n); \
412 : }
413 :
414 : #if CONFIG_EXT_PARTITION
415 : HIGHBD_MASKSADMXN(128, 128)
416 : HIGHBD_MASKSADMXN(128, 64)
417 : HIGHBD_MASKSADMXN(64, 128)
418 : #endif // CONFIG_EXT_PARTITION
419 0 : HIGHBD_MASKSADMXN(64, 64)
420 0 : HIGHBD_MASKSADMXN(64, 32)
421 0 : HIGHBD_MASKSADMXN(32, 64)
422 0 : HIGHBD_MASKSADMXN(32, 32)
423 0 : HIGHBD_MASKSADMXN(32, 16)
424 0 : HIGHBD_MASKSADMXN(16, 32)
425 0 : HIGHBD_MASKSADMXN(16, 16)
426 0 : HIGHBD_MASKSADMXN(16, 8)
427 0 : HIGHBD_MASKSADMXN(8, 16)
428 0 : HIGHBD_MASKSADMXN(8, 8)
429 0 : HIGHBD_MASKSADMXN(8, 4)
430 0 : HIGHBD_MASKSADMXN(4, 8)
431 0 : HIGHBD_MASKSADMXN(4, 4)
432 : #endif // CONFIG_HIGHBITDEPTH
433 : #endif // CONFIG_AV1 && CONFIG_EXT_INTER
434 :
435 : #if CONFIG_AV1 && CONFIG_MOTION_VAR
436 : // pre: predictor being evaluated
437 : // wsrc: target weighted prediction (has been *4096 to keep precision)
438 : // mask: 2d weights (scaled by 4096)
439 0 : static INLINE unsigned int obmc_sad(const uint8_t *pre, int pre_stride,
440 : const int32_t *wsrc, const int32_t *mask,
441 : int width, int height) {
442 : int y, x;
443 0 : unsigned int sad = 0;
444 :
445 0 : for (y = 0; y < height; y++) {
446 0 : for (x = 0; x < width; x++)
447 0 : sad += ROUND_POWER_OF_TWO(abs(wsrc[x] - pre[x] * mask[x]), 12);
448 :
449 0 : pre += pre_stride;
450 0 : wsrc += width;
451 0 : mask += width;
452 : }
453 :
454 0 : return sad;
455 : }
456 :
457 : #define OBMCSADMxN(m, n) \
458 : unsigned int aom_obmc_sad##m##x##n##_c(const uint8_t *ref, int ref_stride, \
459 : const int32_t *wsrc, \
460 : const int32_t *mask) { \
461 : return obmc_sad(ref, ref_stride, wsrc, mask, m, n); \
462 : }
463 :
464 : /* clang-format off */
465 : #if CONFIG_EXT_PARTITION
466 : OBMCSADMxN(128, 128)
467 : OBMCSADMxN(128, 64)
468 : OBMCSADMxN(64, 128)
469 : #endif // CONFIG_EXT_PARTITION
470 0 : OBMCSADMxN(64, 64)
471 0 : OBMCSADMxN(64, 32)
472 0 : OBMCSADMxN(32, 64)
473 0 : OBMCSADMxN(32, 32)
474 0 : OBMCSADMxN(32, 16)
475 0 : OBMCSADMxN(16, 32)
476 0 : OBMCSADMxN(16, 16)
477 0 : OBMCSADMxN(16, 8)
478 0 : OBMCSADMxN(8, 16)
479 0 : OBMCSADMxN(8, 8)
480 0 : OBMCSADMxN(8, 4)
481 0 : OBMCSADMxN(4, 8)
482 0 : OBMCSADMxN(4, 4)
483 : /* clang-format on */
484 :
485 : #if CONFIG_HIGHBITDEPTH
486 : static INLINE
487 0 : unsigned int highbd_obmc_sad(const uint8_t *pre8, int pre_stride,
488 : const int32_t *wsrc, const int32_t *mask,
489 : int width, int height) {
490 : int y, x;
491 0 : unsigned int sad = 0;
492 0 : const uint16_t *pre = CONVERT_TO_SHORTPTR(pre8);
493 :
494 0 : for (y = 0; y < height; y++) {
495 0 : for (x = 0; x < width; x++)
496 0 : sad += ROUND_POWER_OF_TWO(abs(wsrc[x] - pre[x] * mask[x]), 12);
497 :
498 0 : pre += pre_stride;
499 0 : wsrc += width;
500 0 : mask += width;
501 : }
502 :
503 0 : return sad;
504 : }
505 :
506 : #define HIGHBD_OBMCSADMXN(m, n) \
507 : unsigned int aom_highbd_obmc_sad##m##x##n##_c( \
508 : const uint8_t *ref, int ref_stride, const int32_t *wsrc, \
509 : const int32_t *mask) { \
510 : return highbd_obmc_sad(ref, ref_stride, wsrc, mask, m, n); \
511 : }
512 :
513 : /* clang-format off */
514 : #if CONFIG_EXT_PARTITION
515 : HIGHBD_OBMCSADMXN(128, 128)
516 : HIGHBD_OBMCSADMXN(128, 64)
517 : HIGHBD_OBMCSADMXN(64, 128)
518 : #endif // CONFIG_EXT_PARTITION
519 0 : HIGHBD_OBMCSADMXN(64, 64)
520 0 : HIGHBD_OBMCSADMXN(64, 32)
521 0 : HIGHBD_OBMCSADMXN(32, 64)
522 0 : HIGHBD_OBMCSADMXN(32, 32)
523 0 : HIGHBD_OBMCSADMXN(32, 16)
524 0 : HIGHBD_OBMCSADMXN(16, 32)
525 0 : HIGHBD_OBMCSADMXN(16, 16)
526 0 : HIGHBD_OBMCSADMXN(16, 8)
527 0 : HIGHBD_OBMCSADMXN(8, 16)
528 0 : HIGHBD_OBMCSADMXN(8, 8)
529 0 : HIGHBD_OBMCSADMXN(8, 4)
530 0 : HIGHBD_OBMCSADMXN(4, 8)
531 0 : HIGHBD_OBMCSADMXN(4, 4)
532 : /* clang-format on */
533 : #endif // CONFIG_HIGHBITDEPTH
534 : #endif // CONFIG_AV1 && CONFIG_MOTION_VAR
|