FFmpeg
Loading...
Searching...
No Matches
uops_backend.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 "libavutil/avassert.h"
22
23#include "uops_tmpl.h"
24
25/**
26 * We want to disable FP contraction because this is a reference backend that
27 * establishes a bit-exact reference result.
28 */
29#ifdef __clang__
30#pragma STDC FP_CONTRACT OFF
31#elif AV_GCC_VERSION_AT_LEAST(4, 8)
32#pragma GCC optimize ("fp-contract=off")
33#elif defined(_MSC_VER)
34#pragma fp_contract (off)
35#endif
36
37#if AV_GCC_VERSION_AT_LEAST(4, 4)
38#pragma GCC optimize ("finite-math-only")
39#endif
40
41/* Integer types */
42#define IS_FLOAT 0
43# define BIT_DEPTH 8
44# include "uops_tmpl.c"
45# undef BIT_DEPTH
46# define BIT_DEPTH 16
47# include "uops_tmpl.c"
48# undef BIT_DEPTH
49# define BIT_DEPTH 32
50# include "uops_tmpl.c"
51# undef BIT_DEPTH
52#undef IS_FLOAT
53
54/* Floating point types */
55#define IS_FLOAT 1
56# define BIT_DEPTH 32
57# include "uops_tmpl.c"
58# undef BIT_DEPTH
59#undef IS_FLOAT
60
61/* Expanded as new uop types are implemented in the C/template backend */
62#define REF_ALL_UOPS(TYPE) \
63 SWS_FOR(TYPE, READ_PLANAR, REF_ENTRY) \
64 SWS_FOR(TYPE, READ_PLANAR_FV, REF_ENTRY) \
65 SWS_FOR(TYPE, READ_PLANAR_FH, REF_ENTRY) \
66 SWS_FOR(TYPE, READ_PACKED, REF_ENTRY) \
67 SWS_FOR(TYPE, READ_NIBBLE, REF_ENTRY) \
68 SWS_FOR(TYPE, READ_BIT, REF_ENTRY) \
69 SWS_FOR(TYPE, READ_PALETTE, REF_ENTRY) \
70 SWS_FOR(TYPE, PERMUTE, REF_ENTRY) \
71 SWS_FOR(TYPE, COPY, REF_ENTRY) \
72 SWS_FOR(TYPE, WRITE_PLANAR, REF_ENTRY) \
73 SWS_FOR(TYPE, WRITE_PACKED, REF_ENTRY) \
74 SWS_FOR(TYPE, WRITE_NIBBLE, REF_ENTRY) \
75 SWS_FOR(TYPE, WRITE_BIT, REF_ENTRY) \
76 SWS_FOR(TYPE, SWAP_BYTES, REF_ENTRY) \
77 SWS_FOR(TYPE, EXPAND_BIT, REF_ENTRY) \
78 SWS_FOR(TYPE, EXPAND_PAIR, REF_ENTRY) \
79 SWS_FOR(TYPE, EXPAND_QUAD, REF_ENTRY) \
80 SWS_FOR(TYPE, TO_U8, REF_ENTRY) \
81 SWS_FOR(TYPE, TO_U16, REF_ENTRY) \
82 SWS_FOR(TYPE, TO_U32, REF_ENTRY) \
83 SWS_FOR(TYPE, TO_F32, REF_ENTRY) \
84 SWS_FOR(TYPE, SCALE, REF_ENTRY) \
85 SWS_FOR(TYPE, ADD, REF_ENTRY) \
86 SWS_FOR(TYPE, MIN, REF_ENTRY) \
87 SWS_FOR(TYPE, MAX, REF_ENTRY) \
88 SWS_FOR(TYPE, UNPACK, REF_ENTRY) \
89 SWS_FOR(TYPE, PACK, REF_ENTRY) \
90 SWS_FOR(TYPE, LSHIFT, REF_ENTRY) \
91 SWS_FOR(TYPE, RSHIFT, REF_ENTRY) \
92 SWS_FOR(TYPE, CLEAR, REF_ENTRY) \
93 SWS_FOR(TYPE, LINEAR, REF_ENTRY) \
94 SWS_FOR(TYPE, DITHER, REF_ENTRY) \
95 SWS_FOR(TYPE, LUT_3D, REF_ENTRY) \
96 /* end of macro */
97
98static const SwsUOpTable uop_table = {
99 .block_size = SWS_BLOCK_SIZE,
100 .entries = {
101 REF_ALL_UOPS(U8)
102 REF_ALL_UOPS(U16)
103 REF_ALL_UOPS(U32)
104 REF_ALL_UOPS(F32)
105 NULL
106 },
107};
108
109static void process(const SwsOpExec *exec, const void *priv,
110 const int bx_start, const int y_start,
111 int bx_end, int y_end)
112{
113 const SwsOpChain *chain = priv;
114 const SwsOpImpl *impl = chain->impl;
115 block_t x, y, z, w; /* allocate enough space for any intermediate */
116
117 SwsOpIter iterdata;
118 SwsOpIter *iter = &iterdata; /* for CONTINUE() macro to work */
119 iter->exec = exec;
120 for (int i = 0; i < 4; i++) {
121 iter->in[i] = (uintptr_t) exec->in[i];
122 iter->out[i] = (uintptr_t) exec->out[i];
123 }
124
125 for (iter->y = y_start; iter->y < y_end; iter->y++) {
126 for (int block = bx_start; block < bx_end; block++) {
127 iter->x = block * SWS_BLOCK_SIZE;
128 CONTINUE(&x, &y, &z, &w);
129 }
130
131 const int y_bump = exec->in_bump_y ? exec->in_bump_y[iter->y] : 0;
132 for (int i = 0; i < 4; i++) {
133 iter->in[i] += exec->in_bump[i] + y_bump * exec->in_stride[i];
134 iter->out[i] += exec->out_bump[i];
135 }
136 }
137}
138
140{
141 int ret;
142
144 if (!chain)
145 return AVERROR(ENOMEM);
146
147 av_assert0(uops->num_ops > 0);
148 for (int i = 0; i < uops->num_ops; i++) {
149 const SwsUOpTable *table = &uop_table;
150 ret = ff_sws_uop_lookup(ctx, &table, 1, &uops->ops[i],
151 SWS_BLOCK_SIZE, chain);
152 if (ret < 0)
153 goto fail;
154 }
155
156 *out = (SwsCompiledOp) {
157 .slice_align = 1,
158 .block_size = SWS_BLOCK_SIZE,
159 .cpu_flags = chain->cpu_flags,
160 .priv = chain,
162 .func = process,
163 };
164
165 memcpy(out->over_read, chain->over_read, sizeof(out->over_read));
166 memcpy(out->over_write, chain->over_write, sizeof(out->over_write));
167
168 av_log(ctx, AV_LOG_DEBUG, "Compiled micro-ops:\n");
169 for (int i = 0; i < uops->num_ops; i++) {
171 ff_sws_uop_name(&uops->ops[i], name);
172 av_log(ctx, AV_LOG_DEBUG, " %s\n", name);
173 }
174
175 return 0;
176
177fail:
179 return ret;
180}
181
183{
185 if (!uops)
186 return AVERROR(ENOMEM);
187
188 int ret = ff_sws_ops_translate(ctx, ops, 0, uops);
189 if (ret < 0)
190 goto fail;
191
192 ret = compile_uops_c(ctx, uops, out);
193
194fail:
196 return ret;
197}
198
200 .name = "c",
201 .flags = SWS_BACKEND_C,
202 .compile = compile_c,
203 .compile_uops = compile_uops_c,
204 .hw_format = AV_PIX_FMT_NONE,
205};
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define NULL
Definition coverity.c:32
static int16_t block[64]
Definition dct.c:125
#define fail
Definition test.h:479
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
@ SWS_BACKEND_C
Template-based C reference implementation.
Definition swscale.h:116
uint8_t w
Definition llvidencdsp.c:39
const SwsOpBackend backend_c
Copyright (C) 2025 Niklas Haas.
SwsOpChain * ff_sws_op_chain_alloc(void)
Copyright (C) 2025 Niklas Haas.
Definition ops_chain.c:27
int ff_sws_uop_lookup(SwsContext *ctx, const SwsUOpTable *const tables[], int num_tables, const SwsUOp *uop, const int block_size, SwsOpChain *chain)
"Compile" a single uop by looking it up in a list of fixed size uop tables, in decreasing order of pr...
Definition ops_chain.c:116
void ff_sws_op_chain_free_cb(void *ptr)
Definition ops_chain.c:32
static void ff_sws_op_chain_free(SwsOpChain *chain)
Definition ops_chain.h:96
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
static const uint16_t table[]
Definition prosumer.c:203
const char * name
Definition qsvenc.c:142
Main external API structure.
Definition swscale.h:227
Compiled "chain" of operations, which can be dispatched efficiently.
Definition ops_chain.h:84
int over_read[4]
Definition ops_chain.h:90
SwsOpImpl impl[SWS_MAX_OPS+1]
Definition ops_chain.h:86
int over_write[4]
Definition ops_chain.h:91
int cpu_flags
Definition ops_chain.h:89
void(* free[SWS_MAX_OPS+1])(SwsOpPriv *)
Definition ops_chain.h:87
Copyright (C) 2026 Niklas Haas.
uint8_t * out[4]
const uint8_t * in[4]
ptrdiff_t in_stride[4]
ptrdiff_t in_bump[4]
Pointer bump, difference between stride and processed line size.
ptrdiff_t out_bump[4]
int32_t * in_bump_y
Line bump; determines how many additional lines to advance (after incrementing normally to the next l...
Internal context holding per-iter execution data.
Definition uops_tmpl.h:56
uintptr_t in[4]
Definition uops_tmpl.h:57
const SwsOpExec * exec
Definition uops_tmpl.h:62
uintptr_t out[4]
Definition uops_tmpl.h:58
Helper struct for representing a list of operations.
Definition ops.h:293
SwsUOp * ops
Definition uops.h:301
int num_ops
Definition uops.h:302
Copyright (C) 2025 Niklas Haas.
Definition ops_chain.h:154
#define av_log(a,...)
static FILE * out
Definition movenc.c:55
static AVFormatContext * ctx
Definition movenc.c:49
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:677
void ff_sws_uop_name(const SwsUOp *op, char buf[SWS_UOP_NAME_MAX])
Definition uops.c:81
SwsUOpList * ff_sws_uop_list_alloc(void)
Definition uops.c:203
void ff_sws_uop_list_free(SwsUOpList **p_ops)
Definition uops.c:189
#define SWS_UOP_NAME_MAX
Generate a unique name for a SwsUOp.
Definition uops.h:297
#define REF_ALL_UOPS(TYPE)
static int compile_c(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
static const SwsUOpTable uop_table
static int compile_uops_c(SwsContext *ctx, const SwsUOpList *uops, SwsCompiledOp *out)
static void process(const SwsOpExec *exec, const void *priv, const int bx_start, const int y_start, int bx_end, int y_end)
#define CONTINUE(...)
Definition uops_tmpl.h:107
#define SWS_BLOCK_SIZE
Copyright (C) 2026 Niklas Haas.
Definition uops_tmpl.h:40
static void process(NormalizeContext *s, AVFrame *in, AVFrame *out)