FFmpeg
Loading...
Searching...
No Matches
uops.c
Go to the documentation of this file.
1/**
2 * Copyright (C) 2026 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
21#include <stdbool.h>
22
23#include "libavutil/avassert.h"
24#include "libavutil/mem.h"
25#include "libavutil/refstruct.h"
26
27#include "ops.h"
28#include "uops.h"
29#include "uops_list.h"
30
31int ff_sws_uop_cmp(const SwsUOp *a, const SwsUOp *b)
32{
33 if (a->type != b->type)
34 return (int) a->type - b->type;
35 if (a->uop != b->uop)
36 return (int) a->uop - b->uop;
37 if (a->mask != b->mask)
38 return (int) a->mask - b->mask;
39 return memcmp(&a->par, &b->par, sizeof(a->par));
40}
41
42static const struct {
43 char abbr[32];
45#define UOP_NAME(OP, ABBR) [OP] = { ABBR },
47#undef UOP_NAME
48};
49
50#define Q2PIXEL(val) ff_sws_pixel_from_q64(op->type, val)
51
53{
54 AVBPrint bp;
56
57 if (op->type != SWS_PIXEL_NONE)
58 av_bprintf(&bp, "%s_", ff_sws_pixel_type_name(op->type));
59 av_bprintf(&bp, "%s", uop_names[op->uop].abbr);
60
61 if (op->mask)
62 av_bprintf(&bp, "_%s", ff_sws_comp_mask_str(op->mask));
63
64 const SwsUOpParams *par = &op->par;
65 switch (op->uop) {
70 break;
72 av_bprintf(&bp, "_%x_%u_%u", par->shuffle.clear_value,
74 break;
75 case SWS_UOP_LSHIFT:
76 case SWS_UOP_RSHIFT:
77 av_bprintf(&bp, "_%u", par->shift.amount);
78 break;
79 case SWS_UOP_PERMUTE:
80 case SWS_UOP_COPY:
81 av_bprint_chars(&bp, '_', 1);
82 for (int i = 0; i < par->move.num_moves; i++)
83 av_bprint_chars(&bp, "txyzw"[par->move.dst[i] + 1], 1);
84 av_bprint_chars(&bp, '_', 1);
85 for (int i = 0; i < par->move.num_moves; i++)
86 av_bprint_chars(&bp, "txyzw"[par->move.src[i] + 1], 1);
87 break;
88 case SWS_UOP_PACK:
89 case SWS_UOP_UNPACK:
90 av_bprint_chars(&bp, '_', 1);
91 for (int i = 0; i < 4 && par->pack.pattern[i]; i++)
92 av_bprintf(&bp, "%x", par->pack.pattern[i]);
93 break;
94 case SWS_UOP_CLEAR:
95 av_bprint_chars(&bp, '_', 1);
96 for (int i = 0; i < 4; i++) {
97 if (!SWS_COMP_TEST(op->mask, i))
98 continue;
99 else if (SWS_COMP_TEST(par->clear.one, i))
100 av_bprint_chars(&bp, '1', 1);
101 else if (SWS_COMP_TEST(par->clear.zero, i))
102 av_bprint_chars(&bp, '0', 1);
103 else
104 av_bprint_chars(&bp, 'x', 1);
105 }
106 break;
107 case SWS_UOP_LINEAR:
109 for (int i = 0; i < 4; i++) {
110 if (!SWS_COMP_TEST(op->mask, i))
111 continue;
112 av_bprint_chars(&bp, '_', 1);
113 for (int j = 0; j < 5; j++) {
114 if (par->lin.one & SWS_MASK(i, j))
115 av_bprint_chars(&bp, '1', 1);
116 else if (par->lin.zero & SWS_MASK(i, j))
117 av_bprint_chars(&bp, '0', 1);
118 else if (par->lin.exact & SWS_MASK(i, j))
119 av_bprint_chars(&bp, 'X', 1);
120 else
121 av_bprint_chars(&bp, 'x', 1);
122 }
123 }
124 break;
125 case SWS_UOP_DITHER:
126 for (int i = 0; i < 4; i++) {
127 if (SWS_COMP_TEST(op->mask, i))
128 av_bprintf(&bp, "_%d", par->dither.y_offset[i]);
129 }
130 const unsigned size = 1u << par->dither.size_log2;
131 av_bprintf(&bp, "_%ux%u", size, size);
132 break;
133 case SWS_UOP_LUT_3D:
134 av_bprintf(&bp, "_%s", par->lut3d.dynamic ? "dynamic" : "static");
135 break;
136 }
137
139}
140
141static void uop_uninit(SwsUOp *uop)
142{
143 switch (uop->uop) {
144 case SWS_UOP_DITHER:
146 break;
151 break;
152 case SWS_UOP_LUT_3D:
154 break;
155 }
156
157 *uop = (SwsUOp) {0};
158}
159
161{
162 SwsUOpList *ops = *p_ops;
163 if (!ops)
164 return;
165
166 for (int i = 0; i < ops->num_ops; i++)
167 uop_uninit(&ops->ops[i]);
168
169 av_freep(&ops->ops);
170 av_free(ops);
171 *p_ops = NULL;
172}
173
175{
176 return av_mallocz(sizeof(SwsUOpList));
177}
178
180{
181 if (!av_dynarray2_add((void **) &uops->ops, &uops->num_ops,
182 sizeof(*uop), (uint8_t *) uop))
183 {
184 uop_uninit(uop);
185 return AVERROR(ENOMEM);
186 }
187
188 *uop = (SwsUOp) {0};
189 return 0;
190}
191
192void ff_sws_uop_list_remove_at(SwsUOpList *uops, int index, int count)
193{
194 const int end = uops->num_ops - count;
195 av_assert2(index >= 0 && count >= 0 && index + count <= uops->num_ops);
196 for (int i = 0; i < count; i++)
197 uop_uninit(&uops->ops[index + i]);
198 for (int i = index; i < end; i++)
199 uops->ops[i] = uops->ops[i + count];
200 uops->num_ops = end;
201}
202
204{
205 int max_offset = 0;
206 for (int i = 0; i < 4; i++)
207 max_offset = FFMAX(max_offset, dither->y_offset[i]);
208 return (1 << dither->size_log2) + max_offset;
209}
210
212{
213 switch (ff_sws_pixel_type_size(type)) {
214 case 1: return SWS_PIXEL_U8;
215 case 2: return SWS_PIXEL_U16;
216 case 4: return SWS_PIXEL_U32;
217 default: break;
218 }
219
220 av_unreachable("Invalid pixel type!");
221 return SWS_PIXEL_NONE;
222}
223
224static bool exact_product_f32(float a, float b)
225{
226 volatile float prod = a * b;
227 volatile float result = b ? prod / b : 0.0f;
228 return !b || result == a;
229}
230
232 const SwsComps *comps, int idx)
233{
234 const AVRational64 minq = comps->min[idx];
235 const AVRational64 maxq = comps->max[idx];
237 return true;
238 else if (!minq.den || !maxq.den)
239 return false; /* unknown bounds */
240
241 const SwsPixel min = ff_sws_pixel_from_q64(type, minq);
242 const SwsPixel max = ff_sws_pixel_from_q64(type, maxq);
243 switch (type) {
244 case SWS_PIXEL_F32:
245 return exact_product_f32(coef.f32, min.f32) &&
246 exact_product_f32(coef.f32, max.f32);
247 }
248
249 av_unreachable("Invalid pixel type!");
250 return false;
251}
252
254{
255 if (!(flags & SWS_UOP_FLAG_FMA))
256 return false;
257 if (!(ctx->flags & SWS_BITEXACT))
258 return true;
259 if (!ff_sws_pixel_type_is_int(op->type))
260 return false;
261
262 const int bits = ff_sws_pixel_type_size(op->type) * 8;
263 const uint64_t max_val = UINT64_MAX >> (64 - bits);
264
265 /* Maximum value representable losslessly as float. Note that this is
266 * currently true only for U8, but that may change if we ever update the
267 * value of SWS_FILTER_SCALE. */
268 return max_val * SWS_FILTER_SCALE <= (1 << 22);
269}
270
272 const SwsOp *op)
273{
274 SwsUOp uop = {
275 .type = op->type,
276 .mask = SWS_COMP_MASK(op->rw.elems > 0, op->rw.elems > 1,
277 op->rw.elems > 2, op->rw.elems > 3),
278 };
279
280 /* Non-filtered reads don't care about the exact pixel contents */
281 if (!op->rw.filter.op)
282 uop.type = pixel_type_to_int(op->type);
283
284 const bool is_read = op->op == SWS_OP_READ;
285 if (op->rw.filter.op) {
286 if (op->op == SWS_OP_WRITE || op->rw.frac || op->rw.mode != SWS_RW_PLANAR)
287 return AVERROR(ENOTSUP);
288 uop.par.filter.type = op->rw.filter.type;
289 uop.data.kernel = av_refstruct_ref(op->rw.filter.kernel);
290 if (op->rw.filter.op == SWS_OP_FILTER_H) {
292 } else if (check_filter_fma(ctx, flags, op)) {
294 } else {
296 }
297 } else if (op->rw.mode == SWS_RW_PACKED && op->rw.elems > 1) {
298 if (op->rw.frac)
299 return AVERROR(ENOTSUP);
301 } else if (op->rw.mode == SWS_RW_PALETTE) {
302 if (!(flags & SWS_UOP_FLAG_READ_PALETTE) || op->rw.frac || !is_read)
303 return AVERROR(ENOTSUP);
305 } else if (op->rw.frac == 3) {
306 uop.uop = is_read ? SWS_UOP_READ_BIT : SWS_UOP_WRITE_BIT;
307 } else if (op->rw.frac == 1) {
309 } else {
310 av_assert0(!op->rw.frac);
312 }
313
314 const int planes = ff_sws_rw_op_planes(op);
315 if (op->op == SWS_OP_READ) {
317 } else {
319 }
320
321 return ff_sws_uop_list_append(ops, &uop);
322}
323
324static int count_idx(const int *arr, size_t size, int val)
325{
326 int num = 0;
327 for (size_t i = 0; i < size; i++) {
328 if (arr[i] == val)
329 num++;
330 }
331
332 return num;
333}
334
335static int translate_swizzle(SwsUOpList *ops, const SwsOp *op)
336{
337 SwsUOp uop = {
338 .uop = SWS_UOP_PERMUTE,
339 .type = pixel_type_to_int(op->type),
341 };
342 SwsMoveUOp *par = &uop.par.move;
343
344 /* Mask of components that are not yet satisfied */
345 SwsCompMask todo = uop.mask;
346 for (int i = 0; i < 4; i++) {
347 if (op->swizzle.in[i] == i)
348 todo &= ~SWS_COMP(i);
349 }
350
351 /* Mask of components whose value is required for the final output */
352 SwsCompMask needed = 0;
353 for (int i = 0; i < 4; i++) {
354 if (SWS_OP_NEEDED(op, i))
355 needed |= SWS_COMP(op->swizzle.in[i]);
356 }
357
358 /* Current mapping of registers to components */
359 int idx[4 + 1] = { 0, 1, 2, 3, -1 }; /* +1 for tmp */
360
361 /* Decompose the swizzle mask into a series of register-register moves */
362 while (todo) {
363 int dst = -1, src = -1;
364
365 /* Find next unsatisfied dst <- src move that doesn't clobber a value */
366 for (dst = 0; dst < 4; dst++) {
367 if (!SWS_COMP_TEST(todo, dst))
368 continue; /* already satisfied */
369 const int cur = idx[dst];
370 if (count_idx(idx, FF_ARRAY_ELEMS(idx), cur) == 1 && SWS_COMP_TEST(needed, cur))
371 continue; /* clobbers last remaining, still-needed value */
372 for (src = 0; src < FF_ARRAY_ELEMS(idx); src++) {
373 if (idx[src] == op->swizzle.in[dst]) {
374 /* Prevent read-after-write dependency. */
375 if (par->num_moves > 0 && src == par->dst[par->num_moves - 1])
376 src = par->src[par->num_moves - 1];
377 break;
378 }
379 }
381 todo &= ~SWS_COMP(dst);
382 break;
383 }
384
385 if (dst == 4) {
386 /* Stuck in a cycle, break it by saving to the scratch register */
387 dst = 4;
388 for (src = 0; src < 4; src++) {
389 if (SWS_COMP_TEST(todo, src)) {
390 needed &= ~SWS_COMP(idx[src]);
391 break;
392 }
393 }
394 av_assert1(src < 4);
395 }
396
398 par->dst[par->num_moves] = dst > 3 ? -1 : dst;
399 par->src[par->num_moves] = src > 3 ? -1 : src;
400 par->num_moves++;
401 idx[dst] = idx[src];
402 }
403
404 /* Check for duplicates in the final register map */
405 SwsCompMask seen = 0;
406 for (int i = 0; i < 4; i++) {
407 if (!SWS_COMP_TEST(uop.mask, i))
408 continue;
409 av_assert2(idx[i] >= 0); /* should be no tmp register */
410 const SwsCompMask bit = SWS_COMP(idx[i]);
411 if (seen & bit) {
412 uop.uop = SWS_UOP_COPY;
413 break;
414 }
415 seen |= bit;
416 }
417
418 /* Add any extra unused components to the mask, to prevent generating
419 * duplicate uops like permute_xyz_txy_xyt and permute_xyzw_txy_xyt */
420 for (int i = 0; i < 4; i++) {
421 const SwsCompMask bit = SWS_COMP(i);
422 if (!(seen & bit) && idx[i] == i)
423 uop.mask |= bit;
424 }
425
426 return ff_sws_uop_list_append(ops, &uop);
427}
428
430{
431 SwsUOp uop = {
432 .type = op->type,
433 .uop = SWS_UOP_DITHER,
434 .par.dither.size_log2 = op->dither.size_log2,
435 };
436
437 if ((flags & SWS_UOP_FLAG_ADD) && op->dither.size_log2 == 0) {
438 /* Constant offset */
439 const SwsPixel val = Q2PIXEL(op->dither.matrix[0]);
440 uop.uop = SWS_UOP_ADD;
441 for (int i = 0; i < 4; i++) {
442 if (!SWS_OP_NEEDED(op, i) || op->dither.y_offset[i] < 0)
443 continue;
444 uop.mask |= SWS_COMP(i);
445 uop.data.vec4[i] = val;
446 }
447
448 return ff_sws_uop_list_append(ops, &uop);
449 }
450
451 const int size = 1 << op->dither.size_log2;
452 for (int i = 0; i < 4; i++) {
453 if (!SWS_OP_NEEDED(op, i) || op->dither.y_offset[i] < 0)
454 continue;
455 const uint8_t off = op->dither.y_offset[i] & (size - 1);
456 uop.mask |= SWS_COMP(i);
457 uop.par.dither.y_offset[i] = off;
458 }
459
460 /* Allocate extra rows to allow over-reading for row offsets. Note that
461 * y_offset is currently never larger than 5, so the extra space needed
462 * for this over-allocation is bounded by 5 * size * sizeof(float),
463 * typically 320 bytes for a 16x16 dither matrix. */
464 const int stride = size * sizeof(SwsPixel);
465 const int num_rows = ff_sws_dither_height(&uop.par.dither);
466 SwsPixel *matrix = uop.data.ptr = av_refstruct_allocz(num_rows * stride);
467 if (!matrix)
468 return AVERROR(ENOMEM);
469
470 for (int i = 0; i < size * size; i++)
471 matrix[i] = Q2PIXEL(op->dither.matrix[i]);
472 memcpy(&matrix[size * size], matrix, (num_rows - size) * stride);
473
474 return ff_sws_uop_list_append(ops, &uop);
475}
476
478 SwsUOpFlags flags, const SwsOp *op,
479 const SwsComps *input)
480{
481 SwsUOp uop = {
482 .type = op->type,
483 .uop = SWS_UOP_LINEAR,
484 };
485
486 const uint32_t mask = ff_sws_linear_mask(&op->lin);
487 const bool bitexact = ctx->flags & SWS_BITEXACT;
488 uint32_t exact = 0;
489
490 for (int i = 0; i < 4; i++) {
491 if (!SWS_OP_NEEDED(op, i) || !(mask & SWS_MASK_ROW(i))) {
492 uop.par.lin.zero |= SWS_MASK_ROW(i);
493 continue;
494 }
495 uop.mask |= SWS_COMP(i);
496 bool nonzero = (op->lin.m[i][4].num != 0);
497 for (int j = 0; j < 5; j++) {
498 const AVRational64 k = op->lin.m[i][j];
499 const SwsPixel px = Q2PIXEL(k);
500 uop.data.mat4x5[i][j] = px;
501 if (k.num == 0)
502 uop.par.lin.zero |= SWS_MASK(i, j);
503 else if (j < 4 && k.num == k.den)
504 uop.par.lin.one |= SWS_MASK(i, j);
505 else if (j < 4 && nonzero && (!bitexact || exact_prod(uop.type, px, input, j)))
506 exact |= SWS_MASK(i, j);
507 if (k.num != 0)
508 nonzero = true;
509 }
510 }
511
513 /* multiplication by 1 and 0 are always exact by definition */
515 uop.par.lin.exact = exact | uop.par.lin.zero | uop.par.lin.one;
516 }
517
518 return ff_sws_uop_list_append(ops, &uop);
519}
520
522 const SwsOp *op, const SwsComps *input)
523{
524 switch (op->op) {
525 case SWS_OP_FILTER_H:
526 case SWS_OP_FILTER_V:
527 return AVERROR(ENOTSUP); /* always handled by subpass splitting */
528 case SWS_OP_READ:
529 case SWS_OP_WRITE:
530 return translate_rw_op(ctx, uops, flags, op);
531 case SWS_OP_SWIZZLE:
532 return translate_swizzle(uops, op);
533 case SWS_OP_DITHER:
534 return translate_dither_op(uops, flags, op);
535 case SWS_OP_LINEAR:
536 return translate_linear_op(ctx, uops, flags, op, input);
537 default:
538 break;
539 }
540
541 /* Default handling for "simple" ops */
542 SwsUOp uop = {
543 .type = op->type,
544 .uop = SWS_UOP_INVALID,
546 };
547
548 switch (op->op) {
549 case SWS_OP_CONVERT:
550 switch (op->convert.to) {
551 case SWS_PIXEL_U8: uop.uop = SWS_UOP_TO_U8; break;
552 case SWS_PIXEL_U16: uop.uop = SWS_UOP_TO_U16; break;
553 case SWS_PIXEL_U32: uop.uop = SWS_UOP_TO_U32; break;
554 case SWS_PIXEL_F32: uop.uop = SWS_UOP_TO_F32; break;
555 }
556 break;
557 case SWS_OP_UNPACK:
558 case SWS_OP_PACK:
560 uop.mask = 0;
561 for (int i = 0; i < 4 && op->pack.pattern[i]; i++) {
562 uop.par.pack.pattern[i] = op->pack.pattern[i];
563 if (op->op == SWS_OP_PACK || SWS_OP_NEEDED(op, i))
564 uop.mask |= SWS_COMP(i);
565 }
566 break;
567 case SWS_OP_LSHIFT:
568 case SWS_OP_RSHIFT:
570 uop.par.shift.amount = op->shift.amount;
571 break;
572 case SWS_OP_CLEAR:
573 uop.uop = SWS_UOP_CLEAR;
574 uop.type = pixel_type_to_int(op->type);
575 uop.mask &= op->clear.mask;
576 for (int i = 0; i < 4; i++) {
577 if (!SWS_COMP_TEST(op->clear.mask, i))
578 continue;
579 const AVRational64 v = op->clear.value[i];
580 const SwsPixel px = Q2PIXEL(op->clear.value[i]);
581 uop.data.vec4[i] = px;
582 if (v.num == 0)
583 uop.par.clear.zero |= SWS_COMP(i);
584 else if (ff_sws_pixel_is_1s(op->type, px))
585 uop.par.clear.one |= SWS_COMP(i);
586 }
587 break;
588 case SWS_OP_SCALE:
589 uop.uop = SWS_UOP_SCALE;
590 uop.data.scalar = Q2PIXEL(op->scale.factor);
591 break;
592 case SWS_OP_MIN:
593 case SWS_OP_MAX:
594 uop.uop = op->op == SWS_OP_MIN ? SWS_UOP_MIN : SWS_UOP_MAX;
595 uop.mask &= ff_sws_comp_mask_q4(op->clamp.limit);
596 for (int i = 0; i < 4; i++) {
597 if (SWS_COMP_TEST(uop.mask, i))
598 uop.data.vec4[i] = Q2PIXEL(op->clamp.limit[i]);
599 }
600 break;
603 uop.type = pixel_type_to_int(op->type);
604 break;
605 case SWS_OP_LUT_3D:
606 uop.uop = SWS_UOP_LUT_3D;
607 uop.par.lut3d.dynamic = op->lut3d.dynamic;
608 uop.data.lut3d = av_refstruct_ref_c(op->lut3d.lut);
609 break;
610 default:
611 return AVERROR(ENOTSUP);
612 }
613
615 return ff_sws_uop_list_append(uops, &uop);
616}
617
620{
621 SwsComps input = ops->comps_src;
622 for (int i = 0; i < ops->num_ops; i++) {
623 const SwsOp *op = &ops->ops[i];
624 const int pixel_size = ff_sws_pixel_type_size(op->type);
625 if (pixel_size > uops->pixel_size_max)
626 uops->pixel_size_max = pixel_size;
627
628 int ret = translate_op(ctx, uops, flags, op, &input);
629 if (ret < 0)
630 return ret;
631 input = ops->ops[i].comps;
632 }
633
634 return ff_sws_uop_list_optimize(ctx, flags, uops);
635}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static double val(void *priv, double ch)
Definition aeval.c:77
static AVFormatContext * ctx
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition avassert.h:68
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
#define av_unreachable(msg)
Asserts that are used as compiler optimization hints depending upon ASSERT_LEVEL and NBDEBUG.
Definition avassert.h:109
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
void av_bprintf(AVBPrint *buf, const char *fmt,...)
Definition bprint.c:121
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define bit(string, value)
Definition cbs_mpeg2.c:56
#define NULL
Definition coverity.c:32
#define min(a, b)
#define max(a, b)
static const uint8_t bits[8]
Definition fastaudio.c:100
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition bprint.h:218
void av_bprint_chars(AVBPrint *buf, char c, unsigned n)
Append char c n times to a print buffer.
Definition bprint.c:129
void av_bprint_init_for_buffer(AVBPrint *buf, char *buffer, unsigned size)
Init a print buffer using a pre-existing buffer.
Definition bprint.c:84
#define AVERROR(e)
Definition error.h:45
void * av_dynarray2_add(void **tab_ptr, int *nb_ptr, size_t elem_size, const uint8_t *elem_data)
Add an element of size elem_size to a dynamic array.
Definition mem.c:447
@ SWS_BITEXACT
Definition swscale.h:178
int index
Definition gxfenc.c:90
int a
#define b
Definition input.c:43
uint32_t type
Definition jpegmpfenc.c:80
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
Definition anm.c:76
@ SWS_FILTER_SCALE
14-bit coefficients are picked to fit comfortably within int16_t for efficient SIMD processing (e....
Definition filters.h:40
static const struct @257111027162314367033347246032313251342043035002 planes[]
static const uint16_t mask[17]
Definition lzw.c:38
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
uint32_t ff_sws_linear_mask(const SwsLinearOp *c)
Definition ops.c:797
SwsCompMask ff_sws_comp_mask_needed(const SwsOp *op)
Definition ops.c:123
const char * ff_sws_pixel_type_name(SwsPixelType type)
Definition ops.c:56
SwsCompMask ff_sws_comp_mask_q4(const AVRational64 q[4])
Definition ops.c:100
int ff_sws_rw_op_planes(const SwsOp *op)
Return the number of planes involved in a read/write operation.
Definition ops.c:133
@ SWS_OP_RSHIFT
Definition ops.h:49
@ SWS_OP_SWIZZLE
Definition ops.h:43
@ SWS_OP_LSHIFT
Definition ops.h:48
@ SWS_OP_FILTER_V
Definition ops.h:64
@ SWS_OP_SCALE
Definition ops.h:56
@ SWS_OP_FILTER_H
Definition ops.h:63
@ SWS_OP_WRITE
Definition ops.h:41
@ SWS_OP_READ
Definition ops.h:40
@ SWS_OP_CLEAR
Definition ops.h:52
@ SWS_OP_SWAP_BYTES
Definition ops.h:42
@ SWS_OP_MIN
Definition ops.h:54
@ SWS_OP_UNPACK
Definition ops.h:46
@ SWS_OP_LINEAR
Definition ops.h:57
@ SWS_OP_PACK
Definition ops.h:47
@ SWS_OP_DITHER
Definition ops.h:60
@ SWS_OP_MAX
Definition ops.h:55
@ SWS_OP_LUT_3D
Definition ops.h:67
@ SWS_OP_CONVERT
Definition ops.h:53
@ SWS_RW_PALETTE
Definition ops.h:109
@ SWS_RW_PLANAR
Note: 1-component reads are either SWS_RW_PLANAR or SWS_RW_PACKED, depending on the underlying interp...
Definition ops.h:107
@ SWS_RW_PACKED
Definition ops.h:108
#define SWS_OP_NEEDED(op, idx)
Definition ops.h:269
int ff_sws_uop_list_optimize(SwsContext *ctx, SwsUOpFlags flags, SwsUOpList *uops)
Called internally by ff_sws_ops_translate().
void av_refstruct_unref(void *objp)
Decrement the reference count of the underlying object and automatically free the object if there are...
Definition refstruct.c:121
const void * av_refstruct_ref_c(const void *obj)
Analog of av_refstruct_ref(), but for constant objects.
Definition refstruct.c:150
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
Definition refstruct.c:141
static void * av_refstruct_allocz(size_t size)
Equivalent to av_refstruct_alloc_ext(size, 0, NULL, NULL)
Definition refstruct.h:105
#define FF_ARRAY_ELEMS(a)
64-bit Rational number (pair of numerator and denominator).
Definition rational64.h:52
int64_t num
Numerator.
Definition rational64.h:53
int64_t den
Denominator.
Definition rational64.h:54
SwsCompMask one
Definition uops.h:247
SwsCompMask zero
Definition uops.h:248
Definition ops.h:86
AVRational64 min[4]
Definition ops.h:91
AVRational64 max[4]
Definition ops.h:91
Main external API structure.
Definition swscale.h:227
uint8_t size_log2
Definition uops.h:267
uint8_t y_offset[4]
Definition uops.h:266
SwsPixelType type
Definition uops.h:225
uint32_t zero
Definition uops.h:253
uint32_t one
Definition uops.h:252
uint32_t exact
Definition uops.h:256
int dynamic
Definition uops.h:271
int8_t src[SWS_UOP_MOVE_MAX]
Definition uops.h:239
int num_moves
Definition uops.h:235
int8_t dst[SWS_UOP_MOVE_MAX]
Definition uops.h:238
Helper struct for representing a list of operations.
Definition ops.h:297
SwsComps comps_src
Source component metadata associated with pixel values from each corresponding component (in plane/me...
Definition ops.h:316
SwsOp * ops
Definition ops.h:298
int num_ops
Definition ops.h:299
Definition ops.h:241
SwsComps comps
Metadata about the operation's input/output components.
Definition ops.h:266
uint8_t pattern[4]
Definition uops.h:243
uint8_t amount
Definition uops.h:229
uint8_t write_size
Definition uops.h:216
uint8_t read_size
Definition uops.h:215
uint8_t clear_value
Definition uops.h:214
SwsUOp * ops
Definition uops.h:329
int pixel_size_max
Definition uops.h:335
int num_ops
Definition uops.h:330
SwsCompMask planes_in
Definition uops.h:333
SwsCompMask planes_out
Definition uops.h:334
Definition uops.h:292
SwsPixel scalar
Definition uops.h:303
SwsCompMask mask
Definition uops.h:296
SwsUOpType uop
Definition uops.h:295
SwsUOpParams par
Definition uops.h:297
const SwsLut3D * lut3d
Definition uops.h:307
SwsFilterWeights * kernel
Definition uops.h:301
SwsPixel * ptr
Definition uops.h:302
union SwsUOp::@242237116251216327057105100216205033300341206345 data
SwsPixelType type
Definition uops.h:294
SwsPixel mat4x5[4][5]
Definition uops.h:305
SwsPixel vec4[4]
Definition uops.h:304
#define stride
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
#define src
Definition vp8dsp.c:248
int num
Definition error.c:23
int size
float f32
Definition uops.h:85
SwsMoveUOp move
Definition uops.h:284
SwsClearUOp clear
Definition uops.h:286
SwsDitherUOp dither
Definition uops.h:288
SwsFilterUOp filter
Definition uops.h:282
SwsLut3DUOp lut3d
Definition uops.h:289
SwsShuffleUOp shuffle
Definition uops.h:281
SwsLinearUOp lin
Definition uops.h:287
SwsShiftUOp shift
Definition uops.h:283
SwsPackUOp pack
Definition uops.h:285
char abbr[32]
Definition uops.c:43
int ff_sws_ops_translate(SwsContext *ctx, const SwsOpList *ops, SwsUOpFlags flags, SwsUOpList *uops)
Translate a list of operations down to micro-ops, which can be further optimized and then directly ex...
Definition uops.c:618
int ff_sws_dither_height(const SwsDitherUOp *dither)
Computes (1 << size_log2) + MAX(y_offset).
Definition uops.c:203
static bool check_filter_fma(SwsContext *ctx, SwsUOpFlags flags, const SwsOp *op)
Definition uops.c:253
static void uop_uninit(SwsUOp *uop)
Definition uops.c:141
int ff_sws_uop_list_append(SwsUOpList *uops, SwsUOp *uop)
Definition uops.c:179
#define UOP_NAME(OP, ABBR)
static bool exact_prod(SwsPixelType type, SwsPixel coef, const SwsComps *comps, int idx)
Definition uops.c:231
void ff_sws_uop_name(const SwsUOp *op, char buf[SWS_UOP_NAME_MAX])
Definition uops.c:52
static int translate_linear_op(SwsContext *ctx, SwsUOpList *ops, SwsUOpFlags flags, const SwsOp *op, const SwsComps *input)
Definition uops.c:477
static int translate_dither_op(SwsUOpList *ops, SwsUOpFlags flags, const SwsOp *op)
Definition uops.c:429
int ff_sws_uop_cmp(const SwsUOp *a, const SwsUOp *b)
Copyright (C) 2026 Niklas Haas.
Definition uops.c:31
SwsUOpList * ff_sws_uop_list_alloc(void)
Definition uops.c:174
void ff_sws_uop_list_free(SwsUOpList **p_ops)
Definition uops.c:160
#define Q2PIXEL(val)
Definition uops.c:50
static int translate_swizzle(SwsUOpList *ops, const SwsOp *op)
Definition uops.c:335
static int translate_rw_op(SwsContext *ctx, SwsUOpList *ops, SwsUOpFlags flags, const SwsOp *op)
Definition uops.c:271
void ff_sws_uop_list_remove_at(SwsUOpList *uops, int index, int count)
Definition uops.c:192
static int translate_op(SwsContext *ctx, SwsUOpList *uops, SwsUOpFlags flags, const SwsOp *op, const SwsComps *input)
Definition uops.c:521
static int count_idx(const int *arr, size_t size, int val)
Definition uops.c:324
static const struct @145311200363243152256244361015041277337174162300 uop_names[SWS_UOP_TYPE_NB]
static SwsPixelType pixel_type_to_int(const SwsPixelType type)
Definition uops.c:211
static bool exact_product_f32(float a, float b)
Definition uops.c:224
uint32_t SwsUOpFlags
Definition uops.h:147
SwsPixelType
Definition uops.h:40
@ SWS_PIXEL_F32
Definition uops.h:45
@ SWS_PIXEL_U32
Definition uops.h:44
@ SWS_PIXEL_U16
Definition uops.h:43
@ SWS_PIXEL_NONE
Definition uops.h:41
@ SWS_PIXEL_U8
Definition uops.h:42
#define SWS_COMP(X)
Definition uops.h:122
#define ff_sws_comp_mask_str(mask)
Definition uops.h:135
#define SWS_UOP_MOVE_MAX
Definition uops.h:234
#define SWS_MASK_ROW(I)
Definition uops.h:261
#define SWS_COMP_TEST(mask, X)
Definition uops.h:123
#define SWS_COMP_ELEMS(N)
Definition uops.h:125
#define SWS_MASK(I, J)
Definition uops.h:259
@ SWS_UOP_TO_U8
Definition uops.h:187
@ SWS_UOP_PACK
Definition uops.h:200
@ SWS_UOP_PERMUTE
Definition uops.h:179
@ SWS_UOP_READ_PLANAR
Definition uops.h:161
@ SWS_UOP_WRITE_PLANAR
Definition uops.h:170
@ SWS_UOP_READ_NIBBLE
Definition uops.h:166
@ SWS_UOP_MAX
Definition uops.h:196
@ SWS_UOP_READ_BIT
Definition uops.h:167
@ SWS_UOP_SWAP_BYTES
Definition uops.h:183
@ SWS_UOP_MIN
Definition uops.h:195
@ SWS_UOP_LINEAR
Definition uops.h:204
@ SWS_UOP_RSHIFT
Definition uops.h:202
@ SWS_UOP_COPY
Definition uops.h:180
@ SWS_UOP_WRITE_NIBBLE
Definition uops.h:172
@ SWS_UOP_INVALID
Definition uops.h:158
@ SWS_UOP_LINEAR_FMA
Definition uops.h:205
@ SWS_UOP_READ_PLANAR_FH
Definition uops.h:162
@ SWS_UOP_SCALE
Definition uops.h:193
@ SWS_UOP_WRITE_PACKED
Definition uops.h:171
@ SWS_UOP_WRITE_BIT
Definition uops.h:173
@ SWS_UOP_READ_PLANAR_FV_FMA
Definition uops.h:164
@ SWS_UOP_READ_PACKED
Definition uops.h:165
@ SWS_UOP_LUT_3D
Definition uops.h:207
@ SWS_UOP_TO_U16
Definition uops.h:188
@ SWS_UOP_DITHER
Definition uops.h:206
@ SWS_UOP_ADD
Definition uops.h:194
@ SWS_UOP_TYPE_NB
Definition uops.h:210
@ SWS_UOP_CLEAR
Definition uops.h:203
@ SWS_UOP_READ_PALETTE
Definition uops.h:168
@ SWS_UOP_READ_PLANAR_FV
Definition uops.h:163
@ SWS_UOP_TO_U32
Definition uops.h:189
@ SWS_UOP_RW_SHUFFLE
Definition uops.h:176
@ SWS_UOP_UNPACK
Definition uops.h:199
@ SWS_UOP_TO_F32
Definition uops.h:190
@ SWS_UOP_LSHIFT
Definition uops.h:201
#define SWS_COMP_MASK(X, Y, Z, W)
Definition uops.h:127
static bool ff_sws_pixel_is_1s(SwsPixelType type, SwsPixel val)
Definition uops.h:104
static SwsPixel ff_sws_pixel_from_q64(SwsPixelType type, AVRational64 val)
Definition uops.h:91
@ SWS_UOP_FLAG_FMA
Definition uops.h:150
@ SWS_UOP_FLAG_ADD
Definition uops.h:154
@ SWS_UOP_FLAG_READ_PALETTE
Definition uops.h:153
#define SWS_UOP_NAME_MAX
Generate a unique name for a SwsUOp.
Definition uops.h:325
static av_const bool ff_sws_pixel_type_is_int(SwsPixelType type)
Definition uops.h:64
uint8_t SwsCompMask
Bit-mask of components.
Definition uops.h:118
static av_const int ff_sws_pixel_type_size(SwsPixelType type)
Definition uops.h:51
#define UOPS_LIST(ENTRY)
This file is part of FFmpeg.
Definition uops_list.h:23
static const uint16_t dither[8][8]
Definition vf_gradfun.c:46