xref: /aosp_15_r20/external/libaom/aom_dsp/sad_av1.c (revision 77c1e3ccc04c968bd2bc212e87364f250e820521)
1 /*
2  * Copyright (c) 2017, Alliance for Open Media. All rights reserved.
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include <stdlib.h>
13 
14 #include "config/aom_config.h"
15 #include "config/aom_dsp_rtcd.h"
16 
17 #include "aom/aom_integer.h"
18 #include "aom_ports/mem.h"
19 #include "aom_dsp/blend.h"
20 
masked_sad(const uint8_t * src,int src_stride,const uint8_t * a,int a_stride,const uint8_t * b,int b_stride,const uint8_t * m,int m_stride,int width,int height)21 static inline unsigned int masked_sad(const uint8_t *src, int src_stride,
22                                       const uint8_t *a, int a_stride,
23                                       const uint8_t *b, int b_stride,
24                                       const uint8_t *m, int m_stride, int width,
25                                       int height) {
26   int y, x;
27   unsigned int sad = 0;
28   for (y = 0; y < height; y++) {
29     for (x = 0; x < width; x++) {
30       const int16_t pred = AOM_BLEND_A64(m[x], a[x], b[x]);
31       sad += abs(pred - src[x]);
32     }
33     src += src_stride;
34     a += a_stride;
35     b += b_stride;
36     m += m_stride;
37   }
38   return sad;
39 }
40 
41 #define MASKSADMxN(m, n)                                                       \
42   unsigned int aom_masked_sad##m##x##n##_c(                                    \
43       const uint8_t *src, int src_stride, const uint8_t *ref, int ref_stride,  \
44       const uint8_t *second_pred, const uint8_t *msk, int msk_stride,          \
45       int invert_mask) {                                                       \
46     if (!invert_mask)                                                          \
47       return masked_sad(src, src_stride, ref, ref_stride, second_pred, m, msk, \
48                         msk_stride, m, n);                                     \
49     else                                                                       \
50       return masked_sad(src, src_stride, second_pred, m, ref, ref_stride, msk, \
51                         msk_stride, m, n);                                     \
52   }
53 
54 /* clang-format off */
55 MASKSADMxN(128, 128)
56 MASKSADMxN(128, 64)
57 MASKSADMxN(64, 128)
58 MASKSADMxN(64, 64)
59 MASKSADMxN(64, 32)
60 MASKSADMxN(32, 64)
61 MASKSADMxN(32, 32)
62 MASKSADMxN(32, 16)
63 MASKSADMxN(16, 32)
64 MASKSADMxN(16, 16)
65 MASKSADMxN(16, 8)
66 MASKSADMxN(8, 16)
67 MASKSADMxN(8, 8)
68 MASKSADMxN(8, 4)
69 MASKSADMxN(4, 8)
70 MASKSADMxN(4, 4)
71 #if !CONFIG_REALTIME_ONLY
72 MASKSADMxN(4, 16)
73 MASKSADMxN(16, 4)
74 MASKSADMxN(8, 32)
75 MASKSADMxN(32, 8)
76 MASKSADMxN(16, 64)
77 MASKSADMxN(64, 16)
78 #endif  // !CONFIG_REALTIME_ONLY
79 /* clang-format on */
80 
81 #if CONFIG_AV1_HIGHBITDEPTH
highbd_masked_sad(const uint8_t * src8,int src_stride,const uint8_t * a8,int a_stride,const uint8_t * b8,int b_stride,const uint8_t * m,int m_stride,int width,int height)82                         static inline unsigned int highbd_masked_sad(
83                             const uint8_t *src8, int src_stride,
84                             const uint8_t *a8, int a_stride, const uint8_t *b8,
85                             int b_stride, const uint8_t *m, int m_stride,
86                             int width, int height) {
87   int y, x;
88   unsigned int sad = 0;
89   const uint16_t *src = CONVERT_TO_SHORTPTR(src8);
90   const uint16_t *a = CONVERT_TO_SHORTPTR(a8);
91   const uint16_t *b = CONVERT_TO_SHORTPTR(b8);
92 
93   for (y = 0; y < height; y++) {
94     for (x = 0; x < width; x++) {
95       const uint16_t pred = AOM_BLEND_A64(m[x], a[x], b[x]);
96       sad += abs(pred - src[x]);
97     }
98 
99     src += src_stride;
100     a += a_stride;
101     b += b_stride;
102     m += m_stride;
103   }
104 
105   return sad;
106 }
107 
108 #define HIGHBD_MASKSADMXN(m, n)                                         \
109   unsigned int aom_highbd_masked_sad##m##x##n##_c(                      \
110       const uint8_t *src8, int src_stride, const uint8_t *ref8,         \
111       int ref_stride, const uint8_t *second_pred8, const uint8_t *msk,  \
112       int msk_stride, int invert_mask) {                                \
113     if (!invert_mask)                                                   \
114       return highbd_masked_sad(src8, src_stride, ref8, ref_stride,      \
115                                second_pred8, m, msk, msk_stride, m, n); \
116     else                                                                \
117       return highbd_masked_sad(src8, src_stride, second_pred8, m, ref8, \
118                                ref_stride, msk, msk_stride, m, n);      \
119   }
120 
121 HIGHBD_MASKSADMXN(128, 128)
122 HIGHBD_MASKSADMXN(128, 64)
123 HIGHBD_MASKSADMXN(64, 128)
124 HIGHBD_MASKSADMXN(64, 64)
125 HIGHBD_MASKSADMXN(64, 32)
126 HIGHBD_MASKSADMXN(32, 64)
127 HIGHBD_MASKSADMXN(32, 32)
128 HIGHBD_MASKSADMXN(32, 16)
129 HIGHBD_MASKSADMXN(16, 32)
130 HIGHBD_MASKSADMXN(16, 16)
131 HIGHBD_MASKSADMXN(16, 8)
132 HIGHBD_MASKSADMXN(8, 16)
133 HIGHBD_MASKSADMXN(8, 8)
134 HIGHBD_MASKSADMXN(8, 4)
135 HIGHBD_MASKSADMXN(4, 8)
136 HIGHBD_MASKSADMXN(4, 4)
137 #if !CONFIG_REALTIME_ONLY
138 HIGHBD_MASKSADMXN(4, 16)
139 HIGHBD_MASKSADMXN(16, 4)
140 HIGHBD_MASKSADMXN(8, 32)
141 HIGHBD_MASKSADMXN(32, 8)
142 HIGHBD_MASKSADMXN(16, 64)
143 HIGHBD_MASKSADMXN(64, 16)
144 #endif  // !CONFIG_REALTIME_ONLY
145 #endif  // CONFIG_AV1_HIGHBITDEPTH
146 
147 #if !CONFIG_REALTIME_ONLY
148 // pre: predictor being evaluated
149 // wsrc: target weighted prediction (has been *4096 to keep precision)
150 // mask: 2d weights (scaled by 4096)
obmc_sad(const uint8_t * pre,int pre_stride,const int32_t * wsrc,const int32_t * mask,int width,int height)151 static inline unsigned int obmc_sad(const uint8_t *pre, int pre_stride,
152                                     const int32_t *wsrc, const int32_t *mask,
153                                     int width, int height) {
154   int y, x;
155   unsigned int sad = 0;
156 
157   for (y = 0; y < height; y++) {
158     for (x = 0; x < width; x++)
159       sad += ROUND_POWER_OF_TWO(abs(wsrc[x] - pre[x] * mask[x]), 12);
160 
161     pre += pre_stride;
162     wsrc += width;
163     mask += width;
164   }
165 
166   return sad;
167 }
168 
169 #define OBMCSADMxN(m, n)                                                     \
170   unsigned int aom_obmc_sad##m##x##n##_c(const uint8_t *ref, int ref_stride, \
171                                          const int32_t *wsrc,                \
172                                          const int32_t *mask) {              \
173     return obmc_sad(ref, ref_stride, wsrc, mask, m, n);                      \
174   }
175 
176 /* clang-format off */
177 OBMCSADMxN(128, 128)
178 OBMCSADMxN(128, 64)
179 OBMCSADMxN(64, 128)
180 OBMCSADMxN(64, 64)
181 OBMCSADMxN(64, 32)
182 OBMCSADMxN(32, 64)
183 OBMCSADMxN(32, 32)
184 OBMCSADMxN(32, 16)
185 OBMCSADMxN(16, 32)
186 OBMCSADMxN(16, 16)
187 OBMCSADMxN(16, 8)
188 OBMCSADMxN(8, 16)
189 OBMCSADMxN(8, 8)
190 OBMCSADMxN(8, 4)
191 OBMCSADMxN(4, 8)
192 OBMCSADMxN(4, 4)
193 OBMCSADMxN(4, 16)
194 OBMCSADMxN(16, 4)
195 OBMCSADMxN(8, 32)
196 OBMCSADMxN(32, 8)
197 OBMCSADMxN(16, 64)
198 OBMCSADMxN(64, 16)
199 /* clang-format on */
200 
201 #if CONFIG_AV1_HIGHBITDEPTH
highbd_obmc_sad(const uint8_t * pre8,int pre_stride,const int32_t * wsrc,const int32_t * mask,int width,int height)202                             static inline unsigned int highbd_obmc_sad(
203                                 const uint8_t *pre8, int pre_stride,
204                                 const int32_t *wsrc, const int32_t *mask,
205                                 int width, int height) {
206   int y, x;
207   unsigned int sad = 0;
208   const uint16_t *pre = CONVERT_TO_SHORTPTR(pre8);
209 
210   for (y = 0; y < height; y++) {
211     for (x = 0; x < width; x++)
212       sad += ROUND_POWER_OF_TWO(abs(wsrc[x] - pre[x] * mask[x]), 12);
213 
214     pre += pre_stride;
215     wsrc += width;
216     mask += width;
217   }
218 
219   return sad;
220 }
221 
222 #define HIGHBD_OBMCSADMXN(m, n)                                \
223   unsigned int aom_highbd_obmc_sad##m##x##n##_c(               \
224       const uint8_t *ref, int ref_stride, const int32_t *wsrc, \
225       const int32_t *mask) {                                   \
226     return highbd_obmc_sad(ref, ref_stride, wsrc, mask, m, n); \
227   }
228 
229 /* clang-format off */
230 HIGHBD_OBMCSADMXN(128, 128)
231 HIGHBD_OBMCSADMXN(128, 64)
232 HIGHBD_OBMCSADMXN(64, 128)
233 HIGHBD_OBMCSADMXN(64, 64)
234 HIGHBD_OBMCSADMXN(64, 32)
235 HIGHBD_OBMCSADMXN(32, 64)
236 HIGHBD_OBMCSADMXN(32, 32)
237 HIGHBD_OBMCSADMXN(32, 16)
238 HIGHBD_OBMCSADMXN(16, 32)
239 HIGHBD_OBMCSADMXN(16, 16)
240 HIGHBD_OBMCSADMXN(16, 8)
241 HIGHBD_OBMCSADMXN(8, 16)
242 HIGHBD_OBMCSADMXN(8, 8)
243 HIGHBD_OBMCSADMXN(8, 4)
244 HIGHBD_OBMCSADMXN(4, 8)
245 HIGHBD_OBMCSADMXN(4, 4)
246 HIGHBD_OBMCSADMXN(4, 16)
247 HIGHBD_OBMCSADMXN(16, 4)
248 HIGHBD_OBMCSADMXN(8, 32)
249 HIGHBD_OBMCSADMXN(32, 8)
250 HIGHBD_OBMCSADMXN(16, 64)
251 HIGHBD_OBMCSADMXN(64, 16)
252 /* clang-format on */
253 #endif  // CONFIG_AV1_HIGHBITDEPTH
254 #endif  // !CONFIG_REALTIME_ONLY
255