Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Niklas Haas <ffmpeg@haasn.xyz>
To: ffmpeg-devel@ffmpeg.org
Cc: Niklas Haas <git@haasn.dev>
Subject: [FFmpeg-devel] [PATCH v2 08/17] swscale/ops_internal: add internal ops backend API
Date: Wed, 21 May 2025 14:43:54 +0200
Message-ID: <20250521124824.49657-9-ffmpeg@haasn.xyz> (raw)
In-Reply-To: <20250521124824.49657-1-ffmpeg@haasn.xyz>

From: Niklas Haas <git@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 004686147d..8491bd9cad 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) {
@@ -520,3 +533,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(&copy);
+    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

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

  parent reply	other threads:[~2025-05-21 12:51 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-21 12:43 [FFmpeg-devel] [PATCH v2 00/17] swscale: new ops framework Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 01/17] swscale/format: rename legacy format conversion table Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 02/17] swscale/format: add ff_fmt_clear() Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 03/17] tests/checkasm: increase number of runs in between measurements Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 04/17] tests/checkasm: generalize DEF_CHECKASM_CHECK_FUNC to floats Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 05/17] swscale: add SWS_UNSTABLE flag Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 06/17] swscale/ops: introduce new low level framework Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 07/17] swscale/optimizer: add high-level ops optimizer Niklas Haas
2025-05-21 12:43 ` Niklas Haas [this message]
2025-05-23 16:27   ` [FFmpeg-devel] [PATCH v2 08/17] swscale/ops_internal: add internal ops backend API Michael Niedermayer
2025-05-23 16:52     ` Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 09/17] swscale/ops: add dispatch layer Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 10/17] swscale/optimizer: add packed shuffle solver Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 11/17] swscale/ops_chain: add internal abstraction for kernel linking Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 12/17] swscale/ops_backend: add reference backend basend on C templates Niklas Haas
2025-05-21 12:43 ` [FFmpeg-devel] [PATCH v2 13/17] swscale/ops_memcpy: add 'memcpy' backend for plane->plane copies Niklas Haas
2025-05-21 12:44 ` [FFmpeg-devel] [PATCH v2 14/17] swscale/x86: add SIMD backend Niklas Haas
2025-05-21 14:11   ` Kieran Kunhya via ffmpeg-devel
2025-05-21 12:44 ` [FFmpeg-devel] [PATCH v2 15/17] tests/checkasm: add checkasm tests for swscale ops Niklas Haas
2025-05-21 12:44 ` [FFmpeg-devel] [PATCH v2 16/17] swscale/format: add new format decode/encode logic Niklas Haas
2025-05-21 12:44 ` [FFmpeg-devel] [PATCH v2 17/17] swscale/graph: allow experimental use of new format handler Niklas Haas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250521124824.49657-9-ffmpeg@haasn.xyz \
    --to=ffmpeg@haasn.xyz \
    --cc=ffmpeg-devel@ffmpeg.org \
    --cc=git@haasn.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git