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. */
20static 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
72sadMxN(64, 64)
73sadMxNxK(64, 64, 3)
74sadMxNxK(64, 64, 8)
75sadMxNx4D(64, 64)
76
77// 64x32
78sadMxN(64, 32)
79sadMxNx4D(64, 32)
80
81// 32x64
82sadMxN(32, 64)
83sadMxNx4D(32, 64)
84
85// 32x32
86sadMxN(32, 32)
87sadMxNxK(32, 32, 3)
88sadMxNxK(32, 32, 8)
89sadMxNx4D(32, 32)
90
91// 32x16
92sadMxN(32, 16)
93sadMxNx4D(32, 16)
94
95// 16x32
96sadMxN(16, 32)
97sadMxNx4D(16, 32)
98
99// 16x16
100sadMxN(16, 16)
101sadMxNxK(16, 16, 3)
102sadMxNxK(16, 16, 8)
103sadMxNx4D(16, 16)
104
105// 16x8
106sadMxN(16, 8)
107sadMxNxK(16, 8, 3)
108sadMxNxK(16, 8, 8)
109sadMxNx4D(16, 8)
110
111// 8x16
112sadMxN(8, 16)
113sadMxNxK(8, 16, 3)
114sadMxNxK(8, 16, 8)
115sadMxNx4D(8, 16)
116
117// 8x8
118sadMxN(8, 8)
119sadMxNxK(8, 8, 3)
120sadMxNxK(8, 8, 8)
121sadMxNx4D(8, 8)
122
123// 8x4
124sadMxN(8, 4)
125sadMxNxK(8, 4, 8)
126sadMxNx4D(8, 4)
127
128// 4x8
129sadMxN(4, 8)
130sadMxNxK(4, 8, 8)
131sadMxNx4D(4, 8)
132
133// 4x4
134sadMxN(4, 4)
135sadMxNxK(4, 4, 3)
136sadMxNxK(4, 4, 8)
137sadMxNx4D(4, 4)
138/* clang-format on */
139
140#if CONFIG_VP9_HIGHBITDEPTH
141        static INLINE
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
157static 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
210highbd_sadMxN(64, 64)
211highbd_sadMxNxK(64, 64, 3)
212highbd_sadMxNxK(64, 64, 8)
213highbd_sadMxNx4D(64, 64)
214
215// 64x32
216highbd_sadMxN(64, 32)
217highbd_sadMxNx4D(64, 32)
218
219// 32x64
220highbd_sadMxN(32, 64)
221highbd_sadMxNx4D(32, 64)
222
223// 32x32
224highbd_sadMxN(32, 32)
225highbd_sadMxNxK(32, 32, 3)
226highbd_sadMxNxK(32, 32, 8)
227highbd_sadMxNx4D(32, 32)
228
229// 32x16
230highbd_sadMxN(32, 16)
231highbd_sadMxNx4D(32, 16)
232
233// 16x32
234highbd_sadMxN(16, 32)
235highbd_sadMxNx4D(16, 32)
236
237// 16x16
238highbd_sadMxN(16, 16)
239highbd_sadMxNxK(16, 16, 3)
240highbd_sadMxNxK(16, 16, 8)
241highbd_sadMxNx4D(16, 16)
242
243// 16x8
244highbd_sadMxN(16, 8)
245highbd_sadMxNxK(16, 8, 3)
246highbd_sadMxNxK(16, 8, 8)
247highbd_sadMxNx4D(16, 8)
248
249// 8x16
250highbd_sadMxN(8, 16)
251highbd_sadMxNxK(8, 16, 3)
252highbd_sadMxNxK(8, 16, 8)
253highbd_sadMxNx4D(8, 16)
254
255// 8x8
256highbd_sadMxN(8, 8)
257highbd_sadMxNxK(8, 8, 3)
258highbd_sadMxNxK(8, 8, 8)
259highbd_sadMxNx4D(8, 8)
260
261// 8x4
262highbd_sadMxN(8, 4)
263highbd_sadMxNxK(8, 4, 8)
264highbd_sadMxNx4D(8, 4)
265
266// 4x8
267highbd_sadMxN(4, 8)
268highbd_sadMxNxK(4, 8, 8)
269highbd_sadMxNx4D(4, 8)
270
271// 4x4
272highbd_sadMxN(4, 4)
273highbd_sadMxNxK(4, 4, 3)
274highbd_sadMxNxK(4, 4, 8)
275highbd_sadMxNx4D(4, 4)
276/* clang-format on */
277
278#endif  // CONFIG_VP9_HIGHBITDEPTH
279