]> granicus.if.org Git - libvpx/blob - vpx_dsp/sad.c
Merge "block error avx2: sum in 32 bits when possible"
[libvpx] / vpx_dsp / sad.c
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. */
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
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
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