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