sad.c revision 7ce0a1d1337c01056ba24006efab21f00e179e04
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. */
20static 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 */
43static 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
59static 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) \
78unsigned 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} \
82unsigned 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) \
93void 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) \
103void 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
112sadMxN(64, 64)
113sadMxNxK(64, 64, 3)
114sadMxNxK(64, 64, 8)
115sadMxNx4D(64, 64)
116
117// 64x32
118sadMxN(64, 32)
119sadMxNx4D(64, 32)
120
121// 32x64
122sadMxN(32, 64)
123sadMxNx4D(32, 64)
124
125// 32x32
126sadMxN(32, 32)
127sadMxNxK(32, 32, 3)
128sadMxNxK(32, 32, 8)
129sadMxNx4D(32, 32)
130
131// 32x16
132sadMxN(32, 16)
133sadMxNx4D(32, 16)
134
135// 16x32
136sadMxN(16, 32)
137sadMxNx4D(16, 32)
138
139// 16x16
140sadMxN(16, 16)
141sadMxNxK(16, 16, 3)
142sadMxNxK(16, 16, 8)
143sadMxNx4D(16, 16)
144
145// 16x8
146sadMxN(16, 8)
147sadMxNxK(16, 8, 3)
148sadMxNxK(16, 8, 8)
149sadMxNx4D(16, 8)
150
151// 8x16
152sadMxN(8, 16)
153sadMxNxK(8, 16, 3)
154sadMxNxK(8, 16, 8)
155sadMxNx4D(8, 16)
156
157// 8x8
158sadMxN(8, 8)
159sadMxNxK(8, 8, 3)
160sadMxNxK(8, 8, 8)
161sadMxNx4D(8, 8)
162
163// 8x4
164sadMxN(8, 4)
165sadMxNxK(8, 4, 8)
166sadMxNx4D(8, 4)
167
168// 4x8
169sadMxN(4, 8)
170sadMxNxK(4, 8, 8)
171sadMxNx4D(4, 8)
172
173// 4x4
174sadMxN(4, 4)
175sadMxNxK(4, 4, 3)
176sadMxNxK(4, 4, 8)
177sadMxNx4D(4, 4)
178
179#if CONFIG_VP9_HIGHBITDEPTH
180static 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
197static 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) \
214unsigned 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} \
218unsigned 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) \
229void 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) \
240void 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
251highbd_sadMxN(64, 64)
252highbd_sadMxNxK(64, 64, 3)
253highbd_sadMxNxK(64, 64, 8)
254highbd_sadMxNx4D(64, 64)
255
256// 64x32
257highbd_sadMxN(64, 32)
258highbd_sadMxNx4D(64, 32)
259
260// 32x64
261highbd_sadMxN(32, 64)
262highbd_sadMxNx4D(32, 64)
263
264// 32x32
265highbd_sadMxN(32, 32)
266highbd_sadMxNxK(32, 32, 3)
267highbd_sadMxNxK(32, 32, 8)
268highbd_sadMxNx4D(32, 32)
269
270// 32x16
271highbd_sadMxN(32, 16)
272highbd_sadMxNx4D(32, 16)
273
274// 16x32
275highbd_sadMxN(16, 32)
276highbd_sadMxNx4D(16, 32)
277
278// 16x16
279highbd_sadMxN(16, 16)
280highbd_sadMxNxK(16, 16, 3)
281highbd_sadMxNxK(16, 16, 8)
282highbd_sadMxNx4D(16, 16)
283
284// 16x8
285highbd_sadMxN(16, 8)
286highbd_sadMxNxK(16, 8, 3)
287highbd_sadMxNxK(16, 8, 8)
288highbd_sadMxNx4D(16, 8)
289
290// 8x16
291highbd_sadMxN(8, 16)
292highbd_sadMxNxK(8, 16, 3)
293highbd_sadMxNxK(8, 16, 8)
294highbd_sadMxNx4D(8, 16)
295
296// 8x8
297highbd_sadMxN(8, 8)
298highbd_sadMxNxK(8, 8, 3)
299highbd_sadMxNxK(8, 8, 8)
300highbd_sadMxNx4D(8, 8)
301
302// 8x4
303highbd_sadMxN(8, 4)
304highbd_sadMxNxK(8, 4, 8)
305highbd_sadMxNx4D(8, 4)
306
307// 4x8
308highbd_sadMxN(4, 8)
309highbd_sadMxNxK(4, 8, 8)
310highbd_sadMxNx4D(4, 8)
311
312// 4x4
313highbd_sadMxN(4, 4)
314highbd_sadMxNxK(4, 4, 3)
315highbd_sadMxNxK(4, 4, 8)
316highbd_sadMxNx4D(4, 4)
317
318#endif  // CONFIG_VP9_HIGHBITDEPTH
319