| /* |
| * Copyright (C) 2024 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_GRAPH_H |
| #define SWSCALE_GRAPH_H |
| |
| #include <stdbool.h> |
| |
| #include "libavutil/slicethread.h" |
| #include "libavutil/buffer.h" |
| |
| #include "swscale.h" |
| #include "format.h" |
| #include "lut3d.h" |
| |
| static av_always_inline av_const int ff_fmt_vshift(enum AVPixelFormat fmt, int plane) |
| { |
| const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); |
| return (plane == 1 || plane == 2) ? desc->log2_chroma_h : 0; |
| } |
| |
| typedef struct SwsPass SwsPass; |
| typedef struct SwsGraph SwsGraph; |
| |
| /** |
| * Output `h` lines of filtered data. `out` and `in` point to the |
| * start of the image buffer for this pass. |
| */ |
| typedef void (*SwsPassFunc)(const SwsFrame *out, const SwsFrame *in, |
| int y, int h, const SwsPass *pass); |
| |
| /** |
| * Function to run from the main thread before processing any lines. |
| */ |
| typedef int (*SwsPassSetup)(const SwsFrame *out, const SwsFrame *in, |
| const SwsPass *pass); |
| |
| /** |
| * Represents an output buffer for a filter pass. During filter graph |
| * construction, these merely hold the metadata. Allocation of the underlying |
| * storage is deferred until after all filter passes are settled. |
| */ |
| typedef struct SwsPassBuffer { |
| SwsFrame frame; |
| |
| int width, height; /* dimensions of this buffer */ |
| AVFrame *avframe; /* backing storage for `frame` */ |
| |
| /* Optional allocation hints for optimal performance */ |
| int width_align; /* Align width to multiple of this */ |
| int width_pad; /* Extra padding pixels */ |
| |
| /** |
| * Map of planes which are directly copied from the pass input. These |
| * may be promoted from a memcpy to a refcopy. |
| * |
| * Each entry maps the output index to the corresponding input plane |
| * index, or -1 for no copythrough. |
| */ |
| int plane_copy[4]; |
| } SwsPassBuffer; |
| |
| /** |
| * Represents a single filter pass in the scaling graph. Each filter will |
| * read from some previous pass's output, and write to a buffer associated |
| * with the pass (or into the final output image). |
| */ |
| struct SwsPass { |
| const SwsGraph *graph; |
| |
| /** |
| * Filter main execution function. Called from multiple threads, with |
| * the granularity dictated by `slice_h`. Individual slices sent to `run` |
| * are always equal to (or smaller than, for the last slice) `slice_h`. |
| */ |
| SwsPassFunc run; |
| SwsBackend backend; /* backend this pass is using, or 0 */ |
| enum AVPixelFormat format; /* new pixel format */ |
| int lines; /* pass dispatch size */ |
| int slice_h; /* filter granularity */ |
| int num_slices; |
| |
| /** |
| * Filter input. This pass's output will be resolved to form this pass's. |
| * input. If NULL, the original input image is used. |
| */ |
| SwsPass *input; |
| |
| /** |
| * Filter output buffer. This struct is always allocated. |
| */ |
| SwsPassBuffer *output; /* refstruct */ |
| |
| /** |
| * Called once from the main thread before running the filter. Optional. |
| * Returns 0 or a negative error code. |
| */ |
| SwsPassSetup setup; |
| |
| /** |
| * Optional private state and associated free() function. |
| */ |
| void (*free)(void *priv); |
| void *priv; |
| }; |
| |
| /** |
| * Align `width` to the optimal size for `pass`. |
| */ |
| int ff_sws_pass_aligned_width(const SwsPass *pass, int width); |
| |
| /** |
| * Filter graph, which represents a 'baked' pixel format conversion. |
| */ |
| typedef struct SwsGraph { |
| SwsContext *ctx; |
| AVSliceThread *slicethread; |
| int num_threads; /* resolved at init() time */ |
| bool incomplete; /* set during init() if formats had to be inferred */ |
| bool noop; /* set during init() if the graph is a no-op */ |
| SwsBackend backend; /* backends this graph is using, set during init() */ |
| |
| AVBufferRef *hw_frames_ref; |
| |
| /** |
| * Map of planes which directly copied from the input. These may be |
| * promoted from a memcpy to a refcopy. This requires special handling |
| * by the caller. |
| * |
| * Each entry maps the output index to the corresponding input plane |
| * index, or -1 for no copythrough. |
| */ |
| int plane_copy[4]; |
| |
| /** Sorted sequence of filter passes to apply */ |
| SwsPass **passes; |
| int num_passes; |
| |
| /** |
| * Cached copy of the public options that were used to construct this |
| * SwsGraph. Used only to detect when the graph needs to be reinitialized. |
| */ |
| SwsContext opts_copy; |
| |
| /** |
| * Currently active format and processing parameters. |
| */ |
| SwsFormat src, dst; |
| |
| /** |
| * 3DLUT state used for gamut/tone mapping. (Optional) |
| */ |
| SwsLut3D *lut3d; /* refstruct */ |
| |
| /** |
| * Temporary execution state inside ff_sws_graph_run(); used to pass |
| * data to worker threads. |
| */ |
| struct { |
| const SwsPass *pass; /* current filter pass */ |
| const SwsFrame *input; /* current filter pass input/output */ |
| const SwsFrame *output; |
| } exec; |
| } SwsGraph; |
| |
| /** |
| * Allocate an empty SwsGraph. Returns NULL on failure. |
| */ |
| SwsGraph *ff_sws_graph_alloc(void); |
| |
| /** |
| * Initialize the filter graph for a given pair of formats. Returns 0 or a |
| * negative error. |
| */ |
| int ff_sws_graph_init(SwsGraph *graph, SwsContext *ctx, const SwsFormat *dst, |
| const SwsFormat *src); |
| |
| |
| /** |
| * Allocate and add a new pass to the filter graph. Takes over ownership of |
| * `priv`, even on failure. |
| * |
| * @param graph Filter graph to add the pass to. |
| * @param fmt Pixel format of the output image. |
| * @param w Width of the output image. |
| * @param h Height of the output image. |
| * @param input Previous pass to read from, or NULL for the input image. |
| * @param lines Override the number of lines processed for this pass. (Optional) |
| * @param align Minimum slice alignment for this pass, or 0 for no threading. |
| * @param run Filter function to run. |
| * @param setup Optional setup function to run from the main thread. |
| * @param priv Private state for the filter run function. |
| * @param free Function to free the private state. |
| * @param out_pass The newly added pass will be written here on success. |
| * @return 0 or a negative error code |
| */ |
| int ff_sws_graph_add_pass(SwsGraph *graph, enum AVPixelFormat fmt, |
| int width, int height, SwsPass *input, |
| int lines, int align, |
| SwsPassFunc run, SwsPassSetup setup, |
| void *priv, void (*free)(void *priv), |
| SwsPass **out_pass); |
| |
| /** |
| * Link the output buffers to a different pass, rather than allocating |
| * new image buffers. This allows reusing the same buffer for multiple passes, |
| * e.g. in the case of in-place passes or partial passes that modify different |
| * planes. |
| * |
| * Any existing buffer on `dst` will be ignored/unref'd. |
| **/ |
| void ff_sws_pass_link_output(SwsPass *dst, const SwsPass *src); |
| |
| /** |
| * Remove all passes added since the given index. |
| */ |
| void ff_sws_graph_rollback(SwsGraph *graph, int since_idx); |
| |
| /** |
| * Uninitialize any state associate with this filter graph and free it. |
| */ |
| void ff_sws_graph_free(SwsGraph **graph); |
| |
| /** |
| * Update dynamic per-frame HDR metadata without requiring a full reinit. |
| */ |
| void ff_sws_graph_update_metadata(SwsGraph *graph, const SwsColor *color); |
| |
| /** |
| * Wrapper around ff_sws_graph_init() that reuses the existing graph if the |
| * format is compatible. This will also update dynamic per-frame metadata. |
| * |
| * Must also be called after changing any of the fields in `ctx`, or else they |
| * will have no effect. |
| */ |
| int ff_sws_graph_reinit(SwsGraph *graph, SwsContext *ctx, const SwsFormat *dst, |
| const SwsFormat *src); |
| |
| /** |
| * Dispatch the filter graph on a single field of the given frames. Internally |
| * threaded. |
| */ |
| int ff_sws_graph_run(SwsGraph *graph, const AVFrame *dst, const AVFrame *src); |
| |
| #endif /* SWSCALE_GRAPH_H */ |