sad.c (13207B)
1 /* 2 * Copyright (c) 2016, Alliance for Open Media. All rights reserved. 3 * 4 * This source code is subject to the terms of the BSD 2 Clause License and 5 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License 6 * was not distributed with this source code in the LICENSE file, you can 7 * obtain it at www.aomedia.org/license/software. If the Alliance for Open 8 * Media Patent License 1.0 was not distributed with this source code in the 9 * PATENTS file, you can obtain it at www.aomedia.org/license/patent. 10 */ 11 12 #include <stdlib.h> 13 14 #include "config/aom_config.h" 15 #include "config/aom_dsp_rtcd.h" 16 17 #include "aom/aom_integer.h" 18 #include "aom_ports/mem.h" 19 #include "aom_dsp/blend.h" 20 21 /* Sum the difference between every corresponding element of the buffers. */ 22 static inline unsigned int sad(const uint8_t *a, int a_stride, const uint8_t *b, 23 int b_stride, int width, int height) { 24 int y, x; 25 unsigned int sad = 0; 26 27 for (y = 0; y < height; y++) { 28 for (x = 0; x < width; x++) { 29 sad += abs(a[x] - b[x]); 30 } 31 32 a += a_stride; 33 b += b_stride; 34 } 35 return sad; 36 } 37 38 #define SADMXN(m, n) \ 39 unsigned int aom_sad##m##x##n##_c(const uint8_t *src, int src_stride, \ 40 const uint8_t *ref, int ref_stride) { \ 41 return sad(src, src_stride, ref, ref_stride, m, n); \ 42 } 43 44 #define SADMXN_AVG(m, n) \ 45 unsigned int aom_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride, \ 46 const uint8_t *ref, int ref_stride, \ 47 const uint8_t *second_pred) { \ 48 uint8_t comp_pred[m * n]; \ 49 aom_comp_avg_pred(comp_pred, second_pred, m, n, ref, ref_stride); \ 50 return sad(src, src_stride, comp_pred, m, m, n); \ 51 } 52 53 #define SADMXN_SKIP(m, n) \ 54 unsigned int aom_sad_skip_##m##x##n##_c(const uint8_t *src, int src_stride, \ 55 const uint8_t *ref, \ 56 int ref_stride) { \ 57 return 2 * sad(src, 2 * src_stride, ref, 2 * ref_stride, (m), (n / 2)); \ 58 } 59 60 #define SADMXN_NO_SKIP(m, n) \ 61 SADMXN(m, n) \ 62 SADMXN_AVG(m, n) 63 64 #define SADMXN_NO_AVG(m, n) \ 65 SADMXN(m, n) \ 66 SADMXN_SKIP(m, n) 67 68 #define SADMXN_ALL(m, n) \ 69 SADMXN(m, n) \ 70 SADMXN_AVG(m, n) \ 71 SADMXN_SKIP(m, n) 72 73 // Calculate sad against 4 reference locations and store each in sad_array 74 #define SAD_MXNX4D_NO_SKIP(m, n) \ 75 void aom_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \ 76 const uint8_t *const ref_array[4], \ 77 int ref_stride, uint32_t sad_array[4]) { \ 78 int i; \ 79 for (i = 0; i < 4; ++i) { \ 80 sad_array[i] = \ 81 aom_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \ 82 } \ 83 } 84 85 #define SAD_MXNX4D(m, n) \ 86 SAD_MXNX4D_NO_SKIP(m, n) \ 87 void aom_sad_skip_##m##x##n##x4d_c(const uint8_t *src, int src_stride, \ 88 const uint8_t *const ref_array[4], \ 89 int ref_stride, uint32_t sad_array[4]) { \ 90 int i; \ 91 for (i = 0; i < 4; ++i) { \ 92 sad_array[i] = 2 * sad(src, 2 * src_stride, ref_array[i], \ 93 2 * ref_stride, (m), (n / 2)); \ 94 } \ 95 } 96 // Call SIMD version of aom_sad_mxnx4d if the 3d version is unavailable. 97 #define SAD_MXNX3D(m, n) \ 98 void aom_sad##m##x##n##x3d_c(const uint8_t *src, int src_stride, \ 99 const uint8_t *const ref_array[4], \ 100 int ref_stride, uint32_t sad_array[4]) { \ 101 aom_sad##m##x##n##x4d(src, src_stride, ref_array, ref_stride, sad_array); \ 102 } 103 104 // 128x128 105 SADMXN_ALL(128, 128) 106 SAD_MXNX4D(128, 128) 107 SAD_MXNX3D(128, 128) 108 109 // 128x64 110 SADMXN_ALL(128, 64) 111 SAD_MXNX4D(128, 64) 112 SAD_MXNX3D(128, 64) 113 114 // 64x128 115 SADMXN_ALL(64, 128) 116 SAD_MXNX4D(64, 128) 117 SAD_MXNX3D(64, 128) 118 119 // 64x64 120 SADMXN_ALL(64, 64) 121 SAD_MXNX4D(64, 64) 122 SAD_MXNX3D(64, 64) 123 124 // 64x32 125 SADMXN_ALL(64, 32) 126 SAD_MXNX4D(64, 32) 127 SAD_MXNX3D(64, 32) 128 129 // 32x64 130 SADMXN_ALL(32, 64) 131 SAD_MXNX4D(32, 64) 132 SAD_MXNX3D(32, 64) 133 134 // 32x32 135 SADMXN_ALL(32, 32) 136 SAD_MXNX4D(32, 32) 137 SAD_MXNX3D(32, 32) 138 139 // 32x16 140 SADMXN_ALL(32, 16) 141 SAD_MXNX4D(32, 16) 142 SAD_MXNX3D(32, 16) 143 144 // 16x32 145 SADMXN_ALL(16, 32) 146 SAD_MXNX4D(16, 32) 147 SAD_MXNX3D(16, 32) 148 149 // 16x16 150 SADMXN_ALL(16, 16) 151 SAD_MXNX4D(16, 16) 152 SAD_MXNX3D(16, 16) 153 154 // 16x8 155 SADMXN_NO_SKIP(16, 8) 156 SAD_MXNX4D_NO_SKIP(16, 8) 157 SAD_MXNX3D(16, 8) 158 159 // 8x16 160 SADMXN_ALL(8, 16) 161 SAD_MXNX4D(8, 16) 162 SAD_MXNX3D(8, 16) 163 164 // 8x8 165 SADMXN_NO_SKIP(8, 8) 166 SAD_MXNX4D_NO_SKIP(8, 8) 167 SAD_MXNX3D(8, 8) 168 169 // 8x4 170 SADMXN(8, 4) 171 SAD_MXNX4D_NO_SKIP(8, 4) 172 SAD_MXNX3D(8, 4) 173 174 // 4x8 175 SADMXN(4, 8) 176 SAD_MXNX4D_NO_SKIP(4, 8) 177 SAD_MXNX3D(4, 8) 178 179 // 4x4 180 SADMXN(4, 4) 181 SAD_MXNX4D_NO_SKIP(4, 4) 182 SAD_MXNX3D(4, 4) 183 184 #if !CONFIG_REALTIME_ONLY 185 SADMXN_NO_AVG(4, 16) 186 SAD_MXNX4D(4, 16) 187 SADMXN(16, 4) 188 SAD_MXNX4D_NO_SKIP(16, 4) 189 SADMXN_ALL(8, 32) 190 SAD_MXNX4D(8, 32) 191 SADMXN_NO_SKIP(32, 8) 192 SAD_MXNX4D_NO_SKIP(32, 8) 193 SADMXN_ALL(16, 64) 194 SAD_MXNX4D(16, 64) 195 SADMXN_ALL(64, 16) 196 SAD_MXNX4D(64, 16) 197 SAD_MXNX3D(4, 16) 198 SAD_MXNX3D(16, 4) 199 SAD_MXNX3D(8, 32) 200 SAD_MXNX3D(32, 8) 201 SAD_MXNX3D(16, 64) 202 SAD_MXNX3D(64, 16) 203 #endif // !CONFIG_REALTIME_ONLY 204 205 #if CONFIG_AV1_HIGHBITDEPTH 206 static inline unsigned int highbd_sad(const uint8_t *a8, int a_stride, 207 const uint8_t *b8, int b_stride, 208 int width, int height) { 209 int y, x; 210 unsigned int sad = 0; 211 const uint16_t *a = CONVERT_TO_SHORTPTR(a8); 212 const uint16_t *b = CONVERT_TO_SHORTPTR(b8); 213 for (y = 0; y < height; y++) { 214 for (x = 0; x < width; x++) { 215 sad += abs(a[x] - b[x]); 216 } 217 218 a += a_stride; 219 b += b_stride; 220 } 221 return sad; 222 } 223 224 static inline unsigned int highbd_sadb(const uint8_t *a8, int a_stride, 225 const uint8_t *b8, int b_stride, 226 int width, int height) { 227 int y, x; 228 unsigned int sad = 0; 229 const uint16_t *a = CONVERT_TO_SHORTPTR(a8); 230 const uint16_t *b = CONVERT_TO_SHORTPTR(b8); 231 for (y = 0; y < height; y++) { 232 for (x = 0; x < width; x++) { 233 sad += abs(a[x] - b[x]); 234 } 235 236 a += a_stride; 237 b += b_stride; 238 } 239 return sad; 240 } 241 242 #define HIGHBD_SADMXN(m, n) \ 243 unsigned int aom_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \ 244 const uint8_t *ref, \ 245 int ref_stride) { \ 246 return highbd_sad(src, src_stride, ref, ref_stride, m, n); \ 247 } 248 249 #define HIGHBD_SADMXN_AVG(m, n) \ 250 unsigned int aom_highbd_sad##m##x##n##_avg_c( \ 251 const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride, \ 252 const uint8_t *second_pred) { \ 253 uint16_t comp_pred[m * n]; \ 254 uint8_t *const comp_pred8 = CONVERT_TO_BYTEPTR(comp_pred); \ 255 aom_highbd_comp_avg_pred(comp_pred8, second_pred, m, n, ref, ref_stride); \ 256 return highbd_sadb(src, src_stride, comp_pred8, m, m, n); \ 257 } 258 259 #define HIGHBD_SADMXN_SKIP(m, n) \ 260 unsigned int aom_highbd_sad_skip_##m##x##n##_c( \ 261 const uint8_t *src, int src_stride, const uint8_t *ref, \ 262 int ref_stride) { \ 263 return 2 * \ 264 highbd_sad(src, 2 * src_stride, ref, 2 * ref_stride, (m), (n / 2)); \ 265 } 266 267 #define HIGHBD_SADMXN_NO_SKIP(m, n) \ 268 HIGHBD_SADMXN(m, n) \ 269 HIGHBD_SADMXN_AVG(m, n) 270 271 #define HIGHBD_SADMXN_NO_AVG(m, n) \ 272 HIGHBD_SADMXN(m, n) \ 273 HIGHBD_SADMXN_SKIP(m, n) 274 275 #define HIGHBD_SADMXN_ALL(m, n) \ 276 HIGHBD_SADMXN(m, n) \ 277 HIGHBD_SADMXN_AVG(m, n) \ 278 HIGHBD_SADMXN_SKIP(m, n) 279 280 #define HIGHBD_SAD_MXNX4D_NO_SKIP(m, n) \ 281 void aom_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \ 282 const uint8_t *const ref_array[4], \ 283 int ref_stride, uint32_t sad_array[4]) { \ 284 int i; \ 285 for (i = 0; i < 4; ++i) { \ 286 sad_array[i] = aom_highbd_sad##m##x##n##_c(src, src_stride, \ 287 ref_array[i], ref_stride); \ 288 } \ 289 } 290 291 #define HIGHBD_SAD_MXNX4D(m, n) \ 292 HIGHBD_SAD_MXNX4D_NO_SKIP(m, n) \ 293 void aom_highbd_sad_skip_##m##x##n##x4d_c( \ 294 const uint8_t *src, int src_stride, const uint8_t *const ref_array[4], \ 295 int ref_stride, uint32_t sad_array[4]) { \ 296 int i; \ 297 for (i = 0; i < 4; ++i) { \ 298 sad_array[i] = 2 * highbd_sad(src, 2 * src_stride, ref_array[i], \ 299 2 * ref_stride, (m), (n / 2)); \ 300 } \ 301 } 302 // Call SIMD version of aom_highbd_sad_mxnx4d if the 3d version is unavailable. 303 #define HIGHBD_SAD_MXNX3D(m, n) \ 304 void aom_highbd_sad##m##x##n##x3d_c(const uint8_t *src, int src_stride, \ 305 const uint8_t *const ref_array[4], \ 306 int ref_stride, uint32_t sad_array[4]) { \ 307 aom_highbd_sad##m##x##n##x4d(src, src_stride, ref_array, ref_stride, \ 308 sad_array); \ 309 } 310 311 // 128x128 312 HIGHBD_SADMXN_ALL(128, 128) 313 HIGHBD_SAD_MXNX4D(128, 128) 314 HIGHBD_SAD_MXNX3D(128, 128) 315 316 // 128x64 317 HIGHBD_SADMXN_ALL(128, 64) 318 HIGHBD_SAD_MXNX4D(128, 64) 319 HIGHBD_SAD_MXNX3D(128, 64) 320 321 // 64x128 322 HIGHBD_SADMXN_ALL(64, 128) 323 HIGHBD_SAD_MXNX4D(64, 128) 324 HIGHBD_SAD_MXNX3D(64, 128) 325 326 // 64x64 327 HIGHBD_SADMXN_ALL(64, 64) 328 HIGHBD_SAD_MXNX4D(64, 64) 329 HIGHBD_SAD_MXNX3D(64, 64) 330 331 // 64x32 332 HIGHBD_SADMXN_ALL(64, 32) 333 HIGHBD_SAD_MXNX4D(64, 32) 334 HIGHBD_SAD_MXNX3D(64, 32) 335 336 // 32x64 337 HIGHBD_SADMXN_ALL(32, 64) 338 HIGHBD_SAD_MXNX4D(32, 64) 339 HIGHBD_SAD_MXNX3D(32, 64) 340 341 // 32x32 342 HIGHBD_SADMXN_ALL(32, 32) 343 HIGHBD_SAD_MXNX4D(32, 32) 344 HIGHBD_SAD_MXNX3D(32, 32) 345 346 // 32x16 347 HIGHBD_SADMXN_ALL(32, 16) 348 HIGHBD_SAD_MXNX4D(32, 16) 349 HIGHBD_SAD_MXNX3D(32, 16) 350 351 // 16x32 352 HIGHBD_SADMXN_ALL(16, 32) 353 HIGHBD_SAD_MXNX4D(16, 32) 354 HIGHBD_SAD_MXNX3D(16, 32) 355 356 // 16x16 357 HIGHBD_SADMXN_ALL(16, 16) 358 HIGHBD_SAD_MXNX4D(16, 16) 359 HIGHBD_SAD_MXNX3D(16, 16) 360 361 // 16x8 362 HIGHBD_SADMXN_NO_SKIP(16, 8) 363 HIGHBD_SAD_MXNX4D_NO_SKIP(16, 8) 364 HIGHBD_SAD_MXNX3D(16, 8) 365 366 // 8x16 367 HIGHBD_SADMXN_ALL(8, 16) 368 HIGHBD_SAD_MXNX4D(8, 16) 369 HIGHBD_SAD_MXNX3D(8, 16) 370 371 // 8x8 372 HIGHBD_SADMXN_NO_SKIP(8, 8) 373 HIGHBD_SAD_MXNX4D_NO_SKIP(8, 8) 374 HIGHBD_SAD_MXNX3D(8, 8) 375 376 // 8x4 377 HIGHBD_SADMXN(8, 4) 378 HIGHBD_SAD_MXNX4D_NO_SKIP(8, 4) 379 HIGHBD_SAD_MXNX3D(8, 4) 380 381 // 4x8 382 HIGHBD_SADMXN(4, 8) 383 HIGHBD_SAD_MXNX4D_NO_SKIP(4, 8) 384 HIGHBD_SAD_MXNX3D(4, 8) 385 386 // 4x4 387 HIGHBD_SADMXN(4, 4) 388 HIGHBD_SAD_MXNX4D_NO_SKIP(4, 4) 389 HIGHBD_SAD_MXNX3D(4, 4) 390 391 #if !CONFIG_REALTIME_ONLY 392 HIGHBD_SADMXN_NO_AVG(4, 16) 393 HIGHBD_SAD_MXNX4D(4, 16) 394 HIGHBD_SADMXN(16, 4) 395 HIGHBD_SAD_MXNX4D_NO_SKIP(16, 4) 396 HIGHBD_SADMXN_ALL(8, 32) 397 HIGHBD_SAD_MXNX4D(8, 32) 398 HIGHBD_SADMXN_NO_SKIP(32, 8) 399 HIGHBD_SAD_MXNX4D_NO_SKIP(32, 8) 400 HIGHBD_SADMXN_ALL(16, 64) 401 HIGHBD_SAD_MXNX4D(16, 64) 402 HIGHBD_SADMXN_ALL(64, 16) 403 HIGHBD_SAD_MXNX4D(64, 16) 404 405 HIGHBD_SAD_MXNX3D(4, 16) 406 HIGHBD_SAD_MXNX3D(16, 4) 407 HIGHBD_SAD_MXNX3D(8, 32) 408 HIGHBD_SAD_MXNX3D(32, 8) 409 HIGHBD_SAD_MXNX3D(16, 64) 410 HIGHBD_SAD_MXNX3D(64, 16) 411 #endif // !CONFIG_REALTIME_ONLY 412 #endif // CONFIG_AV1_HIGHBITDEPTH