Home | History | Annotate | Download | only in vpx_dsp
      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 *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
     72 sadMxN(64, 64)
     73 sadMxNx4D(64, 64)
     74 
     75 // 64x32
     76 sadMxN(64, 32)
     77 sadMxNx4D(64, 32)
     78 
     79 // 32x64
     80 sadMxN(32, 64)
     81 sadMxNx4D(32, 64)
     82 
     83 // 32x32
     84 sadMxN(32, 32)
     85 sadMxNx4D(32, 32)
     86 
     87 // 32x16
     88 sadMxN(32, 16)
     89 sadMxNx4D(32, 16)
     90 
     91 // 16x32
     92 sadMxN(16, 32)
     93 sadMxNx4D(16, 32)
     94 
     95 // 16x16
     96 sadMxN(16, 16)
     97 sadMxNxK(16, 16, 3)
     98 sadMxNxK(16, 16, 8)
     99 sadMxNx4D(16, 16)
    100 
    101 // 16x8
    102 sadMxN(16, 8)
    103 sadMxNxK(16, 8, 3)
    104 sadMxNxK(16, 8, 8)
    105 sadMxNx4D(16, 8)
    106 
    107 // 8x16
    108 sadMxN(8, 16)
    109 sadMxNxK(8, 16, 3)
    110 sadMxNxK(8, 16, 8)
    111 sadMxNx4D(8, 16)
    112 
    113 // 8x8
    114 sadMxN(8, 8)
    115 sadMxNxK(8, 8, 3)
    116 sadMxNxK(8, 8, 8)
    117 sadMxNx4D(8, 8)
    118 
    119 // 8x4
    120 sadMxN(8, 4)
    121 sadMxNx4D(8, 4)
    122 
    123 // 4x8
    124 sadMxN(4, 8)
    125 sadMxNx4D(4, 8)
    126 
    127 // 4x4
    128 sadMxN(4, 4)
    129 sadMxNxK(4, 4, 3)
    130 sadMxNxK(4, 4, 8)
    131 sadMxNx4D(4, 4)
    132 /* clang-format on */
    133 
    134 #if CONFIG_VP9_HIGHBITDEPTH
    135         static INLINE
    136     unsigned int highbd_sad(const uint8_t *a8, int a_stride, const uint8_t *b8,
    137                             int b_stride, int width, int height) {
    138   int y, x;
    139   unsigned int sad = 0;
    140   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
    141   const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
    142   for (y = 0; y < height; y++) {
    143     for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
    144 
    145     a += a_stride;
    146     b += b_stride;
    147   }
    148   return sad;
    149 }
    150 
    151 static INLINE unsigned int highbd_sadb(const uint8_t *a8, int a_stride,
    152                                        const uint16_t *b, int b_stride,
    153                                        int width, int height) {
    154   int y, x;
    155   unsigned int sad = 0;
    156   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
    157   for (y = 0; y < height; y++) {
    158     for (x = 0; x < width; x++) sad += abs(a[x] - b[x]);
    159 
    160     a += a_stride;
    161     b += b_stride;
    162   }
    163   return sad;
    164 }
    165 
    166 #define highbd_sadMxN(m, n)                                                    \
    167   unsigned int vpx_highbd_sad##m##x##n##_c(const uint8_t *src, int src_stride, \
    168                                            const uint8_t *ref,                 \
    169                                            int ref_stride) {                   \
    170     return highbd_sad(src, src_stride, ref, ref_stride, m, n);                 \
    171   }                                                                            \
    172   unsigned int vpx_highbd_sad##m##x##n##_avg_c(                                \
    173       const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride,  \
    174       const uint8_t *second_pred) {                                            \
    175     DECLARE_ALIGNED(16, uint16_t, comp_pred[m * n]);                           \
    176     vpx_highbd_comp_avg_pred_c(comp_pred, second_pred, m, n, ref, ref_stride); \
    177     return highbd_sadb(src, src_stride, comp_pred, m, m, n);                   \
    178   }
    179 
    180 #define highbd_sadMxNx4D(m, n)                                               \
    181   void vpx_highbd_sad##m##x##n##x4d_c(const uint8_t *src, int src_stride,    \
    182                                       const uint8_t *const ref_array[],      \
    183                                       int ref_stride, uint32_t *sad_array) { \
    184     int i;                                                                   \
    185     for (i = 0; i < 4; ++i) {                                                \
    186       sad_array[i] = vpx_highbd_sad##m##x##n##_c(src, src_stride,            \
    187                                                  ref_array[i], ref_stride);  \
    188     }                                                                        \
    189   }
    190 
    191 /* clang-format off */
    192 // 64x64
    193 highbd_sadMxN(64, 64)
    194 highbd_sadMxNx4D(64, 64)
    195 
    196 // 64x32
    197 highbd_sadMxN(64, 32)
    198 highbd_sadMxNx4D(64, 32)
    199 
    200 // 32x64
    201 highbd_sadMxN(32, 64)
    202 highbd_sadMxNx4D(32, 64)
    203 
    204 // 32x32
    205 highbd_sadMxN(32, 32)
    206 highbd_sadMxNx4D(32, 32)
    207 
    208 // 32x16
    209 highbd_sadMxN(32, 16)
    210 highbd_sadMxNx4D(32, 16)
    211 
    212 // 16x32
    213 highbd_sadMxN(16, 32)
    214 highbd_sadMxNx4D(16, 32)
    215 
    216 // 16x16
    217 highbd_sadMxN(16, 16)
    218 highbd_sadMxNx4D(16, 16)
    219 
    220 // 16x8
    221 highbd_sadMxN(16, 8)
    222 highbd_sadMxNx4D(16, 8)
    223 
    224 // 8x16
    225 highbd_sadMxN(8, 16)
    226 highbd_sadMxNx4D(8, 16)
    227 
    228 // 8x8
    229 highbd_sadMxN(8, 8)
    230 highbd_sadMxNx4D(8, 8)
    231 
    232 // 8x4
    233 highbd_sadMxN(8, 4)
    234 highbd_sadMxNx4D(8, 4)
    235 
    236 // 4x8
    237 highbd_sadMxN(4, 8)
    238 highbd_sadMxNx4D(4, 8)
    239 
    240 // 4x4
    241 highbd_sadMxN(4, 4)
    242 highbd_sadMxNx4D(4, 4)
    243 /* clang-format on */
    244 
    245 #endif  // CONFIG_VP9_HIGHBITDEPTH
    246