• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 * a,int a_stride,const uint8_t * b,int b_stride,int width,int height)20 static INLINE unsigned int sad(const uint8_t *a, int a_stride,
21                                const uint8_t *b, int b_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++)
28       sad += abs(a[x] - b[x]);
29 
30     a += a_stride;
31     b += b_stride;
32   }
33   return sad;
34 }
35 
36 // TODO(johannkoenig): this moved to vpx_dsp, should be able to clean this up.
37 /* Remove dependency on vp9 variance function by duplicating vp9_comp_avg_pred.
38  * The function averages every corresponding element of the buffers and stores
39  * the value in a third buffer, comp_pred.
40  * pred and comp_pred are assumed to have stride = width
41  * In the usage below comp_pred is a local array.
42  */
avg_pred(uint8_t * comp_pred,const uint8_t * pred,int width,int height,const uint8_t * ref,int ref_stride)43 static INLINE void avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,
44                             int height, const uint8_t *ref, int ref_stride) {
45   int i, j;
46 
47   for (i = 0; i < height; i++) {
48     for (j = 0; j < width; j++) {
49       const int tmp = pred[j] + ref[j];
50       comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
51     }
52     comp_pred += width;
53     pred += width;
54     ref += ref_stride;
55   }
56 }
57 
58 #if CONFIG_VP9_HIGHBITDEPTH
highbd_avg_pred(uint16_t * comp_pred,const uint8_t * pred8,int width,int height,const uint8_t * ref8,int ref_stride)59 static INLINE void highbd_avg_pred(uint16_t *comp_pred, const uint8_t *pred8,
60                                    int width, int height, const uint8_t *ref8,
61                                    int ref_stride) {
62   int i, j;
63   uint16_t *pred = CONVERT_TO_SHORTPTR(pred8);
64   uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
65   for (i = 0; i < height; i++) {
66     for (j = 0; j < width; j++) {
67       const int tmp = pred[j] + ref[j];
68       comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
69     }
70     comp_pred += width;
71     pred += width;
72     ref += ref_stride;
73   }
74 }
75 #endif  // CONFIG_VP9_HIGHBITDEPTH
76 
77 #define sadMxN(m, n) \
78 unsigned int vpx_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
79                                   const uint8_t *ref, int ref_stride) { \
80   return sad(src, src_stride, ref, ref_stride, m, n); \
81 } \
82 unsigned int vpx_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride, \
83                                       const uint8_t *ref, int ref_stride, \
84                                       const uint8_t *second_pred) { \
85   uint8_t comp_pred[m * n]; \
86   avg_pred(comp_pred, second_pred, m, n, ref, ref_stride); \
87   return sad(src, src_stride, comp_pred, m, m, n); \
88 }
89 
90 // depending on call sites, pass **ref_array to avoid & in subsequent call and
91 // de-dup with 4D below.
92 #define sadMxNxK(m, n, k) \
93 void vpx_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride, \
94                                 const uint8_t *ref_array, int ref_stride, \
95                                 uint32_t *sad_array) { \
96   int i; \
97   for (i = 0; i < k; ++i) \
98     sad_array[i] = vpx_sad##m##x##n##_c(src, src_stride, &ref_array[i], ref_stride); \
99 }
100 
101 // This appears to be equivalent to the above when k == 4 and refs is const
102 #define sadMxNx4D(m, n) \
103 void vpx_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
104                              const uint8_t *const ref_array[], int ref_stride, \
105                              uint32_t *sad_array) { \
106   int i; \
107   for (i = 0; i < 4; ++i) \
108     sad_array[i] = vpx_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \
109 }
110 
111 // 64x64
112 sadMxN(64, 64)
113 sadMxNxK(64, 64, 3)
114 sadMxNxK(64, 64, 8)
115 sadMxNx4D(64, 64)
116 
117 // 64x32
118 sadMxN(64, 32)
119 sadMxNx4D(64, 32)
120 
121 // 32x64
122 sadMxN(32, 64)
123 sadMxNx4D(32, 64)
124 
125 // 32x32
126 sadMxN(32, 32)
127 sadMxNxK(32, 32, 3)
128 sadMxNxK(32, 32, 8)
129 sadMxNx4D(32, 32)
130 
131 // 32x16
132 sadMxN(32, 16)
133 sadMxNx4D(32, 16)
134 
135 // 16x32
136 sadMxN(16, 32)
137 sadMxNx4D(16, 32)
138 
139 // 16x16
140 sadMxN(16, 16)
141 sadMxNxK(16, 16, 3)
142 sadMxNxK(16, 16, 8)
143 sadMxNx4D(16, 16)
144 
145 // 16x8
146 sadMxN(16, 8)
147 sadMxNxK(16, 8, 3)
148 sadMxNxK(16, 8, 8)
149 sadMxNx4D(16, 8)
150 
151 // 8x16
152 sadMxN(8, 16)
153 sadMxNxK(8, 16, 3)
154 sadMxNxK(8, 16, 8)
155 sadMxNx4D(8, 16)
156 
157 // 8x8
158 sadMxN(8, 8)
159 sadMxNxK(8, 8, 3)
160 sadMxNxK(8, 8, 8)
161 sadMxNx4D(8, 8)
162 
163 // 8x4
164 sadMxN(8, 4)
165 sadMxNxK(8, 4, 8)
166 sadMxNx4D(8, 4)
167 
168 // 4x8
169 sadMxN(4, 8)
170 sadMxNxK(4, 8, 8)
171 sadMxNx4D(4, 8)
172 
173 // 4x4
174 sadMxN(4, 4)
175 sadMxNxK(4, 4, 3)
176 sadMxNxK(4, 4, 8)
177 sadMxNx4D(4, 4)
178 
179 #if CONFIG_VP9_HIGHBITDEPTH
highbd_sad(const uint8_t * a8,int a_stride,const uint8_t * b8,int b_stride,int width,int height)180 static INLINE unsigned int highbd_sad(const uint8_t *a8, int a_stride,
181                                       const uint8_t *b8, int b_stride,
182                                       int width, int height) {
183   int y, x;
184   unsigned int sad = 0;
185   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
186   const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
187   for (y = 0; y < height; y++) {
188     for (x = 0; x < width; x++)
189       sad += abs(a[x] - b[x]);
190 
191     a += a_stride;
192     b += b_stride;
193   }
194   return sad;
195 }
196 
highbd_sadb(const uint8_t * a8,int a_stride,const uint16_t * b,int b_stride,int width,int height)197 static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
198                                        const uint16_t *b, int b_stride,
199                                        int width, int height) {
200   int y, x;
201   unsigned int sad = 0;
202   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
203   for (y = 0; y < height; y++) {
204     for (x = 0; x < width; x++)
205       sad += abs(a[x] - b[x]);
206 
207     a += a_stride;
208     b += b_stride;
209   }
210   return sad;
211 }
212 
213 #define highbd_sadMxN(m, n) \
214 unsigned int vpx_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
215                                          const uint8_t *ref, int ref_stride) { \
216   return highbd_sad(src, src_stride, ref, ref_stride, m, n); \
217 } \
218 unsigned int vpx_highbd_sad##m##x##n##_avg_c(const uint8_t *src, \
219                                              int src_stride, \
220                                              const uint8_t *ref, \
221                                              int ref_stride, \
222                                              const uint8_t *second_pred) { \
223   uint16_t comp_pred[m * n]; \
224   highbd_avg_pred(comp_pred, second_pred, m, n, ref, ref_stride); \
225   return highbd_sadb(src, src_stride, comp_pred, m, m, n); \
226 }
227 
228 #define highbd_sadMxNxK(m, n, k) \
229 void vpx_highbd_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride, \
230                                        const uint8_t *ref_array, int ref_stride, \
231                                        uint32_t *sad_array) { \
232   int i; \
233   for (i = 0; i < k; ++i) { \
234     sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, &ref_array[i], \
235                                                ref_stride); \
236   } \
237 }
238 
239 #define highbd_sadMxNx4D(m, n) \
240 void vpx_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \
241                                     const uint8_t *const ref_array[], \
242                                     int ref_stride, uint32_t *sad_array) { \
243   int i; \
244   for (i = 0; i < 4; ++i) { \
245     sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, ref_array[i], \
246                                                ref_stride); \
247   } \
248 }
249 
250 // 64x64
251 highbd_sadMxN(64, 64)
252 highbd_sadMxNxK(64, 64, 3)
253 highbd_sadMxNxK(64, 64, 8)
254 highbd_sadMxNx4D(64, 64)
255 
256 // 64x32
257 highbd_sadMxN(64, 32)
258 highbd_sadMxNx4D(64, 32)
259 
260 // 32x64
261 highbd_sadMxN(32, 64)
262 highbd_sadMxNx4D(32, 64)
263 
264 // 32x32
265 highbd_sadMxN(32, 32)
266 highbd_sadMxNxK(32, 32, 3)
267 highbd_sadMxNxK(32, 32, 8)
268 highbd_sadMxNx4D(32, 32)
269 
270 // 32x16
271 highbd_sadMxN(32, 16)
272 highbd_sadMxNx4D(32, 16)
273 
274 // 16x32
275 highbd_sadMxN(16, 32)
276 highbd_sadMxNx4D(16, 32)
277 
278 // 16x16
279 highbd_sadMxN(16, 16)
280 highbd_sadMxNxK(16, 16, 3)
281 highbd_sadMxNxK(16, 16, 8)
282 highbd_sadMxNx4D(16, 16)
283 
284 // 16x8
285 highbd_sadMxN(16, 8)
286 highbd_sadMxNxK(16, 8, 3)
287 highbd_sadMxNxK(16, 8, 8)
288 highbd_sadMxNx4D(16, 8)
289 
290 // 8x16
291 highbd_sadMxN(8, 16)
292 highbd_sadMxNxK(8, 16, 3)
293 highbd_sadMxNxK(8, 16, 8)
294 highbd_sadMxNx4D(8, 16)
295 
296 // 8x8
297 highbd_sadMxN(8, 8)
298 highbd_sadMxNxK(8, 8, 3)
299 highbd_sadMxNxK(8, 8, 8)
300 highbd_sadMxNx4D(8, 8)
301 
302 // 8x4
303 highbd_sadMxN(8, 4)
304 highbd_sadMxNxK(8, 4, 8)
305 highbd_sadMxNx4D(8, 4)
306 
307 // 4x8
308 highbd_sadMxN(4, 8)
309 highbd_sadMxNxK(4, 8, 8)
310 highbd_sadMxNx4D(4, 8)
311 
312 // 4x4
313 highbd_sadMxN(4, 4)
314 highbd_sadMxNxK(4, 4, 3)
315 highbd_sadMxNxK(4, 4, 8)
316 highbd_sadMxNx4D(4, 4)
317 
318 #endif  // CONFIG_VP9_HIGHBITDEPTH
319