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(16, 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 
48 // depending on call sites, pass **ref_array to avoid & in subsequent call and
49 // de-dup with 4D below.
50 #define sadMxNxK(m, n, k)                                                     \
51   void vpx_sad##m##x##n##x##k##_c(const uint8_t *src_ptr, int src_stride,     \
52                                   const uint8_t *ref_ptr, int ref_stride,     \
53                                   uint32_t *sad_array) {                      \
54     int i;                                                                    \
55     for (i = 0; i < k; ++i)                                                   \
56       sad_array[i] =                                                          \
57           vpx_sad##m##x##n##_c(src_ptr, src_stride, &ref_ptr[i], ref_stride); \
58   }
59 
60 // This appears to be equivalent to the above when k == 4 and refs is const
61 #define sadMxNx4D(m, n)                                                        \
62   void vpx_sad##m##x##n##x4d_c(const uint8_t *src_ptr, int src_stride,         \
63                                const uint8_t *const ref_array[],               \
64                                int ref_stride, uint32_t *sad_array) {          \
65     int i;                                                                     \
66     for (i = 0; i < 4; ++i)                                                    \
67       sad_array[i] =                                                           \
68           vpx_sad##m##x##n##_c(src_ptr, src_stride, ref_array[i], ref_stride); \
69   }
70 
71 /* clang-format off */
72 // 64x64
73 sadMxN(64, 64)
74 sadMxNx4D(64, 64)
75 
76 // 64x32
77 sadMxN(64, 32)
78 sadMxNx4D(64, 32)
79 
80 // 32x64
81 sadMxN(32, 64)
82 sadMxNx4D(32, 64)
83 
84 // 32x32
85 sadMxN(32, 32)
86 sadMxNxK(32, 32, 8)
87 sadMxNx4D(32, 32)
88 
89 // 32x16
90 sadMxN(32, 16)
91 sadMxNx4D(32, 16)
92 
93 // 16x32
94 sadMxN(16, 32)
95 sadMxNx4D(16, 32)
96 
97 // 16x16
98 sadMxN(16, 16)
99 sadMxNxK(16, 16, 3)
100 sadMxNxK(16, 16, 8)
101 sadMxNx4D(16, 16)
102 
103 // 16x8
104 sadMxN(16, 8)
105 sadMxNxK(16, 8, 3)
106 sadMxNxK(16, 8, 8)
107 sadMxNx4D(16, 8)
108 
109 // 8x16
110 sadMxN(8, 16)
111 sadMxNxK(8, 16, 3)
112 sadMxNxK(8, 16, 8)
113 sadMxNx4D(8, 16)
114 
115 // 8x8
116 sadMxN(8, 8)
117 sadMxNxK(8, 8, 3)
118 sadMxNxK(8, 8, 8)
119 sadMxNx4D(8, 8)
120 
121 // 8x4
122 sadMxN(8, 4)
123 sadMxNx4D(8, 4)
124 
125 // 4x8
126 sadMxN(4, 8)
127 sadMxNx4D(4, 8)
128 
129 // 4x4
130 sadMxN(4, 4)
131 sadMxNxK(4, 4, 3)
132 sadMxNxK(4, 4, 8)
133 sadMxNx4D(4, 4)
134 /* clang-format on */
135 
136 #if CONFIG_VP9_HIGHBITDEPTH
137         static INLINE
highbd_sad(const uint8_t * src8_ptr,int src_stride,const uint8_t * ref8_ptr,int ref_stride,int width,int height)138     unsigned int highbd_sad(const uint8_t *src8_ptr, int src_stride,
139                             const uint8_t *ref8_ptr, int ref_stride, int width,
140                             int height) {
141   int y, x;
142   unsigned int sad = 0;
143   const uint16_t *src = CONVERT_TO_SHORTPTR(src8_ptr);
144   const uint16_t *ref_ptr = CONVERT_TO_SHORTPTR(ref8_ptr);
145   for (y = 0; y < height; y++) {
146     for (x = 0; x < width; x++) sad += abs(src[x] - ref_ptr[x]);
147 
148     src += src_stride;
149     ref_ptr += ref_stride;
150   }
151   return sad;
152 }
153 
highbd_sadb(const uint8_t * src8_ptr,int src_stride,const uint16_t * ref_ptr,int ref_stride,int width,int height)154 static INLINE unsigned int highbd_sadb(const uint8_t *src8_ptr, int src_stride,
155                                        const uint16_t *ref_ptr, int ref_stride,
156                                        int width, int height) {
157   int y, x;
158   unsigned int sad = 0;
159   const uint16_t *src = CONVERT_TO_SHORTPTR(src8_ptr);
160   for (y = 0; y < height; y++) {
161     for (x = 0; x < width; x++) sad += abs(src[x] - ref_ptr[x]);
162 
163     src += src_stride;
164     ref_ptr += ref_stride;
165   }
166   return sad;
167 }
168 
169 #define highbd_sadMxN(m, n)                                                    \
170   unsigned int vpx_highbd_sad##m##x##n##_c(                                    \
171       const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr,          \
172       int ref_stride) {                                                        \
173     return highbd_sad(src_ptr, src_stride, ref_ptr, ref_stride, m, n);         \
174   }                                                                            \
175   unsigned int vpx_highbd_sad##m##x##n##_avg_c(                                \
176       const uint8_t *src_ptr, int src_stride, const uint8_t *ref_ptr,          \
177       int ref_stride, const uint8_t *second_pred) {                            \
178     DECLARE_ALIGNED(16, uint16_t, comp_pred[m * n]);                           \
179     vpx_highbd_comp_avg_pred_c(comp_pred, CONVERT_TO_SHORTPTR(second_pred), m, \
180                                n, CONVERT_TO_SHORTPTR(ref_ptr), ref_stride);   \
181     return highbd_sadb(src_ptr, src_stride, comp_pred, m, m, n);               \
182   }
183 
184 #define highbd_sadMxNx4D(m, n)                                                \
185   void vpx_highbd_sad##m##x##n##x4d_c(const uint8_t *src_ptr, int src_stride, \
186                                       const uint8_t *const ref_array[],       \
187                                       int ref_stride, uint32_t *sad_array) {  \
188     int i;                                                                    \
189     for (i = 0; i < 4; ++i) {                                                 \
190       sad_array[i] = vpx_highbd_sad##m##x##n##_c(src_ptr, src_stride,         \
191                                                  ref_array[i], ref_stride);   \
192     }                                                                         \
193   }
194 
195 /* clang-format off */
196 // 64x64
197 highbd_sadMxN(64, 64)
198 highbd_sadMxNx4D(64, 64)
199 
200 // 64x32
201 highbd_sadMxN(64, 32)
202 highbd_sadMxNx4D(64, 32)
203 
204 // 32x64
205 highbd_sadMxN(32, 64)
206 highbd_sadMxNx4D(32, 64)
207 
208 // 32x32
209 highbd_sadMxN(32, 32)
210 highbd_sadMxNx4D(32, 32)
211 
212 // 32x16
213 highbd_sadMxN(32, 16)
214 highbd_sadMxNx4D(32, 16)
215 
216 // 16x32
217 highbd_sadMxN(16, 32)
218 highbd_sadMxNx4D(16, 32)
219 
220 // 16x16
221 highbd_sadMxN(16, 16)
222 highbd_sadMxNx4D(16, 16)
223 
224 // 16x8
225 highbd_sadMxN(16, 8)
226 highbd_sadMxNx4D(16, 8)
227 
228 // 8x16
229 highbd_sadMxN(8, 16)
230 highbd_sadMxNx4D(8, 16)
231 
232 // 8x8
233 highbd_sadMxN(8, 8)
234 highbd_sadMxNx4D(8, 8)
235 
236 // 8x4
237 highbd_sadMxN(8, 4)
238 highbd_sadMxNx4D(8, 4)
239 
240 // 4x8
241 highbd_sadMxN(4, 8)
242 highbd_sadMxNx4D(4, 8)
243 
244 // 4x4
245 highbd_sadMxN(4, 4)
246 highbd_sadMxNx4D(4, 4)
247 /* clang-format on */
248 
249 #endif  // CONFIG_VP9_HIGHBITDEPTH
250