1 /**
2 * Copyright (C) 2025 Niklas Haas
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
24
26
27 #define Q(N) ((AVRational) { N, 1 })
28
30 {
32 }
33
35 {
36 if (!ptr)
37 return;
38
43 }
44
46 }
47
49 void (*free)(
void *),
const SwsOpPriv *priv)
50 {
54
58 chain->
free[idx + 1] = free;
60 return 0;
61 }
62
63 /**
64 * Match an operation against a reference operation. Returns a score for how
65 * well the reference matches the operation, or 0 if there is no match.
66 *
67 * If `ref->comps` has any flags set, they must be set in `op` as well.
68 * Likewise, if `ref->comps` has any components marked as unused, they must be
69 * marked as as unused in `ops` as well.
70 *
71 * For SWS_OP_LINEAR, `ref->linear.mask` must be a strict superset of
72 * `op->linear.mask`, but may not contain any columns explicitly ignored by
73 * `op->comps.unused`.
74 *
75 * For SWS_OP_READ, SWS_OP_WRITE, SWS_OP_SWAP_BYTES and SWS_OP_SWIZZLE, the
76 * exact type is not checked, just the size.
77 *
78 * Components set in `next.unused` are ignored when matching. If `flexible`
79 * is true, the op body is ignored - only the operation, pixel type, and
80 * component masks are checked.
81 */
83 {
84 int score = 10;
86 return 0;
87
93 /* Only the size matters for these operations */
95 return 0;
96 break;
97 default:
99 return 0;
100 break;
101 }
102
103 for (
int i = 0;
i < 4;
i++) {
105 if (
op->comps.unused[
i])
106 score += 1; /* Operating on fewer components is better .. */
107 else
108 return 0; /* .. but not too few! */
109 }
110 }
111
113 /* Clear pattern must match exactly, regardless of `entry->flexible` */
114 for (
int i = 0;
i < 4;
i++) {
116 return 0;
117 }
118 }
119
120 /* Flexible variants always match, but lower the score to prioritize more
121 * specific implementations if they exist */
123 return score - 5;
124
127 return 0;
130 if (
op->rw.elems !=
entry->rw.elems ||
131 op->rw.frac !=
entry->rw.frac ||
132 (
op->rw.elems > 1 &&
op->rw.packed !=
entry->rw.packed))
133 return 0;
134 return score;
136 return score;
139 for (
int i = 0;
i < 4 &&
op->pack.pattern[
i];
i++) {
140 if (
op->pack.pattern[
i] !=
entry->pack.pattern[
i])
141 return 0;
142 }
143 return score;
145 for (
int i = 0;
i < 4;
i++) {
146 if (!
op->c.q4[
i].den)
147 continue;
149 return 0;
150 }
151 return score;
155 return score;
157 for (
int i = 0;
i < 4;
i++) {
159 return 0;
160 }
161 return score;
163 if (
op->convert.to !=
entry->convert.to ||
164 op->convert.expand !=
entry->convert.expand)
165 return 0;
166 return score;
168 return op->dither.size_log2 ==
entry->dither_size ? score : 0;
172 return score;
174 /* All required elements must be present */
175 if (
op->lin.mask & ~
entry->linear_mask)
176 return 0;
177 /* To avoid operating on possibly undefined memory, filter out
178 * implementations that operate on more input components */
179 for (
int i = 0;
i < 4;
i++) {
181 return 0;
182 }
183 /* Prioritize smaller implementations */
185 return score;
187 return score;
189 break;
190 }
191
193 return 0;
194 }
195
199 {
200 static const SwsOp dummy = { .comps.unused = {
true,
true,
true,
true }};
205 int ret, best_score = 0, best_cpu_flags;
207
208 for (int n = 0; n < num_tables; n++) {
210 if (
table->block_size &&
table->block_size != block_size ||
212 continue;
213
214 for (
int i = 0;
table->entries[
i];
i++) {
217 if (score > best_score) {
218 best_score = score;
219 best_cpu_flags =
table->cpu_flags;
221 }
222 }
223 }
224
225 if (!best)
227
232 }
233
240 }
241
245 }
246
247 #define q2pixel(type, q) ((q).den ? (type) (q).num / (q).den : 0)
248
250 {
251 out->u8[0] =
op->c.u;
252 return 0;
253 }
254
256 {
262 default:
return AVERROR(EINVAL);
263 }
264 }
265
267 {
273 default:
return AVERROR(EINVAL);
274 }
275
276 return 0;
277 }
278
280 {
281 for (
int i = 0;
i < 4;
i++) {
287 default:
return AVERROR(EINVAL);
288 }
289 }
290
291 return 0;
292 }