xref: /aosp_15_r20/external/libvpx/vpx_dsp/sad.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
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. */
sad(const uint8_t * src_ptr,int src_stride,const uint8_t * ref_ptr,int ref_stride,int width,int height)20 static INLINE unsigned int sad(const uint8_t *src_ptr, int src_stride,
21                                const uint8_t *ref_ptr, int ref_stride,
22                                int width, int height) {
23   int y, x;
24   unsigned int sad = 0;
25 
26   for (y = 0; y < height; y++) {
27     for (x = 0; x < width; x++) sad += abs(src_ptr[x] - ref_ptr[x]);
28 
29     src_ptr += src_stride;
30     ref_ptr += ref_stride;
31   }
32   return sad;
33 }
34 
35 #define sadMxN(m, n)                                                          \
36   unsigned int vpx_sad##m##x##n##_c(const uint8_t *src_ptr, int src_stride,   \
37                                     const uint8_t *ref_ptr, int ref_stride) { \
38     return sad(src_ptr, src_stride, ref_ptr, ref_stride, m, n);               \
39   }                                                                           \
40   unsigned int vpx_sad##m##x##n##_avg_c(                                      \
41       const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr,         \
42       int ref_stride, const uint8_t *second_pred) {                           \
43     DECLARE_ALIGNED(32, uint8_t, comp_pred[m * n]);                           \
44     vpx_comp_avg_pred_c(comp_pred, second_pred, m, n, ref_ptr, ref_stride);   \
45     return sad(src_ptr, src_stride, comp_pred, m, m, n);                      \
46   }                                                                           \
47   unsigned int vpx_sad_skip_##m##x##n##_c(                                    \
48       const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr,         \
49       int ref_stride) {                                                       \
50     return 2 * sad(src_ptr, 2 * src_stride, ref_ptr, 2 * ref_stride, (m),     \
51                    (n / 2));                                                  \
52   }
53 
54 // Compare |src_ptr| to 4 distinct references in |ref_array[4]|
55 #define sadMxNx4D(m, n)                                                        \
56   void vpx_sad##m##x##n##x4d_c(const uint8_t *src_ptr, int src_stride,         \
57                                const uint8_t *const ref_array[4],              \
58                                int ref_stride, uint32_t sad_array[4]) {        \
59     int i;                                                                     \
60     for (i = 0; i < 4; ++i)                                                    \
61       sad_array[i] =                                                           \
62           vpx_sad##m##x##n##_c(src_ptr, src_stride, ref_array[i], ref_stride); \
63   }                                                                            \
64   void vpx_sad_skip_##m##x##n##x4d_c(const uint8_t *src_ptr, int src_stride,   \
65                                      const uint8_t *const ref_array[4],        \
66                                      int ref_stride, uint32_t sad_array[4]) {  \
67     int i;                                                                     \
68     for (i = 0; i < 4; ++i) {                                                  \
69       sad_array[i] = 2 * sad(src_ptr, 2 * src_stride, ref_array[i],            \
70                              2 * ref_stride, (m), (n / 2));                    \
71     }                                                                          \
72   }
73 
74 /* clang-format off */
75 // 64x64
76 sadMxN(64, 64)
77 sadMxNx4D(64, 64)
78 
79 // 64x32
80 sadMxN(64, 32)
81 sadMxNx4D(64, 32)
82 
83 // 32x64
84 sadMxN(32, 64)
85 sadMxNx4D(32, 64)
86 
87 // 32x32
88 sadMxN(32, 32)
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 sadMxNx4D(16, 16)
102 
103 // 16x8
104 sadMxN(16, 8)
105 sadMxNx4D(16, 8)
106 
107 // 8x16
108 sadMxN(8, 16)
109 sadMxNx4D(8, 16)
110 
111 // 8x8
112 sadMxN(8, 8)
113 sadMxNx4D(8, 8)
114 
115 // 8x4
116 sadMxN(8, 4)
117 sadMxNx4D(8, 4)
118 
119 // 4x8
120 sadMxN(4, 8)
121 sadMxNx4D(4, 8)
122 
123 // 4x4
124 sadMxN(4, 4)
125 sadMxNx4D(4, 4)
126 /* clang-format on */
127 
128 #if CONFIG_VP9_HIGHBITDEPTH
129         static INLINE
highbd_sad(const uint8_t * src8_ptr,int src_stride,const uint8_t * ref8_ptr,int ref_stride,int width,int height)130     unsigned int highbd_sad(const uint8_t *src8_ptr, int src_stride,
131                             const uint8_t *ref8_ptr, int ref_stride, int width,
132                             int height) {
133   int y, x;
134   unsigned int sad = 0;
135   const uint16_t *src = CONVERT_TO_SHORTPTR(src8_ptr);
136   const uint16_t *ref_ptr = CONVERT_TO_SHORTPTR(ref8_ptr);
137   for (y = 0; y < height; y++) {
138     for (x = 0; x < width; x++) sad += abs(src[x] - ref_ptr[x]);
139 
140     src += src_stride;
141     ref_ptr += ref_stride;
142   }
143   return sad;
144 }
145 
highbd_sadb(const uint8_t * src8_ptr,int src_stride,const uint16_t * ref_ptr,int ref_stride,int width,int height)146 static INLINE unsigned int highbd_sadb(const uint8_t *src8_ptr, int src_stride,
147                                        const uint16_t *ref_ptr, int ref_stride,
148                                        int width, int height) {
149   int y, x;
150   unsigned int sad = 0;
151   const uint16_t *src = CONVERT_TO_SHORTPTR(src8_ptr);
152   for (y = 0; y < height; y++) {
153     for (x = 0; x < width; x++) sad += abs(src[x] - ref_ptr[x]);
154 
155     src += src_stride;
156     ref_ptr += ref_stride;
157   }
158   return sad;
159 }
160 
161 #define highbd_sadMxN(m, n)                                                    \
162   unsigned int vpx_highbd_sad##m##x##n##_c(                                    \
163       const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr,          \
164       int ref_stride) {                                                        \
165     return highbd_sad(src_ptr, src_stride, ref_ptr, ref_stride, m, n);         \
166   }                                                                            \
167   unsigned int vpx_highbd_sad##m##x##n##_avg_c(                                \
168       const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr,          \
169       int ref_stride, const uint8_t *second_pred) {                            \
170     DECLARE_ALIGNED(16, uint16_t, comp_pred[m * n]);                           \
171     vpx_highbd_comp_avg_pred_c(comp_pred, CONVERT_TO_SHORTPTR(second_pred), m, \
172                                n, CONVERT_TO_SHORTPTR(ref_ptr), ref_stride);   \
173     return highbd_sadb(src_ptr, src_stride, comp_pred, m, m, n);               \
174   }                                                                            \
175   unsigned int vpx_highbd_sad_skip_##m##x##n##_c(                              \
176       const uint8_t *src, int src_stride, const uint8_t *ref,                  \
177       int ref_stride) {                                                        \
178     return 2 *                                                                 \
179            highbd_sad(src, 2 * src_stride, ref, 2 * ref_stride, (m), (n / 2)); \
180   }
181 
182 #define highbd_sadMxNx4D(m, n)                                                 \
183   void vpx_highbd_sad##m##x##n##x4d_c(const uint8_t *src_ptr, int src_stride,  \
184                                       const uint8_t *const ref_array[4],       \
185                                       int ref_stride, uint32_t sad_array[4]) { \
186     int i;                                                                     \
187     for (i = 0; i < 4; ++i) {                                                  \
188       sad_array[i] = vpx_highbd_sad##m##x##n##_c(src_ptr, src_stride,          \
189                                                  ref_array[i], ref_stride);    \
190     }                                                                          \
191   }                                                                            \
192   void vpx_highbd_sad_skip_##m##x##n##x4d_c(                                   \
193       const uint8_t *src, int src_stride, const uint8_t *const ref_array[4],   \
194       int ref_stride, uint32_t sad_array[4]) {                                 \
195     int i;                                                                     \
196     for (i = 0; i < 4; ++i) {                                                  \
197       sad_array[i] = vpx_highbd_sad_skip_##m##x##n##_c(                        \
198           src, src_stride, ref_array[i], ref_stride);                          \
199     }                                                                          \
200   }
201 
202 /* clang-format off */
203 // 64x64
204 highbd_sadMxN(64, 64)
205 highbd_sadMxNx4D(64, 64)
206 
207 // 64x32
208 highbd_sadMxN(64, 32)
209 highbd_sadMxNx4D(64, 32)
210 
211 // 32x64
212 highbd_sadMxN(32, 64)
213 highbd_sadMxNx4D(32, 64)
214 
215 // 32x32
216 highbd_sadMxN(32, 32)
217 highbd_sadMxNx4D(32, 32)
218 
219 // 32x16
220 highbd_sadMxN(32, 16)
221 highbd_sadMxNx4D(32, 16)
222 
223 // 16x32
224 highbd_sadMxN(16, 32)
225 highbd_sadMxNx4D(16, 32)
226 
227 // 16x16
228 highbd_sadMxN(16, 16)
229 highbd_sadMxNx4D(16, 16)
230 
231 // 16x8
232 highbd_sadMxN(16, 8)
233 highbd_sadMxNx4D(16, 8)
234 
235 // 8x16
236 highbd_sadMxN(8, 16)
237 highbd_sadMxNx4D(8, 16)
238 
239 // 8x8
240 highbd_sadMxN(8, 8)
241 highbd_sadMxNx4D(8, 8)
242 
243 // 8x4
244 highbd_sadMxN(8, 4)
245 highbd_sadMxNx4D(8, 4)
246 
247 // 4x8
248 highbd_sadMxN(4, 8)
249 highbd_sadMxNx4D(4, 8)
250 
251 // 4x4
252 highbd_sadMxN(4, 4)
253 highbd_sadMxNx4D(4, 4)
254 /* clang-format on */
255 
256 #endif  // CONFIG_VP9_HIGHBITDEPTH
257