Commit c744f68541 for ffmpeg
commit c744f685410dcaf6810154cbb18a286ed9b27d9a
Author: Niklas Haas <git@haasn.dev>
Date: Tue Nov 3 16:59:46 2026 +0100
swscale/ops_chain: track references instead of arbitrary free callbacks
We don't really need this level of generality.
Signed-off-by: Niklas Haas <git@haasn.dev>
diff --git a/libswscale/aarch64/ops.c b/libswscale/aarch64/ops.c
index ec11d0d871..d0412909ad 100644
--- a/libswscale/aarch64/ops.c
+++ b/libswscale/aarch64/ops.c
@@ -98,17 +98,14 @@ static int aarch64_setup_linear(const SwsAArch64OpImplParams *p,
}
}
- res->priv.ptr = coeffs;
- res->free = ff_op_priv_unref;
-
+ res->ref = res->priv.ptr = coeffs;
return 0;
}
/*********************************************************************/
static int aarch64_setup_dither(const SwsUOp *uop, SwsImplResult *res)
{
- res->priv.ptr = av_refstruct_ref(uop->data.ptr);
- res->free = ff_op_priv_unref;
+ res->ref = res->priv.ptr = av_refstruct_ref(uop->data.ptr);
return 0;
}
@@ -186,7 +183,8 @@ static int compile_uops_aarch64(SwsContext *ctx, const SwsUOpList *uops,
ret = aarch64_setup(&uops->ops[i], ¶ms, &res);
if (ret < 0)
goto error;
- ret = ff_sws_op_chain_append(chain, func, res.free, &res.priv);
+ ret = ff_sws_op_chain_append(chain, func, res.ref, &res.priv);
+ av_refstruct_unref(&res.ref);
if (ret < 0)
goto error;
}
diff --git a/libswscale/ops_chain.c b/libswscale/ops_chain.c
index ff48ede4a2..9eb4b242dc 100644
--- a/libswscale/ops_chain.c
+++ b/libswscale/ops_chain.c
@@ -20,6 +20,7 @@
#include "libavutil/avassert.h"
#include "libavutil/mem.h"
+#include "libavutil/refstruct.h"
#include "ops_chain.h"
@@ -34,26 +35,27 @@ void ff_sws_op_chain_free_cb(void *ptr)
return;
SwsOpChain *chain = ptr;
- for (int i = 0; i < chain->num_impl + 1; i++) {
- if (chain->free[i])
- chain->free[i](&chain->impl[i].priv);
- }
+ for (int i = 0; i < chain->num_ref; i++)
+ av_refstruct_unref(&chain->ref[i]);
av_free(chain);
}
-int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func,
- void (*free)(SwsOpPriv *), const SwsOpPriv *priv)
+int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func, const void *ref,
+ const SwsOpPriv *priv)
{
const int idx = chain->num_impl;
if (idx == SWS_MAX_OPS)
return AVERROR(EINVAL);
+ if (ref && chain->num_ref >= FF_ARRAY_ELEMS(chain->ref))
+ return AVERROR(EINVAL);
av_assert1(func);
chain->impl[idx].cont = func;
chain->impl[idx + 1].priv = *priv;
- chain->free[idx + 1] = free;
chain->num_impl++;
+ if (ref)
+ chain->ref[chain->num_ref++] = av_refstruct_ref_c(ref);
return 0;
}
@@ -120,12 +122,10 @@ int ff_sws_uop_lookup(SwsContext *ctx, const SwsUOpTable *const tables[],
}
ret = ff_sws_op_chain_append(chain, res.func ? res.func : match->func,
- res.free, &res.priv);
- if (ret < 0) {
- if (res.free)
- res.free(&res.priv);
+ res.ref, &res.priv);
+ av_refstruct_unref(&res.ref);
+ if (ret < 0)
return ret;
- }
for (int i = 0; i < 4; i++) {
chain->over_read[i] = FFMAX(chain->over_read[i], res.over_read[i]);
diff --git a/libswscale/ops_chain.h b/libswscale/ops_chain.h
index 6fd9a57a94..01c96bbd43 100644
--- a/libswscale/ops_chain.h
+++ b/libswscale/ops_chain.h
@@ -85,11 +85,14 @@ static_assert(offsetof(SwsOpImpl, priv) == 16, "SwsOpImpl layout mismatch");
typedef struct SwsOpChain {
#define SWS_MAX_OPS 16
SwsOpImpl impl[SWS_MAX_OPS + 1]; /* reserve extra space for the entrypoint */
- void (*free[SWS_MAX_OPS + 1])(SwsOpPriv *);
int num_impl;
int cpu_flags; /* set of all used CPU flags */
int over_read[4]; /* chain over-reads input by this many bytes */
int over_write[4]; /* chain over-writes output by this many bytes */
+
+ /* Extra references owned by each kernel */
+ const void *ref[16];
+ int num_ref;
} SwsOpChain;
SwsOpChain *ff_sws_op_chain_alloc(void);
@@ -100,8 +103,8 @@ static inline void ff_sws_op_chain_free(SwsOpChain *chain)
}
/* Returns 0 on success, or a negative error code. */
-int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func,
- void (*free)(SwsOpPriv *), const SwsOpPriv *priv);
+int ff_sws_op_chain_append(SwsOpChain *chain, SwsFuncPtr func, const void *ref,
+ const SwsOpPriv *priv);
/**
* Attach a SwsOpChain and all metadata to a SwsCompiledOp (as out->priv).
@@ -120,9 +123,9 @@ typedef struct SwsImplParams {
typedef struct SwsImplResult {
SwsFuncPtr func; /* overrides `SwsUOpEntry.func` if non-NULL */
SwsOpPriv priv; /* private data for this implementation instance */
- void (*free)(SwsOpPriv *priv); /* free function for `priv` */
int over_read[4]; /* implementation over-reads input by this many bytes */
int over_write[4]; /* implementation over-writes output by this many bytes */
+ const void *ref; /* external data backing `priv`, ownership passes to caller */
} SwsImplResult;
typedef struct SwsUOpEntry {
diff --git a/libswscale/uops_tmpl.c b/libswscale/uops_tmpl.c
index 0ba058c8da..80c6391f5d 100644
--- a/libswscale/uops_tmpl.c
+++ b/libswscale/uops_tmpl.c
@@ -262,9 +262,8 @@ DECL_SETUP(setup_filter_v, params, out)
for (int i = 0; i < filter->num_weights; i++)
weights[i] = (float) filter->weights[i] / SWS_FILTER_SCALE;
- out->priv.ptr = weights;
+ out->ref = out->priv.ptr = weights;
out->priv.i32[2] = filter->filter_size;
- out->free = ff_op_priv_unref;
return 0;
}
@@ -317,9 +316,8 @@ DECL_SETUP(setup_filter_h, params, out)
static_assert(SWS_FILTER_PAD_ROWS >= SWS_BLOCK_SIZE,
"filter weights contain sufficient padding for block over-read");
- out->priv.ptr = av_refstruct_ref(filter->weights);
+ out->ref = out->priv.ptr = av_refstruct_ref(filter->weights);
out->priv.i32[2] = filter->filter_size;
- out->free = ff_op_priv_unref;
return 0;
}
@@ -726,8 +724,7 @@ DECL_SETUP(setup_dither, params, out)
const int size = 1 << dither->size_log2;
if (size >= SWS_BLOCK_SIZE) {
/* No extra padding needed */
- out->priv.ptr = av_refstruct_ref(uop->data.ptr);
- out->free = ff_op_priv_unref;
+ out->ref = out->priv.ptr = av_refstruct_ref(uop->data.ptr);
return 0;
}
@@ -736,8 +733,7 @@ DECL_SETUP(setup_dither, params, out)
pixel_t *matrix = ff_refstruct_calloc(height, sizeof(pixel_t) * stride);
if (!matrix)
return AVERROR(ENOMEM);
- out->priv.ptr = matrix;
- out->free = ff_op_priv_unref;
+ out->ref = out->priv.ptr = matrix;
/* Pad to multiple of block size. We don't need extra padding for the
* height because ff_sws_dither_height() already includes any padding
@@ -805,11 +801,10 @@ DECL_SETUP(setup_linear, params, out)
c.k[i] = uop->data.mat4x5[i][4].px;
}
- out->priv.ptr = av_refstruct_allocz(sizeof(c));
+ out->ref = out->priv.ptr = av_refstruct_allocz(sizeof(c));
if (!out->priv.ptr)
return AVERROR(ENOMEM);
memcpy(out->priv.ptr, &c, sizeof(c));
- out->free = ff_op_priv_unref;
return 0;
}
@@ -861,8 +856,7 @@ SWS_FOR_STRUCT(PX, LINEAR, DECL_ENTRY, .setup = fn(setup_linear) )
DECL_SETUP(setup_lut3d, params, out)
{
const SwsLut3D *lut = params->uop->data.lut3d;
- out->priv.ptr = (void *) av_refstruct_ref_c(lut);
- out->free = ff_op_priv_unref;
+ out->ref = out->priv.ptr = (void *) av_refstruct_ref_c(lut);
return 0;
}
diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c
index 719d19e65b..3c6e783bd6 100644
--- a/libswscale/x86/ops.c
+++ b/libswscale/x86/ops.c
@@ -57,9 +57,8 @@ static int setup_filter_v(const SwsImplParams *params, SwsImplResult *out)
for (int i = 0; i < filter->num_weights; i++)
weights[i] = (float) filter->weights[i] / SWS_FILTER_SCALE;
- out->priv.ptr = weights;
+ out->ref = out->priv.ptr = weights;
out->priv.uptr[1] = filter->filter_size;
- out->free = ff_op_priv_unref;
return 0;
}
@@ -150,9 +149,8 @@ static int setup_filter_h(const SwsImplParams *params, SwsImplResult *out)
}
}
- out->priv.ptr = weights.ptr;
+ out->ref = out->priv.ptr = weights.ptr;
out->priv.uptr[1] = aligned_size;
- out->free = ff_op_priv_unref;
for (int i = 0; i < 4; i++) {
if (uop->mask & SWS_COMP(i))
@@ -237,9 +235,8 @@ static int setup_filter_h_4x4(const SwsImplParams *params, SwsImplResult *out)
}
}
- out->priv.ptr = weights.ptr;
+ out->ref = out->priv.ptr = weights.ptr;
out->priv.uptr[1] = aligned_size * sizeof_weights;
- out->free = ff_op_priv_unref;
for (int i = 0; i < 4; i++) {
if (uop->mask & SWS_COMP(i))
@@ -272,8 +269,7 @@ static int setup_clear(const SwsImplParams *params, SwsImplResult *out)
static int setup_dither(const SwsImplParams *params, SwsImplResult *out)
{
- out->priv.ptr = av_refstruct_ref(params->uop->data.ptr);
- out->free = ff_op_priv_unref;
+ out->ref = out->priv.ptr = av_refstruct_ref(params->uop->data.ptr);
return 0;
}
@@ -298,19 +294,17 @@ static int setup_linear(const SwsImplParams *params, SwsImplResult *out)
{
const SwsUOp *uop = params->uop;
if (uop->type == SWS_PIXEL_F32) {
- out->priv.ptr = av_refstruct_allocz(sizeof(uop->data.mat4x5));
+ out->ref = out->priv.ptr = av_refstruct_allocz(sizeof(uop->data.mat4x5));
if (!out->priv.ptr)
return AVERROR(ENOMEM);
memcpy(out->priv.ptr, uop->data.mat4x5, sizeof(uop->data.mat4x5));
- out->free = ff_op_priv_unref;
return 0;
}
uint8_t *mat = av_refstruct_allocz(4 * 5 * 16); /* one lane per component */
if (!mat)
return AVERROR(ENOMEM);
- out->priv.ptr = mat;
- out->free = ff_op_priv_unref;
+ out->ref = out->priv.ptr = mat;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {