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