FFmpeg
ops_impl_conv.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2026 Ramiro Polla
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 
21 /**
22  * NOTE: This file is #include'd directly by both the NEON backend and
23  * the sws_ops_aarch64 tool.
24  */
25 
26 #include "libavutil/error.h"
27 #include "libavutil/rational.h"
28 #include "libswscale/ops.h"
29 
30 #include "ops_impl.h"
31 
33 {
34  switch (type) {
35  case SWS_PIXEL_U8: return AARCH64_PIXEL_U8;
36  case SWS_PIXEL_U16: return AARCH64_PIXEL_U16;
37  case SWS_PIXEL_U32: return AARCH64_PIXEL_U32;
38  case SWS_PIXEL_F32: return AARCH64_PIXEL_F32;
39  }
40  return 0;
41 }
42 
43 /**
44  * The column index order for SwsLinearOp.mask follows the affine transform
45  * order, where the offset is the last element. SwsAArch64LinearOpMask, on
46  * the other hand, follows execution order, where the offset is the first
47  * element.
48  */
49 static int linear_index_from_sws_op(int idx)
50 {
51  const int reorder_col[5] = { 1, 2, 3, 4, 0 };
52  return reorder_col[idx];
53 }
54 
55 /**
56  * Convert SwsOp to a SwsAArch64OpImplParams. Read the comments regarding
57  * SwsAArch64OpImplParams in ops_impl.h for more information.
58  */
59 static int convert_to_aarch64_impl(SwsContext *ctx, const SwsOpList *ops, int n,
60  int block_size, SwsAArch64OpImplParams *out)
61 {
62  const SwsOp *op = &ops->ops[n];
63 
64  out->block_size = block_size;
65 
66  /**
67  * Most SwsOp work on fields described by SWS_OP_NEEDED().
68  * The few that don't will override this field later.
69  */
70  out->mask = 0;
71  for (int i = 0; i < 4; i++) {
72  if (SWS_OP_NEEDED(op, i))
73  MASK_SET(out->mask, i, 1);
74  }
75 
76  out->type = sws_pixel_to_aarch64(op->type);
77 
78  /* Map SwsOpType to SwsAArch64OpType */
79  switch (op->op) {
80  case SWS_OP_READ:
81  if (op->rw.filter.op)
82  return AVERROR(ENOTSUP);
83  /**
84  * The different types of read operations have been split into
85  * their own SwsAArch64OpType to simplify the implementation.
86  */
87  if (op->rw.frac == 1)
89  else if (op->rw.frac == 3)
91  else if (op->rw.mode == SWS_RW_PACKED && op->rw.elems > 1)
93  else if (op->rw.mode == SWS_RW_PACKED || op->rw.mode == SWS_RW_PLANAR)
95  else
96  return AVERROR(ENOTSUP);
97  break;
98  case SWS_OP_WRITE:
99  if (op->rw.filter.op)
100  return AVERROR(ENOTSUP);
101  /**
102  * The different types of write operations have been split into
103  * their own SwsAArch64OpType to simplify the implementation.
104  */
105  if (op->rw.frac == 1)
107  else if (op->rw.frac == 3)
109  else if (op->rw.mode == SWS_RW_PACKED && op->rw.elems > 1)
111  else if (op->rw.mode == SWS_RW_PACKED || op->rw.mode == SWS_RW_PLANAR)
113  else
114  return AVERROR(ENOTSUP);
115  break;
117  case SWS_OP_SWIZZLE: out->op = AARCH64_SWS_OP_SWIZZLE; break;
118  case SWS_OP_UNPACK: out->op = AARCH64_SWS_OP_UNPACK; break;
119  case SWS_OP_PACK: out->op = AARCH64_SWS_OP_PACK; break;
120  case SWS_OP_LSHIFT: out->op = AARCH64_SWS_OP_LSHIFT; break;
121  case SWS_OP_RSHIFT: out->op = AARCH64_SWS_OP_RSHIFT; break;
122  case SWS_OP_CLEAR: out->op = AARCH64_SWS_OP_CLEAR; break;
123  case SWS_OP_CONVERT:
124  out->op = op->convert.expand ? AARCH64_SWS_OP_EXPAND : AARCH64_SWS_OP_CONVERT;
125  break;
126  case SWS_OP_MIN: out->op = AARCH64_SWS_OP_MIN; break;
127  case SWS_OP_MAX: out->op = AARCH64_SWS_OP_MAX; break;
128  case SWS_OP_SCALE: out->op = AARCH64_SWS_OP_SCALE; break;
129  case SWS_OP_LINEAR: out->op = AARCH64_SWS_OP_LINEAR; break;
130  case SWS_OP_DITHER: out->op = AARCH64_SWS_OP_DITHER; break;
131  case SWS_OP_FILTER_H:
132  case SWS_OP_FILTER_V:
133  return AVERROR(ENOTSUP);
134  }
135 
136  switch (out->op) {
145  switch (op->rw.elems) {
146  case 1: out->mask = 0x0001; break;
147  case 2: out->mask = 0x0011; break;
148  case 3: out->mask = 0x0111; break;
149  case 4: out->mask = 0x1111; break;
150  };
151  break;
153  /* Recompute mask taking identity swizzle into account */
154  out->mask = 0;
155  for (int i = 0; i < 4; i++) {
156  if (SWS_OP_NEEDED(op, i) && op->swizzle.in[i] != i) {
157  MASK_SET(out->mask, i, 1);
158  MASK_SET(out->swizzle, i, op->swizzle.in[i]);
159  } else {
160  MASK_SET(out->swizzle, i, 0xf);
161  }
162  }
163  /* The element size and type don't matter. */
164  out->block_size = block_size * ff_sws_pixel_type_size(op->type);
165  out->type = AARCH64_PIXEL_U8;
166  break;
168  MASK_SET(out->pack, 0, op->pack.pattern[0]);
169  MASK_SET(out->pack, 1, op->pack.pattern[1]);
170  MASK_SET(out->pack, 2, op->pack.pattern[2]);
171  MASK_SET(out->pack, 3, op->pack.pattern[3]);
172  break;
173  case AARCH64_SWS_OP_PACK:
174  out->mask = 0;
175  for (int i = 0; i < 4 && op->pack.pattern[i]; i++)
176  MASK_SET(out->mask, i, 1);
177  MASK_SET(out->pack, 0, op->pack.pattern[0]);
178  MASK_SET(out->pack, 1, op->pack.pattern[1]);
179  MASK_SET(out->pack, 2, op->pack.pattern[2]);
180  MASK_SET(out->pack, 3, op->pack.pattern[3]);
181  break;
184  out->shift = op->shift.amount;
185  break;
187  out->mask = 0;
188  MASK_SET(out->mask, 0, !!op->clear.value[0].den);
189  MASK_SET(out->mask, 1, !!op->clear.value[1].den);
190  MASK_SET(out->mask, 2, !!op->clear.value[2].den);
191  MASK_SET(out->mask, 3, !!op->clear.value[3].den);
192  break;
195  out->to_type = sws_pixel_to_aarch64(op->convert.to);
196  break;
198  /**
199  * The out->linear.mask field packs the 4x5 matrix from SwsLinearOp as
200  * 2 bits per element:
201  * 00: m[i][j] == 0
202  * 01: m[i][j] == 1
203  * 11: m[i][j] is any other coefficient
204  */
205  out->mask = 0;
206  for (int i = 0; i < 4; i++) {
207  /* Skip unused or identity rows */
208  if (!SWS_OP_NEEDED(op, i) || !(op->lin.mask & SWS_MASK_ROW(i)))
209  continue;
210  MASK_SET(out->mask, i, 1);
211  for (int j = 0; j < 5; j++) {
212  const AVRational k = op->lin.m[i][j];
213  int jj = linear_index_from_sws_op(j);
214  if (j < 4 && k.num == k.den)
215  LINEAR_MASK_SET(out->linear.mask, i, jj, LINEAR_MASK_1);
216  else if (k.num != 0)
217  LINEAR_MASK_SET(out->linear.mask, i, jj, LINEAR_MASK_X);
218  }
219  }
220  out->linear.fmla = !(ctx->flags & SWS_BITEXACT);
221  break;
223  out->mask = 0;
224  MASK_SET(out->mask, 0, op->dither.y_offset[0] >= 0);
225  MASK_SET(out->mask, 1, op->dither.y_offset[1] >= 0);
226  MASK_SET(out->mask, 2, op->dither.y_offset[2] >= 0);
227  MASK_SET(out->mask, 3, op->dither.y_offset[3] >= 0);
228  MASK_SET(out->dither.y_offset, 0, op->dither.y_offset[0]);
229  MASK_SET(out->dither.y_offset, 1, op->dither.y_offset[1]);
230  MASK_SET(out->dither.y_offset, 2, op->dither.y_offset[2]);
231  MASK_SET(out->dither.y_offset, 3, op->dither.y_offset[3]);
232  out->dither.size_log2 = op->dither.size_log2;
233  break;
234  }
235 
236  switch (out->op) {
247  /* Only the element size matters, not the type. */
248  if (out->type == AARCH64_PIXEL_F32)
249  out->type = AARCH64_PIXEL_U32;
250  break;
251  }
252 
253  return 0;
254 }
SWS_OP_READ
@ SWS_OP_READ
Definition: ops.h:38
AARCH64_SWS_OP_MIN
@ AARCH64_SWS_OP_MIN
Definition: ops_impl.h:57
SWS_OP_SWIZZLE
@ SWS_OP_SWIZZLE
Definition: ops.h:41
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
SWS_OP_LSHIFT
@ SWS_OP_LSHIFT
Definition: ops.h:46
SWS_OP_UNPACK
@ SWS_OP_UNPACK
Definition: ops.h:44
SWS_RW_PLANAR
@ SWS_RW_PLANAR
Note: 1-component reads are either SWS_RW_PLANAR or SWS_RW_PACKED, depending on the underlying interp...
Definition: ops.h:97
out
static FILE * out
Definition: movenc.c:55
SWS_OP_CLEAR
@ SWS_OP_CLEAR
Definition: ops.h:50
rational.h
ops_impl.h
ops.h
SWS_OP_DITHER
@ SWS_OP_DITHER
Definition: ops.h:58
SWS_BITEXACT
@ SWS_BITEXACT
Definition: swscale.h:180
AARCH64_SWS_OP_SWIZZLE
@ AARCH64_SWS_OP_SWIZZLE
Definition: ops_impl.h:49
ff_sws_pixel_type_size
int ff_sws_pixel_type_size(SwsPixelType type)
Definition: ops.c:77
AARCH64_SWS_OP_CLEAR
@ AARCH64_SWS_OP_CLEAR
Definition: ops_impl.h:54
SWS_MASK_ROW
#define SWS_MASK_ROW(I)
Definition: ops.h:201
AARCH64_SWS_OP_READ_NIBBLE
@ AARCH64_SWS_OP_READ_NIBBLE
Definition: ops_impl.h:41
AARCH64_SWS_OP_PACK
@ AARCH64_SWS_OP_PACK
Definition: ops_impl.h:51
AARCH64_SWS_OP_SWAP_BYTES
@ AARCH64_SWS_OP_SWAP_BYTES
Definition: ops_impl.h:48
AARCH64_SWS_OP_READ_BIT
@ AARCH64_SWS_OP_READ_BIT
Definition: ops_impl.h:40
AARCH64_SWS_OP_MAX
@ AARCH64_SWS_OP_MAX
Definition: ops_impl.h:58
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
AVRational::num
int num
Numerator.
Definition: rational.h:59
LINEAR_MASK_1
#define LINEAR_MASK_1
Definition: ops_impl.h:127
SWS_RW_PACKED
@ SWS_RW_PACKED
Definition: ops.h:98
SWS_OP_SCALE
@ SWS_OP_SCALE
Definition: ops.h:54
sws_pixel_to_aarch64
static uint8_t sws_pixel_to_aarch64(SwsPixelType type)
NOTE: This file is #include'd directly by both the NEON backend and the sws_ops_aarch64 tool.
Definition: ops_impl_conv.c:32
SWS_OP_NEEDED
#define SWS_OP_NEEDED(op, idx)
Definition: ops.h:255
AARCH64_SWS_OP_WRITE_NIBBLE
@ AARCH64_SWS_OP_WRITE_NIBBLE
Definition: ops_impl.h:45
AARCH64_SWS_OP_DITHER
@ AARCH64_SWS_OP_DITHER
Definition: ops_impl.h:61
AARCH64_SWS_OP_RSHIFT
@ AARCH64_SWS_OP_RSHIFT
Definition: ops_impl.h:53
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1465
AARCH64_SWS_OP_LINEAR
@ AARCH64_SWS_OP_LINEAR
Definition: ops_impl.h:60
op
static int op(uint8_t **dst, const uint8_t *dst_end, GetByteContext *gb, int pixel, int count, int *x, int width, int linesize)
Perform decode operation.
Definition: anm.c:76
SWS_OP_MIN
@ SWS_OP_MIN
Definition: ops.h:52
AARCH64_SWS_OP_CONVERT
@ AARCH64_SWS_OP_CONVERT
Definition: ops_impl.h:55
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
SWS_OP_LINEAR
@ SWS_OP_LINEAR
Definition: ops.h:57
SWS_OP_FILTER_H
@ SWS_OP_FILTER_H
Definition: ops.h:61
AARCH64_PIXEL_F32
@ AARCH64_PIXEL_F32
Definition: ops_impl.h:33
SWS_OP_PACK
@ SWS_OP_PACK
Definition: ops.h:45
AARCH64_SWS_OP_SCALE
@ AARCH64_SWS_OP_SCALE
Definition: ops_impl.h:59
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
LINEAR_MASK_SET
#define LINEAR_MASK_SET(mask, idx, jdx, val)
Definition: ops_impl.h:123
SWS_OP_FILTER_V
@ SWS_OP_FILTER_V
Definition: ops.h:62
AARCH64_SWS_OP_READ_PACKED
@ AARCH64_SWS_OP_READ_PACKED
Definition: ops_impl.h:42
LINEAR_MASK_X
#define LINEAR_MASK_X
Definition: ops_impl.h:128
SwsPixelType
SwsPixelType
Definition: uops.h:38
error.h
linear_index_from_sws_op
static int linear_index_from_sws_op(int idx)
The column index order for SwsLinearOp.mask follows the affine transform order, where the offset is t...
Definition: ops_impl_conv.c:49
AARCH64_SWS_OP_WRITE_PLANAR
@ AARCH64_SWS_OP_WRITE_PLANAR
Definition: ops_impl.h:47
AARCH64_SWS_OP_LSHIFT
@ AARCH64_SWS_OP_LSHIFT
Definition: ops_impl.h:52
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
SWS_OP_RSHIFT
@ SWS_OP_RSHIFT
Definition: ops.h:47
SWS_OP_WRITE
@ SWS_OP_WRITE
Definition: ops.h:39
SWS_PIXEL_U32
@ SWS_PIXEL_U32
Definition: uops.h:42
AARCH64_SWS_OP_WRITE_BIT
@ AARCH64_SWS_OP_WRITE_BIT
Definition: ops_impl.h:44
xf
#define xf(width, name, var, range_min, range_max, subs,...)
Definition: cbs_av1.c:622
AARCH64_SWS_OP_READ_PLANAR
@ AARCH64_SWS_OP_READ_PLANAR
Definition: ops_impl.h:43
AARCH64_SWS_OP_EXPAND
@ AARCH64_SWS_OP_EXPAND
Definition: ops_impl.h:56
AARCH64_SWS_OP_UNPACK
@ AARCH64_SWS_OP_UNPACK
Definition: ops_impl.h:50
SwsOpList::ops
SwsOp * ops
Definition: ops.h:284
SWS_PIXEL_U8
@ SWS_PIXEL_U8
Definition: uops.h:40
SwsOp
Definition: ops.h:228
MASK_SET
#define MASK_SET(mask, idx, val)
Definition: ops_impl.h:110
SWS_OP_MAX
@ SWS_OP_MAX
Definition: ops.h:53
AARCH64_PIXEL_U8
@ AARCH64_PIXEL_U8
Definition: ops_impl.h:30
AARCH64_PIXEL_U32
@ AARCH64_PIXEL_U32
Definition: ops_impl.h:32
convert_to_aarch64_impl
static int convert_to_aarch64_impl(SwsContext *ctx, const SwsOpList *ops, int n, int block_size, SwsAArch64OpImplParams *out)
Convert SwsOp to a SwsAArch64OpImplParams.
Definition: ops_impl_conv.c:59
AVRational::den
int den
Denominator.
Definition: rational.h:60
SWS_OP_SWAP_BYTES
@ SWS_OP_SWAP_BYTES
Definition: ops.h:40
AARCH64_SWS_OP_WRITE_PACKED
@ AARCH64_SWS_OP_WRITE_PACKED
Definition: ops_impl.h:46
SwsAArch64OpImplParams
SwsAArch64OpImplParams describes the parameters for an SwsAArch64OpType operation.
Definition: ops_impl.h:92
SWS_PIXEL_F32
@ SWS_PIXEL_F32
Definition: uops.h:43
AARCH64_PIXEL_U16
@ AARCH64_PIXEL_U16
Definition: ops_impl.h:31
SWS_OP_CONVERT
@ SWS_OP_CONVERT
Definition: ops.h:51
SwsOpList
Helper struct for representing a list of operations.
Definition: ops.h:283
SwsContext
Main external API structure.
Definition: swscale.h:229
SWS_PIXEL_U16
@ SWS_PIXEL_U16
Definition: uops.h:41