swscale/ops_internal: add internal ops backend API
This adds an internal API for ops backends, which are responsible for compiling op lists into executable functions.
This commit is contained in:
@@ -27,6 +27,16 @@
|
||||
#include "ops.h"
|
||||
#include "ops_internal.h"
|
||||
|
||||
const SwsOpBackend * const ff_sws_op_backends[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
#define RET(x) \
|
||||
do { \
|
||||
if ((ret = (x)) < 0) \
|
||||
return ret; \
|
||||
} while (0)
|
||||
|
||||
const char *ff_sws_pixel_type_name(SwsPixelType type)
|
||||
{
|
||||
switch (type) {
|
||||
@@ -508,3 +518,57 @@ 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;
|
||||
SwsCompiledOp compiled = {0};
|
||||
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, &compiled);
|
||||
if (ret < 0) {
|
||||
int msg_lev = ret == AVERROR(ENOTSUP) ? AV_LOG_TRACE : AV_LOG_ERROR;
|
||||
av_log(ctx, msg_lev, "Backend '%s' failed to compile operations: %s\n",
|
||||
backend->name, av_err2str(ret));
|
||||
if (rest.num_ops != ops->num_ops) {
|
||||
av_log(ctx, msg_lev, "Uncompiled remainder:\n");
|
||||
ff_sws_op_list_print(ctx, msg_lev, &rest);
|
||||
}
|
||||
} else {
|
||||
*out = compiled;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#ifndef SWSCALE_OPS_INTERNAL_H
|
||||
#define SWSCALE_OPS_INTERNAL_H
|
||||
|
||||
#include "libavutil/mem_internal.h"
|
||||
|
||||
#include "ops.h"
|
||||
|
||||
#define Q(N) ((AVRational) { N, 1 })
|
||||
@@ -45,4 +47,83 @@ static inline void ff_sws_pack_op_decode(const SwsOp *op, uint64_t mask[4], int
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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[];
|
||||
|
||||
/**
|
||||
* 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 /* SWSCALE_OPS_INTERNAL_H */
|
||||
|
||||
Reference in New Issue
Block a user