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, const uint8_t *b, 21 int b_stride, int width, int height) { 22 int y, x; 23 unsigned int sad = 0; 24 25 for (y = 0; y < height; y++) { 26 for (x = 0; x < width; x++) sad += abs(a[x] - b[x]); 27 28 a += a_stride; 29 b += b_stride; 30 } 31 return sad; 32} 33 34#define sadMxN(m, n) \ 35 unsigned int vpx_sad##m##x##n##_c(const uint8_t *src, int src_stride, \ 36 const uint8_t *ref, int ref_stride) { \ 37 return sad(src, src_stride, ref, ref_stride, m, n); \ 38 } \ 39 unsigned int vpx_sad##m##x##n##_avg_c(const uint8_t *src, int src_stride, \ 40 const uint8_t *ref, int ref_stride, \ 41 const uint8_t *second_pred) { \ 42 DECLARE_ALIGNED(16, uint8_t, comp_pred[m * n]); \ 43 vpx_comp_avg_pred_c(comp_pred, second_pred, m, n, ref, ref_stride); \ 44 return sad(src, src_stride, comp_pred, m, m, n); \ 45 } 46 47// depending on call sites, pass **ref_array to avoid & in subsequent call and 48// de-dup with 4D below. 49#define sadMxNxK(m, n, k) \ 50 void vpx_sad##m##x##n##x##k##_c(const uint8_t *src, int src_stride, \ 51 const uint8_t *ref_array, int ref_stride, \ 52 uint32_t *sad_array) { \ 53 int i; \ 54 for (i = 0; i < k; ++i) \ 55 sad_array[i] = \ 56 vpx_sad##m##x##n##_c(src, src_stride, &ref_array[i], ref_stride); \ 57 } 58 59// This appears to be equivalent to the above when k == 4 and refs is const 60#define sadMxNx4D(m, n) \ 61 void vpx_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \ 62 const uint8_t *const ref_array[], \ 63 int ref_stride, uint32_t *sad_array) { \ 64 int i; \ 65 for (i = 0; i < 4; ++i) \ 66 sad_array[i] = \ 67 vpx_sad##m##x##n##_c(src, src_stride, ref_array[i], ref_stride); \ 68 } 69 70/* clang-format off */ 71// 64x64 72sadMxN(64, 64) 73sadMxNxK(64, 64, 3) 74sadMxNxK(64, 64, 8) 75sadMxNx4D(64, 64) 76 77// 64x32 78sadMxN(64, 32) 79sadMxNx4D(64, 32) 80 81// 32x64 82sadMxN(32, 64) 83sadMxNx4D(32, 64) 84 85// 32x32 86sadMxN(32, 32) 87sadMxNxK(32, 32, 3) 88sadMxNxK(32, 32, 8) 89sadMxNx4D(32, 32) 90 91// 32x16 92sadMxN(32, 16) 93sadMxNx4D(32, 16) 94 95// 16x32 96sadMxN(16, 32) 97sadMxNx4D(16, 32) 98 99// 16x16 100sadMxN(16, 16) 101sadMxNxK(16, 16, 3) 102sadMxNxK(16, 16, 8) 103sadMxNx4D(16, 16) 104 105// 16x8 106sadMxN(16, 8) 107sadMxNxK(16, 8, 3) 108sadMxNxK(16, 8, 8) 109sadMxNx4D(16, 8) 110 111// 8x16 112sadMxN(8, 16) 113sadMxNxK(8, 16, 3) 114sadMxNxK(8, 16, 8) 115sadMxNx4D(8, 16) 116 117// 8x8 118sadMxN(8, 8) 119sadMxNxK(8, 8, 3) 120sadMxNxK(8, 8, 8) 121sadMxNx4D(8, 8) 122 123// 8x4 124sadMxN(8, 4) 125sadMxNxK(8, 4, 8) 126sadMxNx4D(8, 4) 127 128// 4x8 129sadMxN(4, 8) 130sadMxNxK(4, 8, 8) 131sadMxNx4D(4, 8) 132 133// 4x4 134sadMxN(4, 4) 135sadMxNxK(4, 4, 3) 136sadMxNxK(4, 4, 8) 137sadMxNx4D(4, 4) 138/* clang-format on */ 139 140#if CONFIG_VP9_HIGHBITDEPTH 141 static INLINE 142 unsigned int highbd_sad(const uint8_t *a8, int a_stride, const uint8_t *b8, 143 int b_stride, int width, int height) { 144 int y, x; 145 unsigned int sad = 0; 146 const uint16_t *a = CONVERT_TO_SHORTPTR(a8); 147 const uint16_t *b = CONVERT_TO_SHORTPTR(b8); 148 for (y = 0; y < height; y++) { 149 for (x = 0; x < width; x++) sad += abs(a[x] - b[x]); 150 151 a += a_stride; 152 b += b_stride; 153 } 154 return sad; 155} 156 157static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride, 158 const uint16_t *b, int b_stride, 159 int width, int height) { 160 int y, x; 161 unsigned int sad = 0; 162 const uint16_t *a = CONVERT_TO_SHORTPTR(a8); 163 for (y = 0; y < height; y++) { 164 for (x = 0; x < width; x++) sad += abs(a[x] - b[x]); 165 166 a += a_stride; 167 b += b_stride; 168 } 169 return sad; 170} 171 172#define highbd_sadMxN(m, n) \ 173 unsigned int vpx_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \ 174 const uint8_t *ref, \ 175 int ref_stride) { \ 176 return highbd_sad(src, src_stride, ref, ref_stride, m, n); \ 177 } \ 178 unsigned int vpx_highbd_sad##m##x##n##_avg_c( \ 179 const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride, \ 180 const uint8_t *second_pred) { \ 181 DECLARE_ALIGNED(16, uint16_t, comp_pred[m * n]); \ 182 vpx_highbd_comp_avg_pred_c(comp_pred, second_pred, m, n, ref, ref_stride); \ 183 return highbd_sadb(src, src_stride, comp_pred, m, m, n); \ 184 } 185 186#define highbd_sadMxNxK(m, n, k) \ 187 void vpx_highbd_sad##m##x##n##x##k##_c( \ 188 const uint8_t *src, int src_stride, const uint8_t *ref_array, \ 189 int ref_stride, uint32_t *sad_array) { \ 190 int i; \ 191 for (i = 0; i < k; ++i) { \ 192 sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, \ 193 &ref_array[i], ref_stride); \ 194 } \ 195 } 196 197#define highbd_sadMxNx4D(m, n) \ 198 void vpx_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride, \ 199 const uint8_t *const ref_array[], \ 200 int ref_stride, uint32_t *sad_array) { \ 201 int i; \ 202 for (i = 0; i < 4; ++i) { \ 203 sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride, \ 204 ref_array[i], ref_stride); \ 205 } \ 206 } 207 208/* clang-format off */ 209// 64x64 210highbd_sadMxN(64, 64) 211highbd_sadMxNxK(64, 64, 3) 212highbd_sadMxNxK(64, 64, 8) 213highbd_sadMxNx4D(64, 64) 214 215// 64x32 216highbd_sadMxN(64, 32) 217highbd_sadMxNx4D(64, 32) 218 219// 32x64 220highbd_sadMxN(32, 64) 221highbd_sadMxNx4D(32, 64) 222 223// 32x32 224highbd_sadMxN(32, 32) 225highbd_sadMxNxK(32, 32, 3) 226highbd_sadMxNxK(32, 32, 8) 227highbd_sadMxNx4D(32, 32) 228 229// 32x16 230highbd_sadMxN(32, 16) 231highbd_sadMxNx4D(32, 16) 232 233// 16x32 234highbd_sadMxN(16, 32) 235highbd_sadMxNx4D(16, 32) 236 237// 16x16 238highbd_sadMxN(16, 16) 239highbd_sadMxNxK(16, 16, 3) 240highbd_sadMxNxK(16, 16, 8) 241highbd_sadMxNx4D(16, 16) 242 243// 16x8 244highbd_sadMxN(16, 8) 245highbd_sadMxNxK(16, 8, 3) 246highbd_sadMxNxK(16, 8, 8) 247highbd_sadMxNx4D(16, 8) 248 249// 8x16 250highbd_sadMxN(8, 16) 251highbd_sadMxNxK(8, 16, 3) 252highbd_sadMxNxK(8, 16, 8) 253highbd_sadMxNx4D(8, 16) 254 255// 8x8 256highbd_sadMxN(8, 8) 257highbd_sadMxNxK(8, 8, 3) 258highbd_sadMxNxK(8, 8, 8) 259highbd_sadMxNx4D(8, 8) 260 261// 8x4 262highbd_sadMxN(8, 4) 263highbd_sadMxNxK(8, 4, 8) 264highbd_sadMxNx4D(8, 4) 265 266// 4x8 267highbd_sadMxN(4, 8) 268highbd_sadMxNxK(4, 8, 8) 269highbd_sadMxNx4D(4, 8) 270 271// 4x4 272highbd_sadMxN(4, 4) 273highbd_sadMxNxK(4, 4, 3) 274highbd_sadMxNxK(4, 4, 8) 275highbd_sadMxNx4D(4, 4) 276/* clang-format on */ 277 278#endif // CONFIG_VP9_HIGHBITDEPTH 279