sad.c 9.95 KB
Newer Older
John Koleszar's avatar
John Koleszar committed
1
/*
2
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved
John Koleszar's avatar
John Koleszar committed
3
 *
4 5 6 7 8 9
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
John Koleszar's avatar
John Koleszar committed
10 11 12
 */

#include <stdlib.h>
13

Adrian Grange's avatar
Adrian Grange committed
14 15
#include "./aom_config.h"
#include "./aom_dsp_rtcd.h"
16

Adrian Grange's avatar
Adrian Grange committed
17
#include "aom/aom_integer.h"
Yaowu Xu's avatar
Yaowu Xu committed
18
#include "aom_ports/mem.h"
19

Johann's avatar
Johann committed
20
/* Sum the difference between every corresponding element of the buffers. */
clang-format's avatar
clang-format committed
21 22
static INLINE unsigned int sad(const uint8_t *a, int a_stride, const uint8_t *b,
                               int b_stride, int width, int height) {
23 24 25 26
  int y, x;
  unsigned int sad = 0;

  for (y = 0; y < height; y++) {
clang-format's avatar
clang-format committed
27
    for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
28 29 30 31 32 33

    a += a_stride;
    b += b_stride;
  }
  return sad;
}
John Koleszar's avatar
John Koleszar committed
34

Adrian Grange's avatar
Adrian Grange committed
35
// TODO(johannkoenig): this moved to aom_dsp, should be able to clean this up.
Adrian Grange's avatar
Adrian Grange committed
36
/* Remove dependency on av1 variance function by duplicating av1_comp_avg_pred.
Johann's avatar
Johann committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
 * The function averages every corresponding element of the buffers and stores
 * the value in a third buffer, comp_pred.
 * pred and comp_pred are assumed to have stride = width
 * In the usage below comp_pred is a local array.
 */
static INLINE void avg_pred(uint8_t *comp_pred, const uint8_t *pred, int width,
                            int height, const uint8_t *ref, int ref_stride) {
  int i, j;

  for (i = 0; i < height; i++) {
    for (j = 0; j < width; j++) {
      const int tmp = pred[j] + ref[j];
      comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
    }
    comp_pred += width;
    pred += width;
    ref += ref_stride;
  }
}

57
#if CONFIG_AOM_HIGHBITDEPTH
Johann's avatar
Johann committed
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
static INLINE void highbd_avg_pred(uint16_t *comp_pred, const uint8_t *pred8,
                                   int width, int height, const uint8_t *ref8,
                                   int ref_stride) {
  int i, j;
  uint16_t *pred = CONVERT_TO_SHORTPTR(pred8);
  uint16_t *ref = CONVERT_TO_SHORTPTR(ref8);
  for (i = 0; i < height; i++) {
    for (j = 0; j < width; j++) {
      const int tmp = pred[j] + ref[j];
      comp_pred[j] = ROUND_POWER_OF_TWO(tmp, 1);
    }
    comp_pred += width;
    pred += width;
    ref += ref_stride;
  }
}
74
#endif  // CONFIG_AOM_HIGHBITDEPTH
Johann's avatar
Johann committed
75

clang-format's avatar
clang-format committed
76
#define sadMxN(m, n)                                                        \
Adrian Grange's avatar
Adrian Grange committed
77
  unsigned int aom_sad##m##x##n##_c(const uint8_t *src, int src_stride,     \
clang-format's avatar
clang-format committed
78 79 80
                                    const uint8_t *ref, int ref_stride) {   \
    return sad(src, src_stride, ref, ref_stride, m, n);                     \
  }                                                                         \
Adrian Grange's avatar
Adrian Grange committed
81
  unsigned int aom_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride, \
clang-format's avatar
clang-format committed
82 83 84 85 86 87
                                        const uint8_t *ref, int ref_stride, \
                                        const uint8_t *second_pred) {       \
    uint8_t comp_pred[m * n];                                               \
    avg_pred(comp_pred, second_pred, m, n, ref, ref_stride);                \
    return sad(src, src_stride, comp_pred, m, m, n);                        \
  }
88

Johann's avatar
Johann committed
89 90
// depending on call sites, pass **ref_array to avoid & in subsequent call and
// de-dup with 4D below.
clang-format's avatar
clang-format committed
91
#define sadMxNxK(m, n, k)                                                   \
Adrian Grange's avatar
Adrian Grange committed
92
  void aom_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride,       \
