FFmpeg
ops_memcpy.c
Go to the documentation of this file.
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 
21 #include "libavutil/avassert.h"
22 #include "libavutil/mem.h"
23 
24 #include "ops_internal.h"
25 
26 typedef struct MemcpyPriv {
28  int index[4]; /* or -1 to clear plane */
29  uint8_t clear_value[4];
30 } MemcpyPriv;
31 
32 /**
33  * Switch to loop if total padding exceeds this number of bytes. Chosen to
34  * align with the typical L1 cache size of modern CPUs, as this avoids the
35  * risk of the implementation loading one extra unnecessary cache line.
36  */
37 #define SWS_MAX_PADDING 64
38 
39 /* Memcpy backend for trivial cases */
40 
41 static void process(const SwsOpExec *exec, const void *priv,
42  int x_start, int y_start, int x_end, int y_end)
43 {
44  const MemcpyPriv *p = priv;
45  const int lines = y_end - y_start;
46  const int bytes = x_end * exec->block_size_out;
47  av_assert1(x_start == 0 && x_end == exec->width);
48 
49  for (int i = 0; i < p->num_planes; i++) {
50  uint8_t *out = exec->out[i];
51  const int idx = p->index[i];
52  const int use_loop = exec->out_stride[i] > bytes + SWS_MAX_PADDING;
53  if (idx < 0 && !use_loop) {
54  memset(out, p->clear_value[i], exec->out_stride[i] * lines);
55  } else if (idx < 0) {
56  for (int y = y_start; y < y_end; y++) {
57  memset(out, p->clear_value[i], bytes);
58  out += exec->out_stride[i];
59  }
60  } else if (exec->out_stride[i] == exec->in_stride[idx] && !use_loop) {
61  memcpy(out, exec->in[idx], exec->out_stride[i] * lines);
62  } else {
63  const uint8_t *in = exec->in[idx];
64  for (int y = y_start; y < y_end; y++) {
65  memcpy(out, in, bytes);
66  out += exec->out_stride[i];
67  in += exec->in_stride[idx];
68  }
69  }
70  }
71 }
72 
74 {
75  MemcpyPriv p = {0};
76 
77  for (int n = 0; n < ops->num_ops; n++) {
78  const SwsOp *op = &ops->ops[n];
79  switch (op->op) {
80  case SWS_OP_READ:
81  if ((op->rw.packed && op->rw.elems != 1) || op->rw.frac || op->rw.filter)
82  return AVERROR(ENOTSUP);
83  for (int i = 0; i < op->rw.elems; i++)
84  p.index[i] = i;
85  break;
86 
87  case SWS_OP_SWIZZLE: {
88  const MemcpyPriv orig = p;
89  for (int i = 0; i < 4; i++) {
90  /* Explicitly exclude swizzle masks that contain duplicates,
91  * because these are wasteful to implement as a memcpy */
92  for (int j = 0; j < i; j++) {
93  if (op->swizzle.in[i] == op->swizzle.in[j])
94  return AVERROR(ENOTSUP);
95  }
96  p.index[i] = orig.index[op->swizzle.in[i]];
97  }
98  break;
99  }
100 
101  case SWS_OP_CLEAR:
102  for (int i = 0; i < 4; i++) {
103  if (!SWS_COMP_TEST(op->clear.mask, i))
104  continue;
105  if (op->clear.value[i].den != 1)
106  return AVERROR(ENOTSUP);
107 
108  /* Ensure all bytes to be cleared are the same, because we
109  * can't memset on multi-byte sequences */
110  uint8_t val = op->clear.value[i].num & 0xFF;
111  uint32_t ref = val;
112  switch (ff_sws_pixel_type_size(op->type)) {
113  case 2: ref *= 0x101; break;
114  case 4: ref *= 0x1010101; break;
115  }
116  if (ref != op->clear.value[i].num)
117  return AVERROR(ENOTSUP);
118  p.clear_value[i] = val;
119  p.index[i] = -1;
120  }
121  break;
122 
123  case SWS_OP_WRITE:
124  if ((op->rw.packed && op->rw.elems != 1) || op->rw.frac || op->rw.filter)
125  return AVERROR(ENOTSUP);
126  p.num_planes = op->rw.elems;
127  break;
128 
129  default:
130  return AVERROR(ENOTSUP);
131  }
132  }
133 
134  *out = (SwsCompiledOp) {
135  .slice_align = 1,
136  .block_size = 1,
137  .func = process,
138  .priv = av_memdup(&p, sizeof(p)),
139  .free = av_free,
140  };
141  return out->priv ? 0 : AVERROR(ENOMEM);
142 }
143 
145  .name = "memcpy",
146  .compile = compile,
147  .hw_format = AV_PIX_FMT_NONE,
148 };
SWS_OP_READ
@ SWS_OP_READ
Definition: ops.h:50
SWS_OP_SWIZZLE
@ SWS_OP_SWIZZLE
Definition: ops.h:53
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
out
static FILE * out
Definition: movenc.c:55
SWS_OP_CLEAR
@ SWS_OP_CLEAR
Definition: ops.h:62
SwsOpExec::in
const uint8_t * in[4]
Definition: ops_dispatch.h:37
SwsOpExec::out_stride
ptrdiff_t out_stride[4]
Definition: ops_dispatch.h:42
SWS_MAX_PADDING
#define SWS_MAX_PADDING
Switch to loop if total padding exceeds this number of bytes.
Definition: ops_memcpy.c:37
SwsOpExec::in_stride
ptrdiff_t in_stride[4]
Definition: ops_dispatch.h:41
SwsOpBackend::name
const char * name
Definition: ops_dispatch.h:131
ff_sws_pixel_type_size
int ff_sws_pixel_type_size(SwsPixelType type)
Definition: ops.c:77
MemcpyPriv::num_planes
int num_planes
Definition: ops_memcpy.c:27
av_memdup
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
Definition: mem.c:304
SwsOpList::num_ops
int num_ops
Definition: ops.h:290
SWS_COMP_TEST
#define SWS_COMP_TEST(mask, X)
Definition: ops.h:89
val
static double val(void *priv, double ch)
Definition: aeval.c:77
avassert.h
backend_murder
const SwsOpBackend backend_murder
Definition: ops_memcpy.c:144
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
MemcpyPriv::clear_value
uint8_t clear_value[4]
Definition: ops_memcpy.c:29
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
SwsOpBackend
Definition: ops_dispatch.h:130
SwsOpExec
Copyright (C) 2026 Niklas Haas.
Definition: ops_dispatch.h:35
compile
static int compile(SwsContext *ctx, SwsOpList *ops, SwsCompiledOp *out)
Definition: ops_memcpy.c:73
SwsOpExec::block_size_out
int32_t block_size_out
Definition: ops_dispatch.h:58
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:424
process
static void process(const SwsOpExec *exec, const void *priv, int x_start, int y_start, int x_end, int y_end)
Definition: ops_memcpy.c:41
MemcpyPriv::index
int index[4]
Definition: ops_memcpy.c:28
SWS_OP_WRITE
@ SWS_OP_WRITE
Definition: ops.h:51
SwsOpExec::out
uint8_t * out[4]
Definition: ops_dispatch.h:38
SwsOpList::ops
SwsOp * ops
Definition: ops.h:289
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:58
ops_internal.h
SwsOp
Definition: ops.h:238
SwsOpExec::width
int32_t width
Definition: ops_dispatch.h:55
SwsCompiledOp
Definition: ops_dispatch.h:100
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
mem.h
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
MemcpyPriv
Copyright (C) 2025 Niklas Haas.
Definition: ops_memcpy.c:26
SwsOpList
Helper struct for representing a list of operations.
Definition: ops.h:288
SwsContext
Main external API structure.
Definition: swscale.h:206