ops.h 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /**
  2. * Copyright (C) 2025 Niklas Haas
  3. *
  4. * This file is part of FFmpeg.
  5. *
  6. * FFmpeg is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * FFmpeg is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with FFmpeg; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  19. */
  20. #ifndef SWSCALE_OPS_H
  21. #define SWSCALE_OPS_H
  22. #include <assert.h>
  23. #include <stdbool.h>
  24. #include <stdalign.h>
  25. #include "graph.h"
  26. typedef enum SwsPixelType {
  27. SWS_PIXEL_NONE = 0,
  28. SWS_PIXEL_U8,
  29. SWS_PIXEL_U16,
  30. SWS_PIXEL_U32,
  31. SWS_PIXEL_F32,
  32. SWS_PIXEL_TYPE_NB
  33. } SwsPixelType;
  34. const char *ff_sws_pixel_type_name(SwsPixelType type);
  35. int ff_sws_pixel_type_size(SwsPixelType type) av_const;
  36. bool ff_sws_pixel_type_is_int(SwsPixelType type) av_const;
  37. typedef enum SwsOpType {
  38. SWS_OP_INVALID = 0,
  39. /* Input/output handling */
  40. SWS_OP_READ, /* gather raw pixels from planes */
  41. SWS_OP_WRITE, /* write raw pixels to planes */
  42. SWS_OP_SWAP_BYTES, /* swap byte order (for differing endianness) */
  43. SWS_OP_UNPACK, /* split tightly packed data into components */
  44. SWS_OP_PACK, /* compress components into tightly packed data */
  45. /* Pixel manipulation */
  46. SWS_OP_CLEAR, /* clear pixel values */
  47. SWS_OP_LSHIFT, /* logical left shift of raw pixel values by (u8) */
  48. SWS_OP_RSHIFT, /* right shift of raw pixel values by (u8) */
  49. SWS_OP_SWIZZLE, /* rearrange channel order, or duplicate channels */
  50. SWS_OP_CONVERT, /* convert (cast) between formats */
  51. SWS_OP_DITHER, /* add dithering noise */
  52. /* Arithmetic operations */
  53. SWS_OP_LINEAR, /* generalized linear affine transform */
  54. SWS_OP_SCALE, /* multiplication by scalar (q) */
  55. SWS_OP_MIN, /* numeric minimum (q4) */
  56. SWS_OP_MAX, /* numeric maximum (q4) */
  57. SWS_OP_TYPE_NB,
  58. } SwsOpType;
  59. enum SwsCompFlags {
  60. SWS_COMP_GARBAGE = 1 << 0, /* contents are undefined / garbage data */
  61. SWS_COMP_EXACT = 1 << 1, /* value is an in-range, exact, integer */
  62. SWS_COMP_ZERO = 1 << 2, /* known to be a constant zero */
  63. };
  64. typedef union SwsConst {
  65. /* Generic constant value */
  66. AVRational q4[4];
  67. AVRational q;
  68. unsigned u;
  69. } SwsConst;
  70. static_assert(sizeof(SwsConst) == sizeof(AVRational) * 4,
  71. "First field of SwsConst should span the entire union");
  72. typedef struct SwsComps {
  73. unsigned flags[4]; /* knowledge about (output) component contents */
  74. bool unused[4]; /* which input components are definitely unused */
  75. /* Keeps track of the known possible value range, or {0, 0} for undefined
  76. * or (unknown range) floating point inputs */
  77. AVRational min[4], max[4];
  78. } SwsComps;
  79. typedef struct SwsReadWriteOp {
  80. uint8_t elems; /* number of elements (of type `op.type`) to read/write */
  81. uint8_t frac; /* fractional pixel step factor (log2) */
  82. bool packed; /* read multiple elements from a single plane */
  83. /** Examples:
  84. * rgba = 4x u8 packed
  85. * yuv444p = 3x u8
  86. * rgb565 = 1x u16 <- use SWS_OP_UNPACK to unpack
  87. * monow = 1x u8 (frac 3)
  88. * rgb4 = 1x u8 (frac 1)
  89. */
  90. } SwsReadWriteOp;
  91. typedef struct SwsPackOp {
  92. uint8_t pattern[4]; /* bit depth pattern, from MSB to LSB */
  93. } SwsPackOp;
  94. typedef struct SwsSwizzleOp {
  95. /**
  96. * Input component for each output component:
  97. * Out[x] := In[swizzle.in[x]]
  98. */
  99. union {
  100. uint32_t mask;
  101. uint8_t in[4];
  102. struct { uint8_t x, y, z, w; };
  103. };
  104. } SwsSwizzleOp;
  105. #define SWS_SWIZZLE(X,Y,Z,W) ((SwsSwizzleOp) { .in = {X, Y, Z, W} })
  106. typedef struct SwsConvertOp {
  107. SwsPixelType to; /* type of pixel to convert to */
  108. bool expand; /* if true, integers are expanded to the full range */
  109. } SwsConvertOp;
  110. typedef struct SwsDitherOp {
  111. AVRational *matrix; /* tightly packed dither matrix (refstruct) */
  112. int size_log2; /* size (in bits) of the dither matrix */
  113. } SwsDitherOp;
  114. typedef struct SwsLinearOp {
  115. /**
  116. * Generalized 5x5 affine transformation:
  117. * [ Out.x ] = [ A B C D E ]
  118. * [ Out.y ] = [ F G H I J ] * [ x y z w 1 ]
  119. * [ Out.z ] = [ K L M N O ]
  120. * [ Out.w ] = [ P Q R S T ]
  121. *
  122. * The mask keeps track of which components differ from an identity matrix.
  123. * There may be more efficient implementations of particular subsets, for
  124. * example the common subset of {A, E, G, J, M, O} can be implemented with
  125. * just three fused multiply-add operations.
  126. */
  127. AVRational m[4][5];
  128. uint32_t mask; /* m[i][j] <-> 1 << (5 * i + j) */
  129. } SwsLinearOp;
  130. #define SWS_MASK(I, J) (1 << (5 * (I) + (J)))
  131. #define SWS_MASK_OFF(I) SWS_MASK(I, 4)
  132. #define SWS_MASK_ROW(I) (0x1F << (5 * (I)))
  133. #define SWS_MASK_COL(J) (0x8421 << J)
  134. enum {
  135. SWS_MASK_ALL = (1 << 20) - 1,
  136. SWS_MASK_LUMA = SWS_MASK(0, 0) | SWS_MASK_OFF(0),
  137. SWS_MASK_ALPHA = SWS_MASK(3, 3) | SWS_MASK_OFF(3),
  138. SWS_MASK_DIAG3 = SWS_MASK(0, 0) | SWS_MASK(1, 1) | SWS_MASK(2, 2),
  139. SWS_MASK_OFF3 = SWS_MASK_OFF(0) | SWS_MASK_OFF(1) | SWS_MASK_OFF(2),
  140. SWS_MASK_MAT3 = SWS_MASK(0, 0) | SWS_MASK(0, 1) | SWS_MASK(0, 2) |
  141. SWS_MASK(1, 0) | SWS_MASK(1, 1) | SWS_MASK(1, 2) |
  142. SWS_MASK(2, 0) | SWS_MASK(2, 1) | SWS_MASK(2, 2),
  143. SWS_MASK_DIAG4 = SWS_MASK_DIAG3 | SWS_MASK(3, 3),
  144. SWS_MASK_OFF4 = SWS_MASK_OFF3 | SWS_MASK_OFF(3),
  145. SWS_MASK_MAT4 = SWS_MASK_ALL & ~SWS_MASK_OFF4,
  146. };
  147. /* Helper function to compute the correct mask */
  148. uint32_t ff_sws_linear_mask(SwsLinearOp);
  149. typedef struct SwsOp {
  150. SwsOpType op; /* operation to perform */
  151. SwsPixelType type; /* pixel type to operate on */
  152. union {
  153. SwsLinearOp lin;
  154. SwsReadWriteOp rw;
  155. SwsPackOp pack;
  156. SwsSwizzleOp swizzle;
  157. SwsConvertOp convert;
  158. SwsDitherOp dither;
  159. SwsConst c;
  160. };
  161. /* For use internal use inside ff_sws_*() functions */
  162. SwsComps comps;
  163. } SwsOp;
  164. /**
  165. * Frees any allocations associated with an SwsOp and sets it to {0}.
  166. */
  167. void ff_sws_op_uninit(SwsOp *op);
  168. /**
  169. * Apply an operation to an AVRational. No-op for read/write operations.
  170. */
  171. void ff_sws_apply_op_q(const SwsOp *op, AVRational x[4]);
  172. /**
  173. * Helper struct for representing a list of operations.
  174. */
  175. typedef struct SwsOpList {
  176. SwsOp *ops;
  177. int num_ops;
  178. /* Purely informative metadata associated with this operation list */
  179. SwsFormat src, dst;
  180. } SwsOpList;
  181. SwsOpList *ff_sws_op_list_alloc(void);
  182. void ff_sws_op_list_free(SwsOpList **ops);
  183. /**
  184. * Returns a duplicate of `ops`, or NULL on OOM.
  185. */
  186. SwsOpList *ff_sws_op_list_duplicate(const SwsOpList *ops);
  187. /**
  188. * Returns the size of the largest pixel type used in `ops`.
  189. */
  190. int ff_sws_op_list_max_size(const SwsOpList *ops);
  191. /**
  192. * These will take over ownership of `op` and set it to {0}, even on failure.
  193. */
  194. int ff_sws_op_list_append(SwsOpList *ops, SwsOp *op);
  195. int ff_sws_op_list_insert_at(SwsOpList *ops, int index, SwsOp *op);
  196. void ff_sws_op_list_remove_at(SwsOpList *ops, int index, int count);
  197. /**
  198. * Print out the contents of an operation list.
  199. */
  200. void ff_sws_op_list_print(void *log_ctx, int log_level, const SwsOpList *ops);
  201. /**
  202. * Infer + propagate known information about components. Called automatically
  203. * when needed by the optimizer and compiler.
  204. */
  205. void ff_sws_op_list_update_comps(SwsOpList *ops);
  206. /**
  207. * Fuse compatible and eliminate redundant operations, as well as replacing
  208. * some operations with more efficient alternatives.
  209. */
  210. int ff_sws_op_list_optimize(SwsOpList *ops);
  211. enum SwsOpCompileFlags {
  212. /* Automatically optimize the operations when compiling */
  213. SWS_OP_FLAG_OPTIMIZE = 1 << 0,
  214. };
  215. /**
  216. * Resolves an operation list to a graph pass. The first and last operations
  217. * must be a read/write respectively. `flags` is a list of SwsOpCompileFlags.
  218. *
  219. * Note: `ops` may be modified by this function.
  220. */
  221. int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, SwsFormat dst,
  222. SwsPass *input, SwsPass **output);
  223. #endif