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