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