[FFmpeg-devel] [PATCH 08/17] swscale/ops_internal: add internal ops backend API
Niklas Haas
ffmpeg at haasn.xyz
Sun May 18 17:59:44 EEST 2025
From: Niklas Haas <git at haasn.dev>
This adds an internal API for ops backends, which are responsible for
compiling op lists into executable functions.
---
libswscale/ops.c | 62 ++++++++++++++++++++++
libswscale/ops_internal.h | 108 ++++++++++++++++++++++++++++++++++++++
2 files changed, 170 insertions(+)
create mode 100644 libswscale/ops_internal.h
diff --git a/libswscale/ops.c b/libswscale/ops.c
index 79b32ab8fb..734b874ba4 100644
--- a/libswscale/ops.c
+++ b/libswscale/ops.c
@@ -25,9 +25,22 @@
#include "libavutil/refstruct.h"
#include "ops.h"
+#include "ops_internal.h"
+
+const SwsOpBackend * const ff_sws_op_backends[] = {
+ NULL
+};
+
+const int ff_sws_num_op_backends = FF_ARRAY_ELEMS(ff_sws_op_backends) - 1;
#define Q(N) ((AVRational) { N, 1 })
+#define RET(x) \
+ do { \
+ if ((ret = (x)) < 0) \
+ return ret; \
+ } while (0)
+
const char *ff_sws_pixel_type_name(SwsPixelType type)
{
switch (type) {
@@ -528,3 +541,52 @@ void ff_sws_op_list_print(void *log, int lev, const SwsOpList *ops)
av_log(log, lev, " (X = unused, + = exact, 0 = zero)\n");
}
+
+int ff_sws_ops_compile_backend(SwsContext *ctx, const SwsOpBackend *backend,
+ const SwsOpList *ops, SwsCompiledOp *out)
+{
+ SwsOpList *copy, rest;
+ int ret = 0;
+
+ copy = ff_sws_op_list_duplicate(ops);
+ if (!copy)
+ return AVERROR(ENOMEM);
+
+ /* Ensure these are always set during compilation */
+ ff_sws_op_list_update_comps(copy);
+
+ /* Make an on-stack copy of `ops` to ensure we can still properly clean up
+ * the copy afterwards */
+ rest = *copy;
+
+ ret = backend->compile(ctx, &rest, out);
+ if (ret == AVERROR(ENOTSUP)) {
+ av_log(ctx, AV_LOG_DEBUG, "Backend '%s' does not support operations:\n", backend->name);
+ ff_sws_op_list_print(ctx, AV_LOG_DEBUG, &rest);
+ } else if (ret < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Failed to compile operations: %s\n", av_err2str(ret));
+ ff_sws_op_list_print(ctx, AV_LOG_ERROR, &rest);
+ }
+
+ ff_sws_op_list_free(©);
+ return ret;
+}
+
+int ff_sws_ops_compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out)
+{
+ for (int n = 0; ff_sws_op_backends[n]; n++) {
+ const SwsOpBackend *backend = ff_sws_op_backends[n];
+ if (ff_sws_ops_compile_backend(ctx, backend, ops, out) < 0)
+ continue;
+
+ av_log(ctx, AV_LOG_VERBOSE, "Compiled using backend '%s': "
+ "block size = %d, over-read = %d, over-write = %d, cpu flags = 0x%x\n",
+ backend->name, out->block_size, out->over_read, out->over_write,
+ out->cpu_flags);
+ return 0;
+ }
+
+ av_log(ctx, AV_LOG_WARNING, "No backend found for operations:\n");
+ ff_sws_op_list_print(ctx, AV_LOG_WARNING, ops);
+ return AVERROR(ENOTSUP);
+}
diff --git a/libswscale/ops_internal.h b/libswscale/ops_internal.h
new file mode 100644
index 0000000000..9fd866430b
--- /dev/null
+++ b/libswscale/ops_internal.h
@@ -0,0 +1,108 @@
+/**
+ * Copyright (C) 2025 Niklas Haas
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SWSCALE_OPS_INTERNAL_H
+#define SWSCALE_OPS_INTERNAL_H
+
+#include "libavutil/mem_internal.h"
+
+#include "ops.h"
+
+/**
+ * Global execution context for all compiled functions.
+ *
+ * Note: This struct is hard-coded in assembly, so do not change the layout
+ * without updating the corresponding assembly definitions.
+ */
+typedef struct SwsOpExec {
+ /* The data pointers point to the first pixel to process */
+ DECLARE_ALIGNED_32(const uint8_t, *in[4]);
+ DECLARE_ALIGNED_32(uint8_t, *out[4]);
+
+ /* Separation between lines in bytes */
+ DECLARE_ALIGNED_32(ptrdiff_t, in_stride[4]);
+ DECLARE_ALIGNED_32(ptrdiff_t, out_stride[4]);
+
+ /* Extra metadata, may or may not be useful */
+ int32_t width, height; /* Overall image dimensions */
+ int32_t slice_y, slice_h; /* Start and height of current slice */
+ int32_t pixel_bits_in; /* Bits per input pixel */
+ int32_t pixel_bits_out; /* Bits per output pixel */
+} SwsOpExec;
+
+static_assert(sizeof(SwsOpExec) == 16 * sizeof(void *) + 8 * sizeof(int32_t),
+ "SwsOpExec layout mismatch");
+
+/**
+ * Process a given range of pixel blocks.
+ *
+ * Note: `bx_start` and `bx_end` are in units of `SwsCompiledOp.block_size`.
+ */
+typedef void (*SwsOpFunc)(const SwsOpExec *exec, const void *priv,
+ int bx_start, int y_start, int bx_end, int y_end);
+
+#define SWS_DECL_FUNC(NAME) \
+ void NAME(const SwsOpExec *, const void *, int, int, int, int)
+
+typedef struct SwsCompiledOp {
+ SwsOpFunc func;
+
+ int block_size; /* number of pixels processed per iteration */
+ int over_read; /* implementation over-reads input by this many bytes */
+ int over_write; /* implementation over-writes output by this many bytes */
+ int cpu_flags; /* active set of CPU flags (informative) */
+
+ /* Arbitrary private data */
+ void *priv;
+ void (*free)(void *priv);
+} SwsCompiledOp;
+
+typedef struct SwsOpBackend {
+ const char *name; /* Descriptive name for this backend */
+
+ /**
+ * Compile an operation list to an implementation chain. May modify `ops`
+ * freely; the original list will be freed automatically by the caller.
+ *
+ * Returns 0 or a negative error code.
+ */
+ int (*compile)(SwsContext *ctx, SwsOpList *ops, SwsCompiledOp *out);
+} SwsOpBackend;
+
+/* List of all backends, terminated by NULL */
+extern const SwsOpBackend *const ff_sws_op_backends[];
+extern const int ff_sws_num_op_backends; /* excludes terminating NULL */
+
+/**
+ * Attempt to compile a list of operations using a specific backend.
+ *
+ * Returns 0 on success, or a negative error code on failure.
+ */
+int ff_sws_ops_compile_backend(SwsContext *ctx, const SwsOpBackend *backend,
+ const SwsOpList *ops, SwsCompiledOp *out);
+
+/**
+ * Compile a list of operations using the best available backend.
+ *
+ * Returns 0 on success, or a negative error code on failure.
+ */
+int ff_sws_ops_compile(SwsContext *ctx, const SwsOpList *ops, SwsCompiledOp *out);
+
+#endif
--
2.49.0
More information about the ffmpeg-devel
mailing list