clang-format's avatar
clang-format committed
93 94 95 96 97
                                  const uint8_t *ref_array, int ref_stride, \
                                  uint32_t *sad_array) {                    \
    int i;                                                                  \
    for (i = 0; i < k; ++i)                                                 \
      sad_array[i] =                                                        \
Adrian Grange's avatar
Adrian Grange committed
98
          aom_sad##m##x##n##_c(src, src_stride, &ref_array[i], ref_stride); \
clang-format's avatar
clang-format committed
99
  }
100

Johann's avatar
Johann committed
101
// This appears to be equivalent to the above when k == 4 and refs is const
clang-format's avatar
clang-format committed
102
#define sadMxNx4D(m, n)                                                    \
Adrian Grange's avatar
Adrian Grange committed
103
  void aom_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride,         \
clang-format's avatar
clang-format committed
104 105 106 107 108
                               const uint8_t *const ref_array[],           \
                               int ref_stride, uint32_t *sad_array) {      \
    int i;                                                                 \
    for (i = 0; i < 4; ++i)                                                \
      sad_array[i] =                                                       \
Adrian Grange's avatar
Adrian Grange committed
109
          aom_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \
clang-format's avatar
clang-format committed
110
  }
111

clang-format's avatar
clang-format committed
112
/* clang-format off */
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
// 64x64
sadMxN(64, 64)
sadMxNxK(64, 64, 3)
sadMxNxK(64, 64, 8)
sadMxNx4D(64, 64)

// 64x32
sadMxN(64, 32)
sadMxNx4D(64, 32)

// 32x64
sadMxN(32, 64)
sadMxNx4D(32, 64)

// 32x32
sadMxN(32, 32)
sadMxNxK(32, 32, 3)
sadMxNxK(32, 32, 8)
sadMxNx4D(32, 32)

// 32x16
sadMxN(32, 16)
sadMxNx4D(32, 16)

// 16x32
sadMxN(16, 32)
sadMxNx4D(16, 32)

// 16x16
sadMxN(16, 16)
sadMxNxK(16, 16, 3)
sadMxNxK(16, 16, 8)
sadMxNx4D(16, 16)

// 16x8
sadMxN(16, 8)
sadMxNxK(16, 8, 3)
sadMxNxK(16, 8, 8)
sadMxNx4D(16, 8)

// 8x16
sadMxN(8, 16)
sadMxNxK(8, 16, 3)
sadMxNxK(8, 16, 8)
sadMxNx4D(8, 16)

// 8x8
sadMxN(8, 8)
sadMxNxK(8, 8, 3)
sadMxNxK(8, 8, 8)
sadMxNx4D(8, 8)

// 8x4
sadMxN(8, 4)
sadMxNxK(8, 4, 8)
sadMxNx4D(8, 4)

// 4x8
sadMxN(4, 8)
sadMxNxK(4, 8, 8)
sadMxNx4D(4, 8)

// 4x4
sadMxN(4, 4)
sadMxNxK(4, 4, 3)
sadMxNxK(4, 4, 8)
sadMxNx4D(4, 4)
clang-format's avatar
clang-format committed
180
/* clang-format on */
181

182
#if CONFIG_AOM_HIGHBITDEPTH
clang-format's avatar
clang-format committed
183 184 185
        static INLINE
    unsigned int highbd_sad(const uint8_t *a8, int a_stride, const uint8_t *b8,
                            int b_stride, int width, int height) {
186 187 188 189 190
  int y, x;
  unsigned int sad = 0;
  const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
  const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
  for (y = 0; y < height; y++) {
clang-format's avatar
clang-format committed
191
    for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
192 193 194 195 196 197 198

    a += a_stride;
    b += b_stride;
  }
  return sad;
}

199 200 201
static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
                                       const uint16_t *b, int b_stride,
                                       int width, int height) {
202 203 204 205
  int y, x;
  unsigned int sad = 0;
  const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
  for (y = 0; y < height; y++) {
clang-format's avatar
clang-format committed
206
    for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
207 208 209 210 211 212 213

    a += a_stride;
    b += b_stride;
  }
  return sad;
}

clang-format's avatar
clang-format committed
214
#define highbd_sadMxN(m, n)                                                    \
Adrian Grange's avatar
Adrian Grange committed
215
  unsigned int aom_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
clang-format's avatar
clang-format committed
216 217 218 219
                                           const uint8_t *ref,                 \
                                           int ref_stride) {                   \
    return highbd_sad(src, src_stride, ref, ref_stride, m, n);                 \
  }                                                                            \
Adrian Grange's avatar
Adrian Grange committed
220
  unsigned int aom_highbd_sad##m##x##n##_avg_c(                                \
clang-format's avatar
clang-format committed
221 222 223 224 225 226
      const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride,  \
      const uint8_t *second_pred) {                                            \
    uint16_t comp_pred[m * n];                                                 \
    highbd_avg_pred(comp_pred, second_pred, m, n, ref, ref_stride);            \
    return highbd_sadb(src, src_stride, comp_pred, m, m, n);                   \
  }
227

clang-format's avatar
clang-format committed
228
#define highbd_sadMxNxK(m, n, k)                                             \
Adrian Grange's avatar
Adrian Grange committed
229
  void aom_highbd_sad##m##x##n##x##k##_c(                                    \
clang-format's avatar
clang-format committed
230 231 232 233
      const uint8_t *src, int src_stride, const uint8_t *ref_array,          \
      int ref_stride, uint32_t *sad_array) {                                 \
    int i;                                                                   \
    for (i = 0; i < k; ++i) {                                                \
Adrian Grange's avatar
Adrian Grange committed
234
      sad_array[i] = aom_highbd_sad##m##x##n##_c(src, src_stride,            \
clang-format's avatar
clang-format committed
235 236 237
                                                 &ref_array[i], ref_stride); \
    }                                                                        \
  }
238

clang-format's avatar
clang-format committed
239
#define highbd_sadMxNx4D(m, n)                                               \
Adrian Grange's avatar
Adrian Grange committed
240
  void aom_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride,    \
clang-format's avatar
clang-format committed
241 242 243 244
                                      const uint8_t *const ref_array[],      \
                                      int ref_stride, uint32_t *sad_array) { \
    int i;                                                                   \
    for (i = 0; i < 4; ++i) {                                                \
Adrian Grange's avatar
Adrian Grange committed
245
      sad_array[i] = aom_highbd_sad##m##x##n##_c(src, src_stride,            \
clang-format's avatar
clang-format committed
246 247 248
                                                 ref_array[i], ref_stride);  \
    }                                                                        \
  }
249

clang-format's avatar
clang-format committed
250
/* clang-format off */
251
// 64x64
252 253 254 255
highbd_sadMxN(64, 64)
highbd_sadMxNxK(64, 64, 3)
highbd_sadMxNxK(64, 64, 8)
highbd_sadMxNx4D(64, 64)
256 257

// 64x32
258 259
highbd_sadMxN(64, 32)
highbd_sadMxNx4D(64, 32)
260 261

// 32x64
262 263
highbd_sadMxN(32, 64)
highbd_sadMxNx4D(32, 64)
264 265

// 32x32
266 267 268 269
highbd_sadMxN(32, 32)
highbd_sadMxNxK(32, 32, 3)
highbd_sadMxNxK(32, 32, 8)
highbd_sadMxNx4D(32, 32)
270 271

// 32x16
272 273
highbd_sadMxN(32, 16)
highbd_sadMxNx4D(32, 16)
274 275

// 16x32
276 277
highbd_sadMxN(16, 32)
highbd_sadMxNx4D(16, 32)
278 279

// 16x16
280 281 282 283
highbd_sadMxN(16, 16)
highbd_sadMxNxK(16, 16, 3)
highbd_sadMxNxK(16, 16, 8)
highbd_sadMxNx4D(16, 16)
284 285

// 16x8
286 287 288 289
highbd_sadMxN(16, 8)
highbd_sadMxNxK(16, 8, 3)
highbd_sadMxNxK(16, 8, 8)
highbd_sadMxNx4D(16, 8)
290 291

// 8x16
292 293 294 295
highbd_sadMxN(8, 16)
highbd_sadMxNxK(8, 16, 3)
highbd_sadMxNxK(8, 16, 8)
highbd_sadMxNx4D(8, 16)
296 297

// 8x8
298 299 300 301
highbd_sadMxN(8, 8)
highbd_sadMxNxK(8, 8, 3)
highbd_sadMxNxK(8, 8, 8)
highbd_sadMxNx4D(8, 8)
302 303

// 8x4
304 305 306
highbd_sadMxN(8, 4)
highbd_sadMxNxK(8, 4, 8)
highbd_sadMxNx4D(8, 4)
307 308

// 4x8
309 310 311
highbd_sadMxN(4, 8)
highbd_sadMxNxK(4, 8, 8)
highbd_sadMxNx4D(4, 8)
312 313

// 4x4
314 315 316 317
highbd_sadMxN(4, 4)
highbd_sadMxNxK(4, 4, 3)
highbd_sadMxNxK(4, 4, 8)
highbd_sadMxNx4D(4, 4)
clang-format's avatar
clang-format committed
318
/* clang-format on */
319

320
#endif  // CONFIG_AOM_HIGHBITDEPTH