]> granicus.if.org Git - libvpx/blob - vpx_dsp/sad.c
Merge "Add unit test to expose vp8 bug when width is set odd."
[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 sadMxNx4D(64, 64)
74
75 // 64x32
76 sadMxN(64, 32)
77 sadMxNx4D(64, 32)
78
79 // 32x64
80 sadMxN(32, 64)
81 sadMxNx4D(32, 64)
82
83 // 32x32
84 sadMxN(32, 32)
85 sadMxNx4D(32, 32)
86
87 // 32x16
88 sadMxN(32, 16)
89 sadMxNx4D(32, 16)
90
91 // 16x32
92 sadMxN(16, 32)
93 sadMxNx4D(16, 32)
94
95 // 16x16
96 sadMxN(16, 16)
97 sadMxNxK(16, 16, 3)
98 sadMxNxK(16, 16, 8)
99 sadMxNx4D(16, 16)
100
101 // 16x8
102 sadMxN(16, 8)
103 sadMxNxK(16, 8, 3)
104 sadMxNxK(16, 8, 8)
105 sadMxNx4D(16, 8)
106
107 // 8x16
108 sadMxN(8, 16)
109 sadMxNxK(8, 16, 3)
110 sadMxNxK(8, 16, 8)
111 sadMxNx4D(8, 16)
112
113 // 8x8
114 sadMxN(8, 8)
115 sadMxNxK(8, 8, 3)
116 sadMxNxK(8, 8, 8)
117 sadMxNx4D(8, 8)
118
119 // 8x4
120 sadMxN(8, 4)
121 sadMxNx4D(8, 4)
122
123 // 4x8
124 sadMxN(4, 8)
125 sadMxNx4D(4, 8)
126
127 // 4x4
128 sadMxN(4, 4)
129 sadMxNxK(4, 4, 3)
130 sadMxNxK(4, 4, 8)
131 sadMxNx4D(4, 4)
132 /* clang-format on */
133
134 #if CONFIG_VP9_HIGHBITDEPTH
135         static INLINE
136     unsigned int highbd_sad(const uint8_t *a8, int a_stride, const uint8_t *b8,
137                             int b_stride, int width, int height) {
138   int y, x;
139   unsigned int sad = 0;
140   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
141   const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
142   for (y = 0; y < height; y++) {
143     for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
144
145     a += a_stride;
146     b += b_stride;
147   }
148   return sad;
149 }
150
151 static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
152                                        const uint16_t *b, int b_stride,
153                                        int width, int height) {
154   int y, x;
155   unsigned int sad = 0;
156   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
157   for (y = 0; y < height; y++) {
158     for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
159
160     a += a_stride;
161     b += b_stride;
162   }
163   return sad;
164 }
165
166 #define highbd_sadMxN(m, n)                                                    \
167   unsigned int vpx_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
168                                            const uint8_t *ref,                 \
169                                            int ref_stride) {                   \
170     return highbd_sad(src, src_stride, ref, ref_stride, m, n);                 \
171   }                                                                            \
172   unsigned int vpx_highbd_sad##m##x##n##_avg_c(                                \
173       const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride,  \
174       const uint8_t *second_pred) {                                            \
175     DECLARE_ALIGNED(16, uint16_t, comp_pred[m * n]);                           \
176     vpx_highbd_comp_avg_pred_c(comp_pred, second_pred, m, n, ref, ref_stride); \
177     return highbd_sadb(src, src_stride, comp_pred, m, m, n);                   \
178   }
179
180 #define highbd_sadMxNx4D(m, n)                                               \
181   void vpx_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride,    \
182                                       const uint8_t *const ref_array[],      \
183                                       int ref_stride, uint32_t *sad_array) { \
184     int i;                                                                   \
185     for (i = 0; i < 4; ++i) {                                                \
186       sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride,            \
187                                                  ref_array[i], ref_stride);  \
188     }                                                                        \
189   }
190
191 /* clang-format off */
192 // 64x64
193 highbd_sadMxN(64, 64)
194 highbd_sadMxNx4D(64, 64)
195
196 // 64x32
197 highbd_sadMxN(64, 32)
198 highbd_sadMxNx4D(64, 32)
199
200 // 32x64
201 highbd_sadMxN(32, 64)
202 highbd_sadMxNx4D(32, 64)
203
204 // 32x32
205 highbd_sadMxN(32, 32)
206 highbd_sadMxNx4D(32, 32)
207
208 // 32x16
209 highbd_sadMxN(32, 16)
210 highbd_sadMxNx4D(32, 16)
211
212 // 16x32
213 highbd_sadMxN(16, 32)
214 highbd_sadMxNx4D(16, 32)
215
216 // 16x16
217 highbd_sadMxN(16, 16)
218 highbd_sadMxNx4D(16, 16)
219
220 // 16x8
221 highbd_sadMxN(16, 8)
222 highbd_sadMxNx4D(16, 8)
223
224 // 8x16
225 highbd_sadMxN(8, 16)
226 highbd_sadMxNx4D(8, 16)
227
228 // 8x8
229 highbd_sadMxN(8, 8)
230 highbd_sadMxNx4D(8, 8)
231
232 // 8x4
233 highbd_sadMxN(8, 4)
234 highbd_sadMxNx4D(8, 4)
235
236 // 4x8
237 highbd_sadMxN(4, 8)
238 highbd_sadMxNx4D(4, 8)
239
240 // 4x4
241 highbd_sadMxN(4, 4)
242 highbd_sadMxNx4D(4, 4)
243 /* clang-format on */
244
245 #endif  // CONFIG_VP9_HIGHBITDEPTH