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 *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