FFmpeg
Loading...
Searching...
No Matches
uops_tmpl.c
Go to the documentation of this file.
1/**
2 * Copyright (C) 2026 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/bswap.h>
22
23#include "uops_tmpl.h"
24
25#ifndef BIT_DEPTH
26# define BIT_DEPTH 8
27#endif
28
29#if IS_FLOAT && BIT_DEPTH == 32
30# define PIXEL_TYPE SWS_PIXEL_F32
31# define pixel_t float
32# define inter_t float
33# define uinter_t float
34# define vec3_t v3f32_t
35# define PX F32
36# define px f32
37#elif BIT_DEPTH == 32
38# define PIXEL_MAX 0xFFFFFFFFu
39# define PIXEL_SWAP av_bswap32
40# define pixel_t uint32_t
41# define inter_t int64_t
42# define uinter_t uint64_t
43# define PX U32
44# define px u32
45#elif BIT_DEPTH == 16
46# define PIXEL_MAX 0xFFFFu
47# define PIXEL_SWAP av_bswap16
48# define pixel_t uint16_t
49# define inter_t int64_t
50# define uinter_t uint64_t
51# define PX U16
52# define px u16
53#elif BIT_DEPTH == 8
54# define PIXEL_MAX 0xFFu
55# define pixel_t uint8_t
56# define inter_t int32_t
57# define uinter_t uint32_t
58# define PX U8
59# define px u8
60#else
61# error Invalid BIT_DEPTH
62#endif
63
64/* Every intermediate float result is cast to pixel_t, which rounds away the
65 * excess precision of x87 math for the same results as everywhere else */
66
67/*********************************
68 * Generic read/write operations *
69 *********************************/
70
71DECL_READ(read_planar, const SwsCompMask mask)
72{
74 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
75 if (X) x[i] = in0[i];
76 if (Y) y[i] = in1[i];
77 if (Z) z[i] = in2[i];
78 if (W) w[i] = in3[i];
79 }
80
81 if (X) iter->in[0] += SIZEOF_BLOCK;
82 if (Y) iter->in[1] += SIZEOF_BLOCK;
83 if (Z) iter->in[2] += SIZEOF_BLOCK;
84 if (W) iter->in[3] += SIZEOF_BLOCK;
85
86 CONTINUE(x, y, z, w);
87}
88
89DECL_READ(read_packed, const SwsCompMask mask)
90{
91 const int elems = W ? 4 : Z ? 3 : Y ? 2 : 1;
92
94 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
95 if (X) x[i] = in0[elems * i + 0];
96 if (Y) y[i] = in0[elems * i + 1];
97 if (Z) z[i] = in0[elems * i + 2];
98 if (W) w[i] = in0[elems * i + 3];
99 }
100
101 iter->in[0] += SIZEOF_BLOCK * elems;
102 CONTINUE(x, y, z, w);
103}
104
105DECL_WRITE(write_planar, const SwsCompMask mask)
106{
108 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
109 if (X) out0[i] = x[i];
110 if (Y) out1[i] = y[i];
111 if (Z) out2[i] = z[i];
112 if (W) out3[i] = w[i];
113 }
114
115 if (X) iter->out[0] += SIZEOF_BLOCK;
116 if (Y) iter->out[1] += SIZEOF_BLOCK;
117 if (Z) iter->out[2] += SIZEOF_BLOCK;
118 if (W) iter->out[3] += SIZEOF_BLOCK;
119}
120
121DECL_WRITE(write_packed, const SwsCompMask mask)
122{
123 const int elems = W ? 4 : Z ? 3 : Y ? 2 : 1;
124
126 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
127 if (X) out0[elems * i + 0] = x[i];
128 if (Y) out0[elems * i + 1] = y[i];
129 if (Z) out0[elems * i + 2] = z[i];
130 if (W) out0[elems * i + 3] = w[i];
131 }
132
133 iter->out[0] += SIZEOF_BLOCK * elems;
134}
135
136#if BIT_DEPTH == 8
137
139{
141
143 for (int i = 0; i < SWS_BLOCK_SIZE; i += 8) {
144 const pixel_t val = ((const pixel_t *) in0)[i >> 3];
145 x[i + 0] = (val >> 7) & 1;
146 x[i + 1] = (val >> 6) & 1;
147 x[i + 2] = (val >> 5) & 1;
148 x[i + 3] = (val >> 4) & 1;
149 x[i + 4] = (val >> 3) & 1;
150 x[i + 5] = (val >> 2) & 1;
151 x[i + 6] = (val >> 1) & 1;
152 x[i + 7] = (val >> 0) & 1;
153 }
154
155 iter->in[0] += SIZEOF_BLOCK >> 3;
156 CONTINUE(x, y, z, w);
157}
158
159DECL_READ(read_nibble, const SwsCompMask mask)
160{
162
164 for (int i = 0; i < SWS_BLOCK_SIZE; i += 2) {
165 const pixel_t val = in0[i >> 1];
166 x[i + 0] = val >> 4; /* high nibble */
167 x[i + 1] = val & 0xF; /* low nibble */
168 }
169
170 iter->in[0] += SIZEOF_BLOCK >> 1;
171 CONTINUE(x, y, z, w);
172}
173
174DECL_READ(read_palette, const SwsCompMask mask)
175{
177
179 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
180 const pixel_t index = in0[i];
181 const pixel_t *value = &in1[index * 4];
182 x[i] = value[0];
183 y[i] = value[1];
184 z[i] = value[2];
185 w[i] = value[3];
186 }
187
188 iter->in[0] += SIZEOF_BLOCK;
189 CONTINUE(x, y, z, w);
190}
191
192DECL_WRITE(write_bit, const SwsCompMask mask)
193{
195
197 for (int i = 0; i < SWS_BLOCK_SIZE; i += 8) {
198 out0[i >> 3] = x[i + 0] << 7 |
199 x[i + 1] << 6 |
200 x[i + 2] << 5 |
201 x[i + 3] << 4 |
202 x[i + 4] << 3 |
203 x[i + 5] << 2 |
204 x[i + 6] << 1 |
205 x[i + 7];
206 }
207
208 iter->out[0] += SIZEOF_BLOCK >> 3;
209}
210
211DECL_WRITE(write_nibble, const SwsCompMask mask)
212{
214
216 for (int i = 0; i < SWS_BLOCK_SIZE; i += 2)
217 out0[i >> 1] = x[i] << 4 | x[i + 1];
218
219 iter->out[0] += SIZEOF_BLOCK >> 1;
220}
221
222#endif /* BIT_DEPTH == 8 */
223
224SWS_FOR(PX, READ_PLANAR, DECL_IMPL_READ, read_planar)
225SWS_FOR(PX, READ_PACKED, DECL_IMPL_READ, read_packed)
226SWS_FOR(PX, READ_NIBBLE, DECL_IMPL_READ, read_nibble)
227SWS_FOR(PX, READ_BIT, DECL_IMPL_READ, read_bit)
228SWS_FOR(PX, READ_PALETTE, DECL_IMPL_READ, read_palette)
229SWS_FOR(PX, WRITE_PLANAR, DECL_IMPL_WRITE, write_planar)
230SWS_FOR(PX, WRITE_PACKED, DECL_IMPL_WRITE, write_packed)
231SWS_FOR(PX, WRITE_NIBBLE, DECL_IMPL_WRITE, write_nibble)
232SWS_FOR(PX, WRITE_BIT, DECL_IMPL_WRITE, write_bit)
233
234SWS_FOR_STRUCT(PX, READ_PLANAR, DECL_ENTRY)
235SWS_FOR_STRUCT(PX, READ_PACKED, DECL_ENTRY)
236SWS_FOR_STRUCT(PX, READ_NIBBLE, DECL_ENTRY)
237SWS_FOR_STRUCT(PX, READ_BIT, DECL_ENTRY)
238SWS_FOR_STRUCT(PX, READ_PALETTE, DECL_ENTRY)
239SWS_FOR_STRUCT(PX, WRITE_PLANAR, DECL_ENTRY)
240SWS_FOR_STRUCT(PX, WRITE_PACKED, DECL_ENTRY)
241SWS_FOR_STRUCT(PX, WRITE_NIBBLE, DECL_ENTRY)
242SWS_FOR_STRUCT(PX, WRITE_BIT, DECL_ENTRY)
243
244/*****************************
245 * Scaling / filtering reads *
246 *****************************/
247
249{
250 if (params->uop->par.filter.type != SWS_PIXEL_F32)
251 return AVERROR(ENOTSUP);
252
253 const SwsFilterWeights *filter = params->uop->data.kernel;
254 static_assert(sizeof(out->priv.ptr) <= sizeof(int32_t[2]),
255 ">8 byte pointers not supported");
256
257 /* Pre-convert weights to float */
258 float *weights = av_calloc(filter->num_weights, sizeof(float));
259 if (!weights)
260 return AVERROR(ENOMEM);
261
262 for (int i = 0; i < filter->num_weights; i++)
263 weights[i] = (float) filter->weights[i] / SWS_FILTER_SCALE;
264
265 out->priv.ptr = weights;
266 out->priv.i32[2] = filter->filter_size;
267 out->free = ff_op_priv_free;
268 return 0;
269}
270
271/* Fully general vertical planar filter case */
272DECL_READ(read_planar_fv, const SwsCompMask mask, const SwsPixelType type)
273{
275 const SwsOpExec *exec = iter->exec;
276 const float *restrict weights = impl->priv.ptr;
277 const int filter_size = impl->priv.i32[2];
278 weights += filter_size * iter->y;
279
280 block_t xs, ys, zs, ws;
281 if (X) memset(&xs.f32, 0, sizeof(xs.f32));
282 if (Y) memset(&ys.f32, 0, sizeof(ys.f32));
283 if (Z) memset(&zs.f32, 0, sizeof(zs.f32));
284 if (W) memset(&ws.f32, 0, sizeof(ws.f32));
285
286 for (int j = 0; j < filter_size; j++) {
287 const float weight = weights[j];
288
290 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
291 if (X) xs.f32[i] += (float) (weight * in0[i]);
292 if (Y) ys.f32[i] += (float) (weight * in1[i]);
293 if (Z) zs.f32[i] += (float) (weight * in2[i]);
294 if (W) ws.f32[i] += (float) (weight * in3[i]);
295 }
296
297 if (X) in0 = bump_ptr(in0, exec->in_stride[0]);
298 if (Y) in1 = bump_ptr(in1, exec->in_stride[1]);
299 if (Z) in2 = bump_ptr(in2, exec->in_stride[2]);
300 if (W) in3 = bump_ptr(in3, exec->in_stride[3]);
301 }
302
303 if (X) iter->in[0] += SIZEOF_BLOCK;
304 if (Y) iter->in[1] += SIZEOF_BLOCK;
305 if (Z) iter->in[2] += SIZEOF_BLOCK;
306 if (W) iter->in[3] += SIZEOF_BLOCK;
307
308 CONTINUE(&xs, &ys, &zs, &ws);
309}
310
312{
313 if (params->uop->par.filter.type != SWS_PIXEL_F32)
314 return AVERROR(ENOTSUP);
315
316 SwsFilterWeights *filter = params->uop->data.kernel;
317 out->priv.i32[2] = filter->filter_size;
318
319 /* The horizontal filter uop reads weights for a full SWS_BLOCK_SIZE
320 * outputs per block (see read_planar_fh), so the weights array must be
321 * padded up to the block-aligned output count. Pad the tail with zero
322 * weights, which contribute nothing to the accumulated sums. */
323 const size_t padded_w = FFALIGN(filter->dst_size, SWS_BLOCK_SIZE);
324 if (padded_w == filter->dst_size) {
325 out->priv.ptr = av_refstruct_ref(filter->weights);
326 out->free = ff_op_priv_unref;
327 return 0;
328 }
329
330 int *weights = av_calloc(padded_w * filter->filter_size, sizeof(*weights));
331 if (!weights)
332 return AVERROR(ENOMEM);
333 memcpy(weights, filter->weights, filter->num_weights * sizeof(*weights));
334 out->priv.ptr = weights;
335 out->free = ff_op_priv_free;
336 return 0;
337}
338
339/* Fully general horizontal planar filter case */
340DECL_READ(read_planar_fh, const SwsCompMask mask, const SwsPixelType type)
341{
343 const SwsOpExec *exec = iter->exec;
344 const int *restrict weights = impl->priv.ptr;
345 const int filter_size = impl->priv.i32[2];
346 const float scale = 1.0f / SWS_FILTER_SCALE;
347 const int xpos = iter->x;
348 weights += filter_size * iter->x;
349
350 block_t xs, ys, zs, ws;
351 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
352 const int offset = exec->in_offset_x[xpos + i];
353 pixel_t *start0 = bump_ptr(in0, offset);
354 pixel_t *start1 = bump_ptr(in1, offset);
355 pixel_t *start2 = bump_ptr(in2, offset);
356 pixel_t *start3 = bump_ptr(in3, offset);
357
358 inter_t sx = 0, sy = 0, sz = 0, sw = 0;
359 for (int j = 0; j < filter_size; j++) {
360 const int weight = weights[j];
361 if (X) sx += (inter_t) (weight * start0[j]);
362 if (Y) sy += (inter_t) (weight * start1[j]);
363 if (Z) sz += (inter_t) (weight * start2[j]);
364 if (W) sw += (inter_t) (weight * start3[j]);
365 }
366
367 if (X) xs.f32[i] = (float) sx * scale;
368 if (Y) ys.f32[i] = (float) sy * scale;
369 if (Z) zs.f32[i] = (float) sz * scale;
370 if (W) ws.f32[i] = (float) sw * scale;
371
372 weights += filter_size;
373 }
374
375 CONTINUE(&xs, &ys, &zs, &ws);
376}
377
378SWS_FOR(PX, READ_PLANAR_FV, DECL_IMPL_READ, read_planar_fv)
379SWS_FOR(PX, READ_PLANAR_FH, DECL_IMPL_READ, read_planar_fh)
380SWS_FOR_STRUCT(PX, READ_PLANAR_FV, DECL_ENTRY, .setup = fn(setup_filter_v) )
381SWS_FOR_STRUCT(PX, READ_PLANAR_FH, DECL_ENTRY, .setup = fn(setup_filter_h) )
382
383/***************************
384 * Permutation and copying *
385 ***************************/
386
387DECL_FUNC(permute, const SwsCompMask mask, int num_moves,
388 int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5,
389 int8_t s0, int8_t s1, int8_t s2, int8_t s3, int8_t s4, int8_t s5)
390{
391 const int8_t dst[SWS_UOP_MOVE_MAX] = { d0, d1, d2, d3, d4, d5 };
392 const int8_t src[SWS_UOP_MOVE_MAX] = { s0, s1, s2, s3, s4, s5 };
393
394 pixel_t *ptr[5] = { NULL, x, y, z, w };
395 for (int n = 0; n < num_moves; n++)
396 ptr[dst[n] + 1] = ptr[src[n] + 1];
397
398 /* The unneeded registers may still alias the used ones, so point them
399 * back at the stack to avoid collisions */
400 block_t xx, yy, zz, ww;
401 CONTINUE(X ? ptr[1] : xx.px,
402 Y ? ptr[2] : yy.px,
403 Z ? ptr[3] : zz.px,
404 W ? ptr[4] : ww.px);
405}
406
407DECL_FUNC(copy, const SwsCompMask mask, int num_moves,
408 int8_t d0, int8_t d1, int8_t d2, int8_t d3, int8_t d4, int8_t d5,
409 int8_t s0, int8_t s1, int8_t s2, int8_t s3, int8_t s4, int8_t s5)
410{
411 const size_t block_size = SWS_BLOCK_SIZE * sizeof(pixel_t);
412 const int8_t dst[SWS_UOP_MOVE_MAX] = { d0, d1, d2, d3, d4, d5 };
413 const int8_t src[SWS_UOP_MOVE_MAX] = { s0, s1, s2, s3, s4, s5 };
414
415 block_t data[5];
416 memcpy(&data[1].px, x, block_size);
417 memcpy(&data[2].px, y, block_size);
418 memcpy(&data[3].px, z, block_size);
419 memcpy(&data[4].px, w, block_size);
420
421 for (int n = 0; n < num_moves; n++)
422 data[dst[n] + 1] = data[src[n] + 1];
423
424 memcpy(x, &data[1].px, block_size);
425 memcpy(y, &data[2].px, block_size);
426 memcpy(z, &data[3].px, block_size);
427 memcpy(w, &data[4].px, block_size);
428
429 CONTINUE(x, y, z, w);
430}
431
432SWS_FOR(PX, PERMUTE, DECL_IMPL, permute)
434SWS_FOR_STRUCT(PX, PERMUTE, DECL_ENTRY)
436
437/*********************
438 * Format conversion *
439 *********************/
440
441#define DECL_CAST(DST, dst) \
442 DECL_FUNC(to_##dst, const SwsCompMask mask) \
443 { \
444 block_t xx, yy, zz, ww; \
445 \
446 SWS_LOOP \
447 for (int i = 0; i < SWS_BLOCK_SIZE; i++) { \
448 if (X) xx.dst[i] = x[i]; \
449 if (Y) yy.dst[i] = y[i]; \
450 if (Z) zz.dst[i] = z[i]; \
451 if (W) ww.dst[i] = w[i]; \
452 } \
453 \
454 CONTINUE(&xx, &yy, &zz, &ww); \
455 } \
456 \
457 SWS_FOR(PX, TO_##DST, DECL_IMPL, to_##dst) \
458 SWS_FOR_STRUCT(PX, TO_##DST, DECL_ENTRY)
459
460DECL_CAST(U8, u8)
461DECL_CAST(U16, u16)
462DECL_CAST(U32, u32)
463DECL_CAST(F32, f32)
464
465/********************
466 * Bit manipulation *
467 ********************/
468
469#if !IS_FLOAT
470DECL_FUNC(lshift, const SwsCompMask mask, const uint8_t amount)
471{
473 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
474 if (X) x[i] <<= amount;
475 if (Y) y[i] <<= amount;
476 if (Z) z[i] <<= amount;
477 if (W) w[i] <<= amount;
478 }
479
480 CONTINUE(x, y, z, w);
481}
482
483DECL_FUNC(rshift, const SwsCompMask mask, const uint8_t amount)
484{
486 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
487 if (X) x[i] >>= amount;
488 if (Y) y[i] >>= amount;
489 if (Z) z[i] >>= amount;
490 if (W) w[i] >>= amount;
491 }
492
493 CONTINUE(x, y, z, w);
494}
495#endif
496
497SWS_FOR(PX, LSHIFT, DECL_IMPL, lshift)
498SWS_FOR(PX, RSHIFT, DECL_IMPL, rshift)
499
500SWS_FOR_STRUCT(PX, LSHIFT, DECL_ENTRY)
502
503#ifdef PIXEL_SWAP
504DECL_FUNC(swap_bytes, const SwsCompMask mask)
505{
507 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
508 if (X) x[i] = PIXEL_SWAP(x[i]);
509 if (Y) y[i] = PIXEL_SWAP(y[i]);
510 if (Z) z[i] = PIXEL_SWAP(z[i]);
511 if (W) w[i] = PIXEL_SWAP(w[i]);
512 }
513
514 CONTINUE(x, y, z, w);
515}
516#endif /* PIXEL_SWAP */
517
518SWS_FOR(PX, SWAP_BYTES, DECL_IMPL, swap_bytes)
519SWS_FOR_STRUCT(PX, SWAP_BYTES, DECL_ENTRY)
520
521#ifdef PIXEL_MAX
522DECL_FUNC(expand_bit, const SwsCompMask mask)
523{
525 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
526 if (X) x[i] = x[i] ? PIXEL_MAX : 0;
527 if (Y) y[i] = y[i] ? PIXEL_MAX : 0;
528 if (Z) z[i] = z[i] ? PIXEL_MAX : 0;
529 if (W) w[i] = w[i] ? PIXEL_MAX : 0;
530 }
531
532 CONTINUE(x, y, z, w);
533}
534#endif
535
536#if BIT_DEPTH == 8
537DECL_FUNC(expand_pair, const SwsCompMask mask)
538{
539 block_t x16, y16, z16, w16;
540
542 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
543 if (X) x16.u16[i] = x[i] << 8 | x[i];
544 if (Y) y16.u16[i] = y[i] << 8 | y[i];
545 if (Z) z16.u16[i] = z[i] << 8 | z[i];
546 if (W) w16.u16[i] = w[i] << 8 | w[i];
547 }
548
549 CONTINUE(&x16, &y16, &z16, &w16);
550}
551
552DECL_FUNC(expand_quad, const SwsCompMask mask)
553{
554 block_t x32, y32, z32, w32;
555
557 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
558 if (X) x32.u32[i] = (uint32_t) x[i] << 24 | x[i] << 16 | x[i] << 8 | x[i];
559 if (Y) y32.u32[i] = (uint32_t) y[i] << 24 | y[i] << 16 | y[i] << 8 | y[i];
560 if (Z) z32.u32[i] = (uint32_t) z[i] << 24 | z[i] << 16 | z[i] << 8 | z[i];
561 if (W) w32.u32[i] = (uint32_t) w[i] << 24 | w[i] << 16 | w[i] << 8 | w[i];
562 }
563
564 CONTINUE(&x32, &y32, &z32, &w32);
565}
566#endif /* BIT_DEPTH == 8 */
567
568SWS_FOR(PX, EXPAND_BIT, DECL_IMPL, expand_bit)
569SWS_FOR(PX, EXPAND_PAIR, DECL_IMPL, expand_pair)
570SWS_FOR(PX, EXPAND_QUAD, DECL_IMPL, expand_quad)
571SWS_FOR_STRUCT(PX, EXPAND_BIT, DECL_ENTRY)
572SWS_FOR_STRUCT(PX, EXPAND_PAIR, DECL_ENTRY)
573SWS_FOR_STRUCT(PX, EXPAND_QUAD, DECL_ENTRY)
574
575/*************************
576 * Packing and unpacking *
577 ************************/
578
579#if !IS_FLOAT
581 const uint8_t bx, const uint8_t by,
582 const uint8_t bz, const uint8_t bw)
583{
584 const uint8_t sx = bw + bz + by;
585 const uint8_t sy = bw + bz;
586 const uint8_t sz = bw;
587 const uint8_t sw = 0;
588
589 const pixel_t mx = (1 << bx) - 1;
590 const pixel_t my = (1 << by) - 1;
591 const pixel_t mz = (1 << bz) - 1;
592 const pixel_t mw = (1 << bw) - 1;
593
595 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
596 const pixel_t val = x[i];
597 if (X) x[i] = (val >> sx) & mx;
598 if (Y) y[i] = (val >> sy) & my;
599 if (Z) z[i] = (val >> sz) & mz;
600 if (W) w[i] = (val >> sw) & mw;
601 }
602
603 CONTINUE(x, y, z, w);
604}
605
607 const uint8_t bx, const uint8_t by,
608 const uint8_t bz, const uint8_t bw)
609{
610 const uint8_t sx = bw + bz + by;
611 const uint8_t sy = bw + bz;
612 const uint8_t sz = bw;
613 const uint8_t sw = 0;
614
616 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
617 pixel_t val = 0;
618 if (X) val |= x[i] << sx;
619 if (Y) val |= y[i] << sy;
620 if (Z) val |= z[i] << sz;
621 if (W) val |= w[i] << sw;
622 x[i] = val;
623 }
624
625 CONTINUE(x, y, z, w);
626}
627#endif /* !IS_FLOAT */
628
629SWS_FOR(PX, UNPACK, DECL_IMPL, unpack)
630SWS_FOR(PX, PACK, DECL_IMPL, pack)
631SWS_FOR_STRUCT(PX, UNPACK, DECL_ENTRY)
632SWS_FOR_STRUCT(PX, PACK, DECL_ENTRY)
633
634/***********************
635 * Pixel data clearing *
636 ***********************/
637
638#ifdef PIXEL_MAX
639DECL_FUNC(clear, const SwsCompMask mask, const SwsCompMask one,
640 const SwsCompMask zero)
641{
642 #define ONE(N) SWS_COMP_TEST(one, N)
643 #define ZERO(N) SWS_COMP_TEST(zero, N)
644 const pixel_t cx = ONE(0) ? PIXEL_MAX : ZERO(0) ? 0 : impl->priv.px[0];
645 const pixel_t cy = ONE(1) ? PIXEL_MAX : ZERO(1) ? 0 : impl->priv.px[1];
646 const pixel_t cz = ONE(2) ? PIXEL_MAX : ZERO(2) ? 0 : impl->priv.px[2];
647 const pixel_t cw = ONE(3) ? PIXEL_MAX : ZERO(3) ? 0 : impl->priv.px[3];
648
650 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
651 if (X) x[i] = cx;
652 if (Y) y[i] = cy;
653 if (Z) z[i] = cz;
654 if (W) w[i] = cw;
655 }
656
657 CONTINUE(x, y, z, w);
658}
659#endif
660
661SWS_FOR(PX, CLEAR, DECL_IMPL, clear)
663
664/*************************
665 * Arithmetic operations *
666 *************************/
667
669{
670 const pixel_t scale = impl->priv.px[0];
671
673 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
674 if (X) x[i] *= scale;
675 if (Y) y[i] *= scale;
676 if (Z) z[i] *= scale;
677 if (W) w[i] *= scale;
678 }
679
680 CONTINUE(x, y, z, w);
681}
682
684{
686 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
687 if (X) x[i] += impl->priv.px[0];
688 if (Y) y[i] += impl->priv.px[1];
689 if (Z) z[i] += impl->priv.px[2];
690 if (W) w[i] += impl->priv.px[3];
691 }
692
693 CONTINUE(x, y, z, w);
694}
695
697{
699 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
700 if (X) x[i] = FFMIN(x[i], impl->priv.px[0]);
701 if (Y) y[i] = FFMIN(y[i], impl->priv.px[1]);
702 if (Z) z[i] = FFMIN(z[i], impl->priv.px[2]);
703 if (W) w[i] = FFMIN(w[i], impl->priv.px[3]);
704 }
705
706 CONTINUE(x, y, z, w);
707}
708
710{
712 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
713 if (X) x[i] = FFMAX(x[i], impl->priv.px[0]);
714 if (Y) y[i] = FFMAX(y[i], impl->priv.px[1]);
715 if (Z) z[i] = FFMAX(z[i], impl->priv.px[2]);
716 if (W) w[i] = FFMAX(w[i], impl->priv.px[3]);
717 }
718
719 CONTINUE(x, y, z, w);
720}
721
723SWS_FOR(PX, ADD, DECL_IMPL, add)
730
731/*************
732 * Dithering *
733 *************/
734
736{
737 const SwsUOp *uop = params->uop;
738 const SwsDitherUOp *dither = &uop->par.dither;
739 const int size = 1 << dither->size_log2;
740 if (size >= SWS_BLOCK_SIZE) {
741 /* No extra padding needed */
742 out->priv.ptr = av_refstruct_ref(uop->data.ptr);
743 out->free = ff_op_priv_unref;
744 return 0;
745 }
746
747 const int stride = FFMAX(size, SWS_BLOCK_SIZE);
749 pixel_t *matrix = av_malloc(sizeof(pixel_t) * height * stride);
750 if (!matrix)
751 return AVERROR(ENOMEM);
752 out->priv.ptr = matrix;
753 out->free = ff_op_priv_free;
754
755 /* Pad to multiple of block size. We don't need extra padding for the
756 * height because ff_sws_dither_height() already includes any padding
757 * necessary for the y_offset */
758 for (int y = 0; y < height; y++) {
759 pixel_t *row = &matrix[y * stride];
760 for (int x = 0; x < size; x++)
761 row[x] = uop->data.ptr[y * size + x].px;
762 for (int x = size; x < stride; x++)
763 row[x] = row[x % size];
764 }
765
766 return 0;
767}
768
770 const uint8_t off0, const uint8_t off1,
771 const uint8_t off2, const uint8_t off3,
772 const uint8_t size_log2)
773{
774 const int size = 1 << size_log2;
775 const int stride = FFMAX(size, SWS_BLOCK_SIZE);
776
777 const pixel_t *matrix = impl->priv.ptr;
778 matrix += (iter->y & (size - 1)) * stride;
779 matrix += (iter->x & (size - 1)) & ~(SWS_BLOCK_SIZE - 1);
780
781 const pixel_t *const row0 = &matrix[off0 * stride];
782 const pixel_t *const row1 = &matrix[off1 * stride];
783 const pixel_t *const row2 = &matrix[off2 * stride];
784 const pixel_t *const row3 = &matrix[off3 * stride];
785
787 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
788 if (X) x[i] += row0[i];
789 if (Y) y[i] += row1[i];
790 if (Z) z[i] += row2[i];
791 if (W) w[i] += row3[i];
792 }
793
794 CONTINUE(x, y, z, w);
795}
796
797SWS_FOR(PX, DITHER, DECL_IMPL, dither)
798SWS_FOR_STRUCT(PX, DITHER, DECL_ENTRY, .setup = fn(setup_dither) )
799
800/*********************
801 * Linear operations *
802 *********************/
803
804typedef struct {
805 /* Stored in split form for convenience */
806 pixel_t m[4][4];
807 pixel_t k[4];
808} fn(LinCoeffs);
809
811{
812 const SwsUOp *uop = params->uop;
813 fn(LinCoeffs) c;
814
815 for (int i = 0; i < 4; i++) {
816 for (int j = 0; j < 4; j++)
817 c.m[i][j] = uop->data.mat4x5[i][j].px;
818 c.k[i] = uop->data.mat4x5[i][4].px;
819 }
820
821 out->priv.ptr = av_memdup(&c, sizeof(c));
822 out->free = ff_op_priv_free;
823 return out->priv.ptr ? 0 : AVERROR(ENOMEM);
824}
825
826/**
827 * Fully general case for a 5x5 linear affine transformation. Should never be
828 * called without constant `mask`. This function will compile down to the
829 * appropriately optimized version for the required subset of operations when
830 * called with a constant mask.
831 */
832DECL_FUNC(linear, const SwsCompMask mask, const uint32_t one, const uint32_t zero)
833{
834 const fn(LinCoeffs) c = *(const fn(LinCoeffs) *) impl->priv.ptr;
835
837 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
838 const pixel_t xx = x[i];
839 const pixel_t yy = y[i];
840 const pixel_t zz = z[i];
841 const pixel_t ww = w[i];
842
843#define LIN_VAL(I, J, val) \
844 ((one & SWS_MASK(I, J)) ? (val) : (pixel_t) ((uinter_t) c.m[I][J] * (val)))
845
846#define LIN_ROW(I, var) do { \
847 pixel_t tmp = (zero & SWS_MASK(I, 4)) ? 0 : c.k[I]; \
848 if (!(zero & SWS_MASK(I, 0))) tmp += LIN_VAL(I, 0, xx); \
849 if (!(zero & SWS_MASK(I, 1))) tmp += LIN_VAL(I, 1, yy); \
850 if (!(zero & SWS_MASK(I, 2))) tmp += LIN_VAL(I, 2, zz); \
851 if (!(zero & SWS_MASK(I, 3))) tmp += LIN_VAL(I, 3, ww); \
852 var[i] = tmp; \
853} while (0)
854
855 if (X) LIN_ROW(0, x);
856 if (Y) LIN_ROW(1, y);
857 if (Z) LIN_ROW(2, z);
858 if (W) LIN_ROW(3, w);
859 }
860
861 CONTINUE(x, y, z, w);
862}
863
866
867/******************
868 * Look-up tables *
869 ******************/
870
871DECL_SETUP(setup_lut3d, params, out)
872{
873 const SwsLut3D *lut = params->uop->data.lut3d;
874 out->priv.ptr = (void *) av_refstruct_ref_c(lut);
875 out->free = ff_op_priv_unref;
876 return 0;
877}
878
879#if IS_FLOAT
880av_always_inline static vec3_t fn(vec3)(v3u16_t v)
881{
882 return (vec3_t) { v.x, v.y, v.z };
883}
884
885#define lerp(a, b, w) ((pixel_t) ((a) + (pixel_t) ((w) * (pixel_t) ((pixel_t) (b) - (a)))))
886
887av_always_inline static
888pixel_t fn(sum4)(pixel_t w0, pixel_t a, pixel_t w1, pixel_t b,
889 pixel_t w2, pixel_t c, pixel_t w3, pixel_t d)
890{
891 pixel_t sum = (pixel_t) (w0 * a);
892 sum += (pixel_t) (w1 * b);
893 sum += (pixel_t) (w2 * c);
894 sum += (pixel_t) (w3 * d);
895 return sum;
896}
897
898av_always_inline static
899vec3_t fn(lerp3)(vec3_t a, vec3_t b, pixel_t w)
900{
901 return (vec3_t) {
902 lerp(a.x, b.x, w),
903 lerp(a.y, b.y, w),
904 lerp(a.z, b.z, w),
905 };
906}
907
908av_always_inline static
909vec3_t fn(lut3d_static)(const SwsLut3D *restrict lut3d, vec3_t rgb)
910{
911 const int r_base = (int) rgb.x;
912 const int g_base = (int) rgb.y;
913 const int b_base = (int) rgb.z;
914
915 int off0 = (r_base < INPUT_LUT_SIZE - 1);
916 int off1 = (g_base < INPUT_LUT_SIZE - 1) * INPUT_LUT_SIZE;
917 int off2 = (b_base < INPUT_LUT_SIZE - 1) * INPUT_LUT_SIZE * INPUT_LUT_SIZE;
918 pixel_t f0 = rgb.x - r_base;
919 pixel_t f1 = rgb.y - g_base;
920 pixel_t f2 = rgb.z - b_base;
921
922 /* Sort offsets descending by relative weight */
923 if (f0 < f1) {
924 FFSWAP(pixel_t, f0, f1);
925 FFSWAP(int, off0, off1);
926 }
927 if (f0 < f2) {
928 FFSWAP(pixel_t, f0, f2);
929 FFSWAP(int, off0, off2);
930 }
931 if (f1 < f2) {
932 FFSWAP(pixel_t, f1, f2);
933 FFSWAP(int, off1, off2);
934 }
935
936 /* Tetrahedral interpolation */
937 const pixel_t w0 = 1 - f0;
938 const pixel_t w1 = f0 - f1;
939 const pixel_t w2 = f1 - f2;
940 const pixel_t w3 = f2;
941
942 const v3u16_t *restrict base = &lut3d->input[b_base][g_base][r_base];
943 const vec3_t v0 = fn(vec3)(base[0]);
944 const vec3_t v1 = fn(vec3)(base[off0]);
945 const vec3_t v2 = fn(vec3)(base[off0 + off1]);
946 const vec3_t v3 = fn(vec3)(base[off0 + off1 + off2]);
947
948 return (vec3_t) {
949 fn(sum4)(w0, v0.x, w1, v1.x, w2, v2.x, w3, v3.x),
950 fn(sum4)(w0, v0.y, w1, v1.y, w2, v2.y, w3, v3.y),
951 fn(sum4)(w0, v0.z, w1, v1.z, w2, v2.z, w3, v3.z),
952 };
953}
954
955av_always_inline static
956vec3_t fn(lut3d_dynamic)(const SwsLut3D *restrict lut3d, vec3_t rgb)
957{
958 rgb.x *= (pixel_t) ((TONE_LUT_SIZE - 1) / (pixel_t) UINT16_MAX);
959
960 /* Linear interpolation */
961 const int Ix = (int) rgb.x;
962 const pixel_t If = rgb.x - Ix;
963
964 const v2u16_t a = lut3d->tone_map[Ix];
965 const v2u16_t b = lut3d->tone_map[Ix + 1];
966
967 const pixel_t k = lerp(a.y, b.y, If);
968 const pixel_t bias = (1 << 15) - k;
969 const pixel_t scale = k / (pixel_t) (1 << 15);
970
971 rgb.x = lerp(a.x, b.x, If);
972 rgb.y = bias + (pixel_t) (scale * rgb.y);
973 rgb.z = bias + (pixel_t) (scale * rgb.z);
974
975 /* Re-scale to output LUT size */
976 rgb.x *= (pixel_t) ((OUTPUT_LUT_SIZE_I - 1) / (pixel_t) UINT16_MAX);
977 rgb.y *= (pixel_t) ((OUTPUT_LUT_SIZE_PT - 1) / (pixel_t) UINT16_MAX);
978 rgb.z *= (pixel_t) ((OUTPUT_LUT_SIZE_PT - 1) / (pixel_t) UINT16_MAX);
979
980 /* Trilinear interpolation */
981 const int lo0 = (int) rgb.x;
982 const int lo1 = (int) rgb.y;
983 const int lo2 = (int) rgb.z;
984
985 const int hi0 = FFMIN(lo0 + 1, OUTPUT_LUT_SIZE_I - 1);
986 const int hi1 = FFMIN(lo1 + 1, OUTPUT_LUT_SIZE_PT - 1);
987 const int hi2 = FFMIN(lo2 + 1, OUTPUT_LUT_SIZE_PT - 1);
988
989 const pixel_t w0 = rgb.x - lo0;
990 const vec3_t c000 = fn(vec3)(lut3d->output[lo2][lo1][lo0]);
991 const vec3_t c001 = fn(vec3)(lut3d->output[lo2][lo1][hi0]);
992 const vec3_t c00 = fn(lerp3)(c000, c001, w0);
993 const vec3_t c010 = fn(vec3)(lut3d->output[lo2][hi1][lo0]);
994 const vec3_t c011 = fn(vec3)(lut3d->output[lo2][hi1][hi0]);
995 const vec3_t c01 = fn(lerp3)(c010, c011, w0);
996 const vec3_t c100 = fn(vec3)(lut3d->output[hi2][lo1][lo0]);
997 const vec3_t c101 = fn(vec3)(lut3d->output[hi2][lo1][hi0]);
998 const vec3_t c10 = fn(lerp3)(c100, c101, w0);
999 const vec3_t c110 = fn(vec3)(lut3d->output[hi2][hi1][lo0]);
1000 const vec3_t c111 = fn(vec3)(lut3d->output[hi2][hi1][hi0]);
1001 const vec3_t c11 = fn(lerp3)(c110, c111, w0);
1002
1003 const pixel_t w1 = rgb.y - lo1;
1004 const vec3_t c0 = fn(lerp3)(c00, c01, w1);
1005 const vec3_t c1 = fn(lerp3)(c10, c11, w1);
1006
1007 const pixel_t w2 = rgb.z - lo2;
1008 return fn(lerp3)(c0, c1, w2);
1009}
1010
1011DECL_FUNC(lut3d, const SwsCompMask mask, const int dynamic)
1012{
1013 const SwsLut3D *restrict lut3d = impl->priv.ptr;
1014
1015 SWS_LOOP
1016 for (int i = 0; i < SWS_BLOCK_SIZE; i++) {
1017 vec3_t c = { x[i], y[i], z[i] };
1018 c = fn(lut3d_static)(lut3d, c);
1019 if (dynamic)
1020 c = fn(lut3d_dynamic)(lut3d, c);
1021
1022 x[i] = c.x;
1023 y[i] = c.y;
1024 z[i] = c.z;
1025 }
1026
1027 CONTINUE(x, y, z, w);
1028}
1029#endif /* IS_FLOAT */
1030
1031SWS_FOR(PX, LUT_3D, DECL_IMPL, lut3d)
1032SWS_FOR_STRUCT(PX, LUT_3D, DECL_ENTRY, .setup = fn(setup_lut3d) )
1033
1034#undef PIXEL_MAX
1035#undef PIXEL_SWAP
1036#undef pixel_t
1037#undef inter_t
1038#undef uinter_t
1039#undef vec3_t
1040#undef PX
1041#undef px
#define fn(a)
#define ZERO
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t my
Definition dsp.h:67
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t mx
Definition dsp.h:67
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:97
SwsAArch64OpImplParams params
Definition ops.c:51
static double val(void *priv, double ch)
Definition aeval.c:77
static double mz(int i, double w0, double r, double alpha)
Definition af_atilt.c:55
static FILE * out
int32_t
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition avassert.h:68
#define COPY(src, name)
static unsigned int BS_FUNC read_bit(BSCTX *bc)
Return one bit from the buffer.
#define MAX
Definition blend_modes.c:46
#define Y
Definition boxblur.h:37
byte swapping routines
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define xs(width, name, var, subs,...)
Definition cbs_vp9.c:222
#define RSHIFT(a, b)
Definition common.h:56
#define NULL
Definition coverity.c:32
#define min(a, b)
#define max(a, b)
#define SCALE(c)
Definition dcadata.c:7338
#define ADD(a, b)
static void permute(int16_t dst[64], const int16_t src[64], enum idct_permutation_type perm_type)
Definition dct.c:158
static int unpack(const uint8_t *src, const uint8_t *src_end, uint8_t *dst, int width, int height)
Unpack buffer.
Definition eatgv.c:73
double value
Definition eval.c:102
#define X
Definition f_ebur128.c:157
#define AVERROR(e)
Definition error.h:45
void * av_memdup(const void *p, size_t size)
Duplicate a buffer with av_malloc().
Definition mem.c:408
int index
Definition gxfenc.c:90
int a
static const int weights[]
Definition hevc_pel.c:32
static av_always_inline void scale(vec_s32 res[4], vec_s16 res_packed[2], const int shift)
#define b
Definition input.c:43
static int linear(InterplayACMContext *s, unsigned ind, unsigned col)
static int zero(InterplayACMContext *s, unsigned ind, unsigned col)
#define W(a, i, v)
Definition jpegls.h:119
enum MPFType type
Definition jpegmpfenc.c:55
#define ONE
Definition jrevdct.c:137
unsigned offset
Definition libaomenc.c:763
#define av_always_inline
Definition attributes.h:72
@ SWS_FILTER_SCALE
14-bit coefficients are picked to fit comfortably within int16_t for efficient SIMD processing (e....
Definition filters.h:40
@ TONE_LUT_SIZE
Definition lut3d.h:40
@ OUTPUT_LUT_SIZE_I
Definition lut3d.h:46
@ INPUT_LUT_SIZE
Definition lut3d.h:36
@ OUTPUT_LUT_SIZE_PT
Definition lut3d.h:47
uint8_t w
Definition llvidencdsp.c:39
static const uint16_t mask[17]
Definition lzw.c:38
#define FFSWAP(type, a, b)
Definition macros.h:52
#define FFMIN(a, b)
Definition macros.h:49
#define FFMAX(a, b)
Definition macros.h:47
#define FFALIGN(x, a)
Definition macros.h:78
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:370
static const uint64_t c1
Definition murmur3.c:52
const char data[16]
Definition mxf.c:149
int ff_sws_setup_vec4(const SwsImplParams *params, SwsImplResult *out)
Definition ops_chain.c:144
int ff_sws_setup_scalar(const SwsImplParams *params, SwsImplResult *out)
Definition ops_chain.c:129
static void ff_op_priv_unref(SwsOpPriv *priv)
Definition ops_chain.h:141
static void ff_op_priv_free(SwsOpPriv *priv)
Definition ops_chain.h:136
#define av_malloc(s)
Definition ops_static.c:52
static double lerp(double a, double b, double x)
Definition perlin.c:75
#define MIN(a, b)
const void * av_refstruct_ref_c(const void *obj)
Analog of av_refstruct_ref(), but for constant objects.
Definition refstruct.c:150
void * av_refstruct_ref(void *obj)
Create a new reference to an object managed via this API, i.e.
Definition refstruct.c:141
const h264_weight_func weight
Represents a computed filter kernel.
Definition filters.h:85
Copyright (C) 2026 Niklas Haas.
int32_t * in_offset_x
Pixel offset map; for horizontal scaling, in bytes.
ptrdiff_t in_stride[4]
Definition uops.h:293
SwsUOpParams par
Definition uops.h:298
SwsPixel * ptr
Definition uops.h:303
union SwsUOp::@242237116251216327057105100216205033300341206345 data
SwsPixel mat4x5[4][5]
Definition uops.h:306
pixel_t m[4][4]
Definition uops_tmpl.c:806
pixel_t k[4]
Definition uops_tmpl.c:807
Definition rpzaenc.c:60
#define stride
void(* filter)(uint8_t *src, ptrdiff_t stride, int qscale)
Definition h263dsp.c:29
#define src
Definition vp8dsp.c:248
#define height
Definition dsp.h:99
#define PIXEL_MAX
Definition tiny_ssim.c:40
int size
SwsDitherUOp dither
Definition uops.h:289
uint32_t u32[SWS_BLOCK_SIZE]
Definition uops_tmpl.h:47
float f32[SWS_BLOCK_SIZE]
Definition uops_tmpl.h:48
uint16_t u16[SWS_BLOCK_SIZE]
Definition uops_tmpl.h:46
int ff_sws_dither_height(const SwsDitherUOp *dither)
Computes (1 << size_log2) + MAX(y_offset).
Definition uops.c:217
SwsPixelType
Definition uops.h:40
@ SWS_PIXEL_F32
Definition uops.h:45
#define SWS_UOP_MOVE_MAX
Definition uops.h:235
#define SWS_COMP_ELEMS(N)
Definition uops.h:125
uint8_t SwsCompMask
Bit-mask of components.
Definition uops.h:118
#define SWS_FOR(TYPE, UOP, MACRO,...)
Definition uops_macros.h:17
#define SWS_FOR_STRUCT(TYPE, UOP, MACRO,...)
Definition uops_macros.h:19
#define DECL_CAST(DST, dst)
Definition uops_tmpl.c:441
#define LIN_ROW(I, var)
#define DECL_IMPL_WRITE(...)
Definition uops_tmpl.h:138
#define DECL_WRITE(NAME,...)
Definition uops_tmpl.h:104
#define DECL_IMPL_READ(...)
Definition uops_tmpl.h:133
#define CONTINUE(...)
Definition uops_tmpl.h:112
#define Z
Definition uops_tmpl.h:88
#define DECL_FUNC(NAME,...)
Definition uops_tmpl.h:92
#define bump_ptr(ptr, bump)
Definition uops_tmpl.h:83
#define DECL_IMPL(FUNC, NAME, TYPE, UOP,...)
Definition uops_tmpl.h:124
#define SIZEOF_BLOCK
Definition uops_tmpl.h:51
#define SWS_BLOCK_SIZE
Copyright (C) 2026 Niklas Haas.
Definition uops_tmpl.h:41
#define DECL_READ(NAME,...)
Definition uops_tmpl.h:99
#define SWS_LOOP
Definition uops_tmpl.h:73
#define DECL_ENTRY(SETUP, NAME,...)
Definition uops_tmpl.h:144
#define DECL_SETUP(NAME, PARAMS, OUT)
Definition uops_tmpl.h:119
static const uint16_t dither[8][8]
Definition vf_gradfun.c:46
#define LINEAR
static void copy(const float *p1, float *p2, const int length)
uint8_t base
Definition vp3data.h:128
static int bias(int x, int c)
Definition vqcdec.c:115
static double c[64]
#define CLEAR(destin)
Definition wavpackenc.c:50
static int setup_linear(const SwsImplParams *params, SwsImplResult *out)
Definition ops.c:297
static int setup_filter_v(const SwsImplParams *params, SwsImplResult *out)
Definition ops.c:46
static int setup_dither(const SwsImplParams *params, SwsImplResult *out)
Definition ops.c:273
static int setup_filter_h(const SwsImplParams *params, SwsImplResult *out)
Definition ops.c:76