FFmpeg
Loading...
Searching...
No Matches
ops_chain.c
Go to the documentation of this file.
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
21#include "libavutil/avassert.h"
22#include "libavutil/mem.h"
23#include "libavutil/rational.h"
24
25#include "ops_chain.h"
26
28{
29 return av_mallocz(sizeof(SwsOpChain));
30}
31
33{
34 if (!ptr)
35 return;
36
37 SwsOpChain *chain = ptr;
38 for (int i = 0; i < chain->num_impl + 1; i++) {
39 if (chain->free[i])
40 chain->free[i](&chain->impl[i].priv);
41 }
42
43 av_free(chain);
44}
45
47 void (*free)(SwsOpPriv *), const SwsOpPriv *priv)
48{
49 const int idx = chain->num_impl;
50 if (idx == SWS_MAX_OPS)
51 return AVERROR(EINVAL);
52
54 chain->impl[idx].cont = func;
55 chain->impl[idx + 1].priv = *priv;
56 chain->free[idx + 1] = free;
57 chain->num_impl++;
58 return 0;
59}
60
61#define q2pixel(type, q) ((q).den ? (type) (q).num / (q).den : 0)
62
63#if ARCH_AARCH64
65{
66 const SwsOp *op = params->op;
67 const AVRational64 factor = op->scale.factor;
68 switch (op->type) {
69 case SWS_PIXEL_U8: out->priv.u8[0] = q2pixel(uint8_t, factor); break;
70 case SWS_PIXEL_U16: out->priv.u16[0] = q2pixel(uint16_t, factor); break;
71 case SWS_PIXEL_U32: out->priv.u32[0] = q2pixel(uint32_t, factor); break;
72 case SWS_PIXEL_F32: out->priv.f32[0] = q2pixel(float, factor); break;
73 default: return AVERROR(EINVAL);
74 }
75
76 return 0;
77}
78
80{
81 const SwsOp *op = params->op;
82 for (int i = 0; i < 4; i++) {
83 const AVRational64 limit = op->clamp.limit[i];
84 switch (op->type) {
85 case SWS_PIXEL_U8: out->priv.u8[i] = q2pixel(uint8_t, limit); break;
86 case SWS_PIXEL_U16: out->priv.u16[i] = q2pixel(uint16_t, limit); break;
87 case SWS_PIXEL_U32: out->priv.u32[i] = q2pixel(uint32_t, limit); break;
88 case SWS_PIXEL_F32: out->priv.f32[i] = q2pixel(float, limit); break;
89 default: return AVERROR(EINVAL);
90 }
91 }
92
93 return 0;
94}
95
97{
98 const SwsOp *op = params->op;
99 for (int i = 0; i < 4; i++) {
100 const AVRational64 value = op->clear.value[i];
101 if (!value.den)
102 continue;
103 switch (op->type) {
104 case SWS_PIXEL_U8: out->priv.u8[i] = q2pixel(uint8_t, value); break;
105 case SWS_PIXEL_U16: out->priv.u16[i] = q2pixel(uint16_t, value); break;
106 case SWS_PIXEL_U32: out->priv.u32[i] = q2pixel(uint32_t, value); break;
107 case SWS_PIXEL_F32: out->priv.f32[i] = q2pixel(float, value); break;
108 default: return AVERROR(EINVAL);
109 }
110 }
111
112 return 0;
113}
114#endif
115
117 int num_tables, const SwsUOp *uop, const int block_size,
118 SwsOpChain *chain)
119{
120 const unsigned cpu_flags = av_get_cpu_flags();
121 const SwsUOpEntry *match = NULL;
122 int ret;
123
125 .ctx = ctx,
126 .uop = uop
127 };
128
129 for (int n = 0; !match && n < num_tables; n++) {
130 const SwsUOpTable *table = params.table = tables[n];
131 if (table->block_size && table->block_size != block_size ||
132 table->cpu_flags & ~cpu_flags)
133 continue;
134
135 for (int i = 0; table->entries[i]; i++) {
136 const SwsUOpEntry *entry = table->entries[i];
137 const SwsUOp entry_uop = {
138 .uop = entry->uop,
139 .type = entry->type,
140 .mask = entry->mask,
141 .par = entry->par,
142 };
143
144 if (ff_sws_uop_cmp(uop, &entry_uop) != 0)
145 continue;
146 if (entry->check && !entry->check(&params))
147 continue;
148
149 match = entry;
150 break;
151 }
152 }
153
154 if (!match) {
155 char name[64];
156 ff_sws_uop_name(uop, name);
157 av_log(ctx, AV_LOG_DEBUG, "No implementation found for: %s\n", name);
158 return AVERROR(ENOTSUP);
159 }
160
161 SwsImplResult res = {0};
162 if (match->setup) {
163 ret = match->setup(&params, &res);
164 if (ret < 0)
165 return ret;
166 }
167
168 ret = ff_sws_op_chain_append(chain, res.func ? res.func : match->func,
169 res.free, &res.priv);
170 if (ret < 0) {
171 if (res.free)
172 res.free(&res.priv);
173 return ret;
174 }
175
176 for (int i = 0; i < 4; i++) {
177 chain->over_read[i] = FFMAX(chain->over_read[i], res.over_read[i]);
178 chain->over_write[i] = FFMAX(chain->over_write[i], res.over_write[i]);
179 }
180
181 chain->cpu_flags |= params.table->cpu_flags;
182 return 0;
183}
184
186{
187 const SwsUOp *uop = params->uop;
188 const SwsPixel scalar = uop->data.scalar;
189 switch (uop->type) {
190 case SWS_PIXEL_U8: out->priv.u8[0] = scalar.u8; break;
191 case SWS_PIXEL_U16: out->priv.u16[0] = scalar.u16; break;
192 case SWS_PIXEL_U32: out->priv.u32[0] = scalar.u32; break;
193 case SWS_PIXEL_F32: out->priv.f32[0] = scalar.f32; break;
194 default: return AVERROR(EINVAL);
195 }
196
197 return 0;
198}
199
201{
202 const SwsUOp *uop = params->uop;
203 for (int i = 0; i < 4; i++) {
204 const SwsPixel vi = uop->data.vec4[i];
205 switch (uop->type) {
206 case SWS_PIXEL_U8: out->priv.u8[i] = vi.u8; break;
207 case SWS_PIXEL_U16: out->priv.u16[i] = vi.u16; break;
208 case SWS_PIXEL_U32: out->priv.u32[i] = vi.u32; break;
209 case SWS_PIXEL_F32: out->priv.f32[i] = vi.f32; break;
210 default: return AVERROR(EINVAL);
211 }
212 }
213
214 return 0;
215}
SwsAArch64OpImplParams params
Definition ops.c:51
#define entry
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition avassert.h:58
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define NULL
Definition coverity.c:32
double value
Definition eval.c:102
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition log.h:231
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
int(* func)(AVBPrint *dst, const char *in, const char *arg)
Definition jacosubdec.c:66
static const int factor[16]
Definition vf_pp7.c:98
static atomic_int cpu_flags
Definition cpu.c:56
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
Definition cpu.c:109
#define FFMAX(a, b)
Definition macros.h:47
Memory handling functions.
int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func, void(*free)(SwsOpPriv *), const SwsOpPriv *priv)
Definition ops_chain.c:46
int ff_sws_setup_vec4(const SwsImplParams *params, SwsImplResult *out)
Definition ops_chain.c:200
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
#define q2pixel(type, q)
Definition ops_chain.c:61
int ff_sws_setup_scalar(const SwsImplParams *params, SwsImplResult *out)
Definition ops_chain.c:185
#define SWS_MAX_OPS
Definition ops_chain.h:85
void(* SwsFuncPtr)(void)
Per-kernel execution context.
Definition ops_chain.h:70
int ff_sws_setup_clamp(const SwsImplParams *params, SwsImplResult *out)
int ff_sws_setup_scale(const SwsImplParams *params, SwsImplResult *out)
int ff_sws_setup_clear(const SwsImplParams *params, SwsImplResult *out)
static const uint16_t table[]
Definition prosumer.c:203
const char * name
Definition qsvenc.c:142
Utilities for rational number calculation.
64-bit Rational number (pair of numerator and denominator).
Definition rational64.h:52
Main external API structure.
Definition swscale.h:227
int over_write[4]
Definition ops_chain.h:119
SwsFuncPtr func
Definition ops_chain.h:115
SwsOpPriv priv
Definition ops_chain.h:116
int over_read[4]
Definition ops_chain.h:118
void(* free)(SwsOpPriv *priv)
Definition ops_chain.h:117
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
int num_impl
Definition ops_chain.h:88
void(* free[SWS_MAX_OPS+1])(SwsOpPriv *)
Definition ops_chain.h:87
SwsFuncPtr cont
Definition ops_chain.h:72
SwsOpPriv priv
Definition ops_chain.h:73
Definition ops.h:237
SwsFuncPtr func
Definition ops_chain.h:130
int(* setup)(const SwsImplParams *params, SwsImplResult *out)
Definition ops_chain.h:131
Copyright (C) 2025 Niklas Haas.
Definition ops_chain.h:154
Definition uops.h:264
SwsPixel scalar
Definition uops.h:275
union SwsUOp::@242237116251216327057105100216205033300341206345 data
SwsPixelType type
Definition uops.h:266
SwsPixel vec4[4]
Definition uops.h:276
#define av_free(p)
#define av_mallocz(s)
#define av_log(a,...)
static FILE * out
Definition movenc.c:55
static AVFormatContext * ctx
Definition movenc.c:49
static const uint8_t *const tables[]
Private data for each kernel.
Definition ops_chain.h:45
float f32
Definition uops.h:84
uint32_t u32
Definition uops.h:83
uint8_t u8
Definition uops.h:81
uint16_t u16
Definition uops.h:82
void ff_sws_uop_name(const SwsUOp *op, char buf[SWS_UOP_NAME_MAX])
Definition uops.c:81
int ff_sws_uop_cmp(const SwsUOp *a, const SwsUOp *b)
Copyright (C) 2026 Niklas Haas.
Definition uops.c:31
@ SWS_PIXEL_F32
Definition uops.h:44
@ SWS_PIXEL_U32
Definition uops.h:43
@ SWS_PIXEL_U16
Definition uops.h:42
@ SWS_PIXEL_U8
Definition uops.h:41
static double limit(double x)