2 * Copyright (c) 2015 The WebM project authors. All Rights Reserved.
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.
13 #include "./vpx_config.h"
14 #include "./vpx_dsp_rtcd.h"
16 #include "vpx/vpx_integer.h"
17 #include "vpx_ports/mem.h"
19 /* Sum the difference between every corresponding element of the buffers. */
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
) {
26 for (y
= 0; y
< height
; y
++) {
27 for (x
= 0; x
< width
; x
++)
28 sad
+= abs(a
[x
] - b
[x
]);
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.
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
) {
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);
58 #if CONFIG_VP9_HIGHBITDEPTH
59 static INLINE
void highbd_avg_pred(uint16_t *comp_pred
, const uint8_t *pred8
,
60 int width
, int height
, const uint8_t *ref8
,
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);
75 #endif // CONFIG_VP9_HIGHBITDEPTH
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); \
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); \
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) { \
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); \
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) { \
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); \
179 #if CONFIG_VP9_HIGHBITDEPTH
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
) {
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
]);
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
) {
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
]);
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); \
218 unsigned int vpx_highbd_sad##m##x##n##_avg_c(const uint8_t *src, \
220 const uint8_t *ref, \
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); \
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) { \
233 for (i = 0; i < k; ++i) { \
234 sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, &ref_array[i], \
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) { \
244 for (i = 0; i < 4; ++i) { \
245 sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, ref_array[i], \
251 highbd_sadMxN(64, 64)
252 highbd_sadMxNxK(64, 64, 3)
253 highbd_sadMxNxK(64, 64, 8)
254 highbd_sadMxNx4D(64, 64)
257 highbd_sadMxN(64, 32)
258 highbd_sadMxNx4D(64, 32)
261 highbd_sadMxN(32, 64)
262 highbd_sadMxNx4D(32, 64)
265 highbd_sadMxN(32, 32)
266 highbd_sadMxNxK(32, 32, 3)
267 highbd_sadMxNxK(32, 32, 8)
268 highbd_sadMxNx4D(32, 32)
271 highbd_sadMxN(32, 16)
272 highbd_sadMxNx4D(32, 16)
275 highbd_sadMxN(16, 32)
276 highbd_sadMxNx4D(16, 32)
279 highbd_sadMxN(16, 16)
280 highbd_sadMxNxK(16, 16, 3)
281 highbd_sadMxNxK(16, 16, 8)
282 highbd_sadMxNx4D(16, 16)
286 highbd_sadMxNxK(16, 8, 3)
287 highbd_sadMxNxK(16, 8, 8)
288 highbd_sadMxNx4D(16, 8)
292 highbd_sadMxNxK(8, 16, 3)
293 highbd_sadMxNxK(8, 16, 8)
294 highbd_sadMxNx4D(8, 16)
298 highbd_sadMxNxK(8, 8, 3)
299 highbd_sadMxNxK(8, 8, 8)
300 highbd_sadMxNx4D(8, 8)
304 highbd_sadMxNxK(8, 4, 8)
305 highbd_sadMxNx4D(8, 4)
309 highbd_sadMxNxK(4, 8, 8)
310 highbd_sadMxNx4D(4, 8)
314 highbd_sadMxNxK(4, 4, 3)
315 highbd_sadMxNxK(4, 4, 8)
316 highbd_sadMxNx4D(4, 4)
318 #endif // CONFIG_VP9_HIGHBITDEPTH