PR #24522 opened by Marcos Ashton (MarcosAsh)
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24522
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24522.patch

Adds a checkasm test for the whole VVCItxDSPContext and AVX2 versions of the 
16, 32 and 64 point inverse DCT2, which were C on every architecture.

The test runs the 1-D transforms with both the column stride and stride 1 and 
random nonzero counts, capped at 32 for DCT2 and 16 for DST7 and DCT8 as 
residual coding zeroes out the rest, which the C code relies on. The input 
range goes up to the 18 bits sps_extended_precision_flag allows, and the output 
is compared over the whole 64x64 block, for add_residual over the padding too, 
so a write past the line or the block fails.

The kernels gather the inputs to the stack and, when they all fit in 16 bits, 
which is always the case without extended precision, accumulate the even and 
odd halves with pmaddwd over word pairs. Otherwise a pmulld path keeps the 
result exact for the full range. Both paths are bit-exact against the C code 
over 300 seeds, and framecrc output is identical with -cpuflags 0 and avx2 on 
14 conformance streams at 8 and 10 bit, including 4:2:2 and monochrome. The 4 
and 8 point transforms come out slower than the C code because of the call 
overhead and are left alone.

checkasm --bench, Core Ultra 7 155H, best of three pinned to one core:

```
stride 1 (row pass)
vvc_inv_dct2_16_c:                            46.7
vvc_inv_dct2_16_avx2:                         27.0 ( 1.73x)
vvc_inv_dct2_32_c:                           197.5
vvc_inv_dct2_32_avx2:                         50.5 ( 3.91x)
vvc_inv_dct2_64_c:                           350.0
vvc_inv_dct2_64_avx2:                         58.9 ( 5.94x)

stride 64 (column pass)
vvc_inv_dct2_16_c:                            48.8
vvc_inv_dct2_16_avx2:                         46.7 ( 1.04x)
vvc_inv_dct2_32_c:                           214.9
vvc_inv_dct2_32_avx2:                         75.6 ( 2.84x)
vvc_inv_dct2_64_c:                           385.7
vvc_inv_dct2_64_avx2:                        112.6 ( 3.43x)
```

A question for the VVC maintainers before I go further with DST7, DCT8 and 
add_residual. itx_2d() calls the 1-D kernel once per column and once per row, 
so every call pays a gather, a range check and a scatter for a single line, and 
that is what caps the column pass at 3x and makes the small sizes not worth it. 
The HEVC and VP9 x86 transforms work on the whole block with in-register 
transposes and a 16-bit intermediate. Would you take a 2-D entry in 
VVCItxDSPContext, per transform pair and size with the two existing loops as 
the C fallback, so the asm can do the same? That would also be the place to 
tell the asm the transform range, since the DSP init only knows the bit depth 
today. If you would rather keep the 1-D interface I can continue with it as is.



>From 93f977f757dd265ef09ec67dbffd94a35d847ef6 Mon Sep 17 00:00:00 2001
From: Marcos Ashton Iglesias <[email protected]>
Date: Tue, 15 Sep 2026 15:58:40 +0100
Subject: [PATCH 1/2] tests/checkasm: add test for vvc itx

Covers the whole VVCItxDSPContext: the 1-D DCT2, DST7 and DCT8 inverse
transforms for every size, add_residual, pred_residual_joint,
transform_bdpcm and adaptive_color_transform at 8, 10 and 12 bit.

The transforms are run with both the column stride and stride 1 and with
random nonzero counts. The count never exceeds 32 for DCT2 and 16 for DST7
and DCT8, which is what residual coding zeroes out, and the C reference
relies on it. The input range covers Log2TransformRange from 15 up to the
18 bits sps_extended_precision_flag allows at 12 bit. Outputs are compared
over the whole 64x64 block, and add_residual over the padding as well, so
a write past the transformed line or the block fails.
---
 tests/checkasm/Makefile   |   2 +-
 tests/checkasm/checkasm.c |   1 +
 tests/checkasm/checkasm.h |   1 +
 tests/checkasm/vvc_itx.c  | 246 ++++++++++++++++++++++++++++++++++++++
 tests/fate/checkasm.mak   |   1 +
 5 files changed, 250 insertions(+), 1 deletion(-)
 create mode 100644 tests/checkasm/vvc_itx.c

diff --git a/tests/checkasm/Makefile b/tests/checkasm/Makefile
index c5b25e753a..d4404bcf49 100644
--- a/tests/checkasm/Makefile
+++ b/tests/checkasm/Makefile
@@ -62,7 +62,7 @@ AVCODECOBJS-$(CONFIG_V210_ENCODER)      += v210enc.o
 AVCODECOBJS-$(CONFIG_VORBIS_DECODER)    += vorbisdsp.o
 AVCODECOBJS-$(CONFIG_VP6_DECODER)       += vp6dsp.o
 AVCODECOBJS-$(CONFIG_VP9_DECODER)       += vp9dsp.o
-AVCODECOBJS-$(CONFIG_VVC_DECODER)       += vvc_alf.o vvc_mc.o vvc_sao.o
+AVCODECOBJS-$(CONFIG_VVC_DECODER)       += vvc_alf.o vvc_itx.o vvc_mc.o 
vvc_sao.o
 
 CHECKASMOBJS-$(CONFIG_AVCODEC)          += $(AVCODECOBJS-yes)
 
diff --git a/tests/checkasm/checkasm.c b/tests/checkasm/checkasm.c
index b9d7b0d2d4..10c728f520 100644
--- a/tests/checkasm/checkasm.c
+++ b/tests/checkasm/checkasm.c
@@ -237,6 +237,7 @@ static const CheckasmTest tests[] = {
     #endif
     #if CONFIG_VVC_DECODER
         { "vvc_alf", checkasm_check_vvc_alf },
+        { "vvc_itx", checkasm_check_vvc_itx },
         { "vvc_mc",  checkasm_check_vvc_mc  },
         { "vvc_sao", checkasm_check_vvc_sao },
     #endif
diff --git a/tests/checkasm/checkasm.h b/tests/checkasm/checkasm.h
index 84fc0b0c08..0e6c02ac10 100644
--- a/tests/checkasm/checkasm.h
+++ b/tests/checkasm/checkasm.h
@@ -126,6 +126,7 @@ void checkasm_check_vp9dsp(void);
 void checkasm_check_videodsp(void);
 void checkasm_check_vorbisdsp(void);
 void checkasm_check_vvc_alf(void);
+void checkasm_check_vvc_itx(void);
 void checkasm_check_vvc_mc(void);
 void checkasm_check_vvc_sao(void);
 
diff --git a/tests/checkasm/vvc_itx.c b/tests/checkasm/vvc_itx.c
new file mode 100644
index 0000000000..a4d8c07e24
--- /dev/null
+++ b/tests/checkasm/vvc_itx.c
@@ -0,0 +1,246 @@
+/*
+ * 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
+ */
+
+#include <string.h>
+
+#include "checkasm.h"
+
+#include "libavcodec/vvc/ctu.h"
+#include "libavcodec/vvc/dsp.h"
+
+#include "libavutil/intreadwrite.h"
+#include "libavutil/mem_internal.h"
+
+static const uint32_t pixel_mask[3] = { 0xffffffff, 0x03ff03ff, 0x0fff0fff };
+
+static const char *const tx_type_name[VVC_N_TX_TYPE] = { "dct2", "dst7", 
"dct8" };
+
+#define SIZEOF_PIXEL ((bit_depth + 7) / 8)
+#define COEFFS       (MAX_TB_SIZE * MAX_TB_SIZE)
+#define COEFFS_BYTES (COEFFS * sizeof(int))
+#define ROW_BYTES    (MAX_TB_SIZE * sizeof(int))
+
+/*
+ * Coefficients reach the transforms clipped to Log2TransformRange, which
+ * is 15 without sps_extended_precision_flag and up to bit_depth + 6 with it.
+ * The reference code is exact for all of them, so asm has to be as well.
+ */
+static const int log2_ranges[] = { 15, 16, 18 };
+
+#define rnd_intp2(log2) ((int)(rnd() % (2u << (log2))) - (1 << (log2)))
+
+static void randomize_ints(int *buf, int n, int log2)
+{
+    for (int i = 0; i < n; i++)
+        buf[i] = rnd_intp2(log2);
+}
+
+#define randomize_pixels(buf, size)                       \
+    do {                                                  \
+        uint32_t mask = pixel_mask[(bit_depth - 8) >> 1]; \
+        for (int k = 0; k < (size); k += 4)               \
+            AV_WN32A((buf) + k, rnd() & mask);            \
+    } while (0)
+
+static void check_coeffs(const int *coeffs0, const int *coeffs1)
+{
+    /* the whole 64x64 block, so a write outside the transformed line fails */
+    checkasm_check(int32_t, coeffs0, ROW_BYTES, coeffs1, ROW_BYTES,
+                   MAX_TB_SIZE, MAX_TB_SIZE, "coeffs");
+}
+
+static void check_itx(const VVCDSPContext *c)
+{
+    LOCAL_ALIGNED_32(int, coeffs0, [COEFFS]);
+    LOCAL_ALIGNED_32(int, coeffs1, [COEFFS]);
+
+    declare_func(void, int *coeffs, ptrdiff_t stride, size_t nz);
+
+    for (int type = 0; type < VVC_N_TX_TYPE; type++) {
+        for (int idx = 0; idx < VVC_N_TX_SIZE; idx++) {
+            const int size = 2 << idx;
+
+            if (!c->itx.itx[type][idx])
+                continue;
+
+            /* residual coding zeroes out coefficients past 32 for DCT2 and
+             * past 16 for DST7 and DCT8, so nz never exceeds that */
+            const int nz_max = FFMIN(size, type == VVC_DCT2 ? 32 : 16);
+
+            if (check_func(c->itx.itx[type][idx], "vvc_inv_%s_%d", 
tx_type_name[type], size)) {
+                for (int r = 0; r < FF_ARRAY_ELEMS(log2_ranges); r++) {
+                    for (int pass = 0; pass < 4; pass++) {
+                        /* the first pass runs down columns with the block 
width
+                         * as stride, the second along rows with stride 1 */
+                        const ptrdiff_t stride = pass & 1 ? 1 : 2 << (rnd() % 
6);
+                        const size_t    nz     = pass < 2 ? nz_max : 1 + rnd() 
% nz_max;
+
+                        randomize_ints(coeffs0, COEFFS, log2_ranges[r]);
+                        for (size_t i = nz; i < size; i++)
+                            coeffs0[i * stride] = 0;
+                        memcpy(coeffs1, coeffs0, COEFFS_BYTES);
+
+                        call_ref(coeffs0, stride, nz);
+                        call_new(coeffs1, stride, nz);
+                        check_coeffs(coeffs0, coeffs1);
+                    }
+                }
+                /* in place, so keep the input in range across the bench 
iterations */
+                memset(coeffs1, 0, COEFFS_BYTES);
+                bench_new(coeffs1, 1, nz_max);
+            }
+        }
+    }
+    report("itx");
+}
+
+static void check_add_residual(const VVCDSPContext *c, int bit_depth)
+{
+    PIXEL_RECT(dst0, MAX_TB_SIZE, MAX_TB_SIZE);
+    PIXEL_RECT(dst1, MAX_TB_SIZE, MAX_TB_SIZE);
+    LOCAL_ALIGNED_32(int, res, [COEFFS]);
+
+    declare_func(void, uint8_t *dst, const int *res, int w, int h, ptrdiff_t 
stride);
+
+    for (int w = 2; w <= MAX_TB_SIZE; w <<= 1) {
+        for (int h = 2; h <= MAX_TB_SIZE; h <<= 1) {
+            if (check_func(c->itx.add_residual, "vvc_add_residual_%dx%d_%d", 
w, h, bit_depth)) {
+                CLEAR_PIXEL_RECT(dst0);
+                CLEAR_PIXEL_RECT(dst1);
+                randomize_pixels(dst0, dst0_stride * h);
+                memcpy(dst1, dst0, dst0_stride * h);
+                /* residuals are the transform output shifted down, which
+                 * can still exceed 16 bits, so it has to be clipped */
+                randomize_ints(res, w * h, 20);
+
+                call_ref(dst0, res, w, h, dst0_stride);
+                call_new(dst1, res, w, h, dst1_stride);
+                checkasm_check_pixel_padded(dst0, dst0_stride, dst1, 
dst1_stride, w, h, "dst");
+
+                if (w == h)
+                    bench_new(dst1, res, w, h, dst1_stride);
+            }
+        }
+    }
+    report("add_residual");
+}
+
+static void check_pred_residual_joint(const VVCDSPContext *c, int bit_depth)
+{
+    LOCAL_ALIGNED_32(int, dst0, [COEFFS]);
+    LOCAL_ALIGNED_32(int, dst1, [COEFFS]);
+    LOCAL_ALIGNED_32(int, src,  [COEFFS]);
+
+    declare_func(void, int *dst, const int *src, int w, int h, int c_sign, int 
shift);
+
+    for (int w = 2; w <= MAX_TB_SIZE; w <<= 1) {
+        for (int h = 2; h <= MAX_TB_SIZE; h <<= 1) {
+            if (check_func(c->itx.pred_residual_joint, 
"vvc_pred_residual_joint_%dx%d_%d",
+                           w, h, bit_depth)) {
+                for (int shift = 0; shift <= 1; shift++) {
+                    for (int c_sign = -1; c_sign <= 1; c_sign += 2) {
+                        randomize_ints(src, COEFFS, 20);
+                        randomize_ints(dst0, COEFFS, 20);
+                        memcpy(dst1, dst0, COEFFS_BYTES);
+
+                        call_ref(dst0, src, w, h, c_sign, shift);
+                        call_new(dst1, src, w, h, c_sign, shift);
+                        check_coeffs(dst0, dst1);
+                    }
+                }
+                if (w == h)
+                    bench_new(dst1, src, w, h, 1, 1);
+            }
+        }
+    }
+    report("pred_residual_joint");
+}
+
+static void check_transform_bdpcm(const VVCDSPContext *c, int bit_depth)
+{
+    LOCAL_ALIGNED_32(int, coeffs0, [COEFFS]);
+    LOCAL_ALIGNED_32(int, coeffs1, [COEFFS]);
+
+    declare_func(void, int *coeffs, int w, int h, int vertical, int 
log2_transform_range);
+
+    for (int vertical = 0; vertical <= 1; vertical++) {
+        for (int w = 4; w <= MAX_TB_SIZE; w <<= 1) {
+            for (int h = 4; h <= MAX_TB_SIZE; h <<= 1) {
+                if (check_func(c->itx.transform_bdpcm, 
"vvc_transform_bdpcm_%s_%dx%d_%d",
+                               vertical ? "v" : "h", w, h, bit_depth)) {
+                    for (int r = 0; r < FF_ARRAY_ELEMS(log2_ranges); r++) {
+                        randomize_ints(coeffs0, COEFFS, log2_ranges[r]);
+                        memcpy(coeffs1, coeffs0, COEFFS_BYTES);
+
+                        call_ref(coeffs0, w, h, vertical, log2_ranges[r]);
+                        call_new(coeffs1, w, h, vertical, log2_ranges[r]);
+                        check_coeffs(coeffs0, coeffs1);
+                    }
+                    if (w == h)
+                        bench_new(coeffs1, w, h, vertical, 15);
+                }
+            }
+        }
+    }
+    report("transform_bdpcm");
+}
+
+static void check_adaptive_color_transform(const VVCDSPContext *c, int 
bit_depth)
+{
+    LOCAL_ALIGNED_32(int, buf0, [3 * COEFFS]);
+    LOCAL_ALIGNED_32(int, buf1, [3 * COEFFS]);
+
+    declare_func(void, int *y, int *u, int *v, int w, int h);
+
+    for (int w = 4; w <= MAX_TB_SIZE; w <<= 1) {
+        for (int h = 4; h <= MAX_TB_SIZE; h <<= 1) {
+            if (check_func(c->itx.adaptive_color_transform, 
"vvc_adaptive_color_transform_%dx%d_%d",
+                           w, h, bit_depth)) {
+                /* the inputs are clipped to bit_depth + 1 bits inside */
+                randomize_ints(buf0, 3 * COEFFS, bit_depth + 2);
+                memcpy(buf1, buf0, 3 * COEFFS_BYTES);
+
+                call_ref(buf0, buf0 + COEFFS, buf0 + 2 * COEFFS, w, h);
+                call_new(buf1, buf1 + COEFFS, buf1 + 2 * COEFFS, w, h);
+                for (int p = 0; p < 3; p++)
+                    check_coeffs(buf0 + p * COEFFS, buf1 + p * COEFFS);
+
+                if (w == h)
+                    bench_new(buf1, buf1 + COEFFS, buf1 + 2 * COEFFS, w, h);
+            }
+        }
+    }
+    report("adaptive_color_transform");
+}
+
+void checkasm_check_vvc_itx(void)
+{
+    VVCDSPContext c = { 0 };
+
+    /* the 1-D transforms do not depend on the bit depth */
+    ff_vvc_dsp_init(&c, 8);
+    check_itx(&c);
+
+    for (int bit_depth = 8; bit_depth <= 12; bit_depth += 2) {
+        ff_vvc_dsp_init(&c, bit_depth);
+        check_add_residual(&c, bit_depth);
+        check_pred_residual_joint(&c, bit_depth);
+        check_transform_bdpcm(&c, bit_depth);
+        check_adaptive_color_transform(&c, bit_depth);
+    }
+}
diff --git a/tests/fate/checkasm.mak b/tests/fate/checkasm.mak
index fad24e5861..3a94d1e507 100644
--- a/tests/fate/checkasm.mak
+++ b/tests/fate/checkasm.mak
@@ -95,6 +95,7 @@ FATE_CHECKASM = fate-checkasm-aacencdsp                       
          \
                 fate-checkasm-vp8dsp                                    \
                 fate-checkasm-vp9dsp                                    \
                 fate-checkasm-vvc_alf                                   \
+                fate-checkasm-vvc_itx                                   \
                 fate-checkasm-vvc_mc                                    \
                 fate-checkasm-vvc_sao                                   \
 
-- 
2.52.0


>From 54cacb1603ff3f1ed132ee31fb5354a5eeb43166 Mon Sep 17 00:00:00 2001
From: Marcos Ashton Iglesias <[email protected]>
Date: Tue, 15 Sep 2026 16:16:27 +0100
Subject: [PATCH 2/2] avcodec/x86/vvc: add AVX2 inverse DCT2 for 16, 32 and 64
 points

The kernels work on one line at a time like the C code, so the only
vectorization available is along the transform. Inputs are gathered to the
stack, and when all of them fit in 16 bits, which is always the case without
sps_extended_precision_flag, the even and odd halves are accumulated with
pmaddwd over word pairs. Otherwise a pmulld path keeps the result exact for
the full 18-bit range. Both are bit-exact against the C code.

The 4 and 8 point transforms are not faster than the C code and are left
alone.

checkasm --bench, Core Ultra 7 155H, best of three, pinned:

stride 1 (row pass)
vvc_inv_dct2_16_c:                            46.7
vvc_inv_dct2_16_avx2:                         27.0 ( 1.73x)
vvc_inv_dct2_32_c:                           197.5
vvc_inv_dct2_32_avx2:                         50.5 ( 3.91x)
vvc_inv_dct2_64_c:                           350.0
vvc_inv_dct2_64_avx2:                         58.9 ( 5.94x)

stride 64 (column pass)
vvc_inv_dct2_16_c:                            48.8
vvc_inv_dct2_16_avx2:                         46.7 ( 1.04x)
vvc_inv_dct2_32_c:                           214.9
vvc_inv_dct2_32_avx2:                         75.6 ( 2.84x)
vvc_inv_dct2_64_c:                           385.7
vvc_inv_dct2_64_avx2:                        112.6 ( 3.43x)
---
 libavcodec/x86/vvc/Makefile   |   1 +
 libavcodec/x86/vvc/dsp_init.c |  19 ++
 libavcodec/x86/vvc/itx.asm    | 435 ++++++++++++++++++++++++++++++++++
 3 files changed, 455 insertions(+)
 create mode 100644 libavcodec/x86/vvc/itx.asm

diff --git a/libavcodec/x86/vvc/Makefile b/libavcodec/x86/vvc/Makefile
index 0cebfb4e9e..860033aaf1 100644
--- a/libavcodec/x86/vvc/Makefile
+++ b/libavcodec/x86/vvc/Makefile
@@ -4,6 +4,7 @@ clean::
 X86ASM-OBJS-$(CONFIG_VVC_DECODER)      += x86/vvc/dsp_init.o        \
                                           x86/vvc/alf.o             \
                                           x86/vvc/dmvr.o            \
+                                          x86/vvc/itx.o             \
                                           x86/vvc/mc.o              \
                                           x86/vvc/of.o              \
                                           x86/vvc/sad.o             \
diff --git a/libavcodec/x86/vvc/dsp_init.c b/libavcodec/x86/vvc/dsp_init.c
index 6802294795..3121e6313b 100644
--- a/libavcodec/x86/vvc/dsp_init.c
+++ b/libavcodec/x86/vvc/dsp_init.c
@@ -297,11 +297,30 @@ void bf(ff_vvc_alf_filter_chroma, bd, opt)(uint8_t *dst, 
ptrdiff_t dst_stride, \
 
 #endif // ARCH_X86_64
 
+#define ITX_PROTOTYPES(opt)                                                    
                                        \
+void ff_vvc_inv_dct2_16_##opt(int *coeffs, ptrdiff_t stride, size_t nz);       
                                        \
+void ff_vvc_inv_dct2_32_##opt(int *coeffs, ptrdiff_t stride, size_t nz);       
                                        \
+void ff_vvc_inv_dct2_64_##opt(int *coeffs, ptrdiff_t stride, size_t nz);
+
+ITX_PROTOTYPES(avx2)
+
+#define ITX_INIT(opt)                                                          
                                        \
+    do {                                                                       
                                        \
+        c->itx.itx[VVC_DCT2][VVC_TX_SIZE_16] = ff_vvc_inv_dct2_16_##opt;       
                                         \
+        c->itx.itx[VVC_DCT2][VVC_TX_SIZE_32] = ff_vvc_inv_dct2_32_##opt;       
                                         \
+        c->itx.itx[VVC_DCT2][VVC_TX_SIZE_64] = ff_vvc_inv_dct2_64_##opt;       
                                         \
+    } while (0)
+
 av_cold void ff_vvc_dsp_init_x86(VVCDSPContext *const c, const int bd)
 {
 #if ARCH_X86_64
     const int cpu_flags = av_get_cpu_flags();
 
+#if HAVE_AVX2_EXTERNAL
+    if (EXTERNAL_AVX2(cpu_flags))
+        ITX_INIT(avx2);
+#endif
+
     switch (bd) {
     case 8:
 #if HAVE_SSE4_EXTERNAL
diff --git a/libavcodec/x86/vvc/itx.asm b/libavcodec/x86/vvc/itx.asm
new file mode 100644
index 0000000000..e47309abbd
--- /dev/null
+++ b/libavcodec/x86/vvc/itx.asm
@@ -0,0 +1,435 @@
+; *****************************************************************************
+; * VVC inverse transform SIMD optimizations
+; *
+; * Copyright (c) 2026 Marcos Ashton Iglesias
+; *
+; * 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
+; *****************************************************************************
+
+%include "libavutil/x86/x86util.asm"
+
+SECTION_RODATA 32
+
+; DCT2 matrix rows, first N/2 columns. Even rows are symmetric and odd rows
+; antisymmetric about the middle, so out[i] = E[i] + O[i] and
+; out[N-1-i] = E[i] - O[i]. Rows above 31 are never used since those inputs
+; are always zero.
+; dct2_N holds dwords, one row per line, for the 32-bit path.
+; dct2w_N holds words, rows (4q, 4q+2) interleaved then (4q+1, 4q+3), for 
pmaddwd.
+dct2_16:
+    dd  64,  64,  64,  64,  64,  64,  64,  64
+    dd  90,  87,  80,  70,  57,  43,  25,   9
+    dd  89,  75,  50,  18, -18, -50, -75, -89
+    dd  87,  57,   9, -43, -80, -90, -70, -25
+    dd  83,  36, -36, -83, -83, -36,  36,  83
+    dd  80,   9, -70, -87, -25,  57,  90,  43
+    dd  75, -18, -89, -50,  50,  89,  18, -75
+    dd  70, -43, -87,   9,  90,  25, -80, -57
+    dd  64, -64, -64,  64,  64, -64, -64,  64
+    dd  57, -80, -25,  90,  -9, -87,  43,  70
+    dd  50, -89,  18,  75, -75, -18,  89, -50
+    dd  43, -90,  57,  25, -87,  70,   9, -80
+    dd  36, -83,  83, -36, -36,  83, -83,  36
+    dd  25, -70,  90, -80,  43,   9, -57,  87
+    dd  18, -50,  75, -89,  89, -75,  50, -18
+    dd   9, -25,  43, -57,  70, -80,  87, -90
+dct2_32:
+    dd  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  64,  
64,  64
+    dd  90,  90,  88,  85,  82,  78,  73,  67,  61,  54,  46,  38,  31,  22,  
13,   4
+    dd  90,  87,  80,  70,  57,  43,  25,   9,  -9, -25, -43, -57, -70, -80, 
-87, -90
+    dd  90,  82,  67,  46,  22,  -4, -31, -54, -73, -85, -90, -88, -78, -61, 
-38, -13
+    dd  89,  75,  50,  18, -18, -50, -75, -89, -89, -75, -50, -18,  18,  50,  
75,  89
+    dd  88,  67,  31, -13, -54, -82, -90, -78, -46,  -4,  38,  73,  90,  85,  
61,  22
+    dd  87,  57,   9, -43, -80, -90, -70, -25,  25,  70,  90,  80,  43,  -9, 
-57, -87
+    dd  85,  46, -13, -67, -90, -73, -22,  38,  82,  88,  54,  -4, -61, -90, 
-78, -31
+    dd  83,  36, -36, -83, -83, -36,  36,  83,  83,  36, -36, -83, -83, -36,  
36,  83
+    dd  82,  22, -54, -90, -61,  13,  78,  85,  31, -46, -90, -67,   4,  73,  
88,  38
+    dd  80,   9, -70, -87, -25,  57,  90,  43, -43, -90, -57,  25,  87,  70,  
-9, -80
+    dd  78,  -4, -82, -73,  13,  85,  67, -22, -88, -61,  31,  90,  54, -38, 
-90, -46
+    dd  75, -18, -89, -50,  50,  89,  18, -75, -75,  18,  89,  50, -50, -89, 
-18,  75
+    dd  73, -31, -90, -22,  78,  67, -38, -90, -13,  82,  61, -46, -88,  -4,  
85,  54
+    dd  70, -43, -87,   9,  90,  25, -80, -57,  57,  80, -25, -90,  -9,  87,  
43, -70
+    dd  67, -54, -78,  38,  85, -22, -90,   4,  90,  13, -88, -31,  82,  46, 
-73, -61
+    dd  64, -64, -64,  64,  64, -64, -64,  64,  64, -64, -64,  64,  64, -64, 
-64,  64
+    dd  61, -73, -46,  82,  31, -88, -13,  90,  -4, -90,  22,  85, -38, -78,  
54,  67
+    dd  57, -80, -25,  90,  -9, -87,  43,  70, -70, -43,  87,   9, -90,  25,  
80, -57
+    dd  54, -85,  -4,  88, -46, -61,  82,  13, -90,  38,  67, -78, -22,  90, 
-31, -73
+    dd  50, -89,  18,  75, -75, -18,  89, -50, -50,  89, -18, -75,  75,  18, 
-89,  50
+    dd  46, -90,  38,  54, -90,  31,  61, -88,  22,  67, -85,  13,  73, -82,   
4,  78
+    dd  43, -90,  57,  25, -87,  70,   9, -80,  80,  -9, -70,  87, -25, -57,  
90, -43
+    dd  38, -88,  73,  -4, -67,  90, -46, -31,  85, -78,  13,  61, -90,  54,  
22, -82
+    dd  36, -83,  83, -36, -36,  83, -83,  36,  36, -83,  83, -36, -36,  83, 
-83,  36
+    dd  31, -78,  90, -61,   4,  54, -88,  82, -38, -22,  73, -90,  67, -13, 
-46,  85
+    dd  25, -70,  90, -80,  43,   9, -57,  87, -87,  57,  -9, -43,  80, -90,  
70, -25
+    dd  22, -61,  85, -90,  73, -38,  -4,  46, -78,  90, -82,  54, -13, -31,  
67, -88
+    dd  18, -50,  75, -89,  89, -75,  50, -18, -18,  50, -75,  89, -89,  75, 
-50,  18
+    dd  13, -38,  61, -78,  88, -90,  85, -73,  54, -31,   4,  22, -46,  67, 
-82,  90
+    dd   9, -25,  43, -57,  70, -80,  87, -90,  90, -87,  80, -70,  57, -43,  
25,  -9
+    dd   4, -13,  22, -31,  38, -46,  54, -61,  67, -73,  78, -82,  85, -88,  
90, -90
+dct2_64:
+    dd 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+    dd 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+    dd 91, 90, 90, 90, 88, 87, 86, 84, 83, 81, 79, 77, 73, 71, 69, 65
+    dd 62, 59, 56, 52, 48, 44, 41, 37, 33, 28, 24, 20, 15, 11, 7, 2
+    dd 90, 90, 88, 85, 82, 78, 73, 67, 61, 54, 46, 38, 31, 22, 13, 4
+    dd -4, -13, -22, -31, -38, -46, -54, -61, -67, -73, -78, -82, -85, -88, 
-90, -90
+    dd 90, 88, 84, 79, 71, 62, 52, 41, 28, 15, 2, -11, -24, -37, -48, -59
+    dd -69, -77, -83, -87, -90, -91, -90, -86, -81, -73, -65, -56, -44, -33, 
-20, -7
+    dd 90, 87, 80, 70, 57, 43, 25, 9, -9, -25, -43, -57, -70, -80, -87, -90
+    dd -90, -87, -80, -70, -57, -43, -25, -9, 9, 25, 43, 57, 70, 80, 87, 90
+    dd 90, 84, 73, 59, 41, 20, -2, -24, -44, -62, -77, -86, -90, -90, -83, -71
+    dd -56, -37, -15, 7, 28, 48, 65, 79, 87, 91, 88, 81, 69, 52, 33, 11
+    dd 90, 82, 67, 46, 22, -4, -31, -54, -73, -85, -90, -88, -78, -61, -38, -13
+    dd 13, 38, 61, 78, 88, 90, 85, 73, 54, 31, 4, -22, -46, -67, -82, -90
+    dd 90, 79, 59, 33, 2, -28, -56, -77, -88, -90, -81, -62, -37, -7, 24, 52
+    dd 73, 87, 90, 83, 65, 41, 11, -20, -48, -71, -86, -91, -84, -69, -44, -15
+    dd 89, 75, 50, 18, -18, -50, -75, -89, -89, -75, -50, -18, 18, 50, 75, 89
+    dd 89, 75, 50, 18, -18, -50, -75, -89, -89, -75, -50, -18, 18, 50, 75, 89
+    dd 88, 71, 41, 2, -37, -69, -87, -90, -73, -44, -7, 33, 65, 86, 90, 77
+    dd 48, 11, -28, -62, -84, -90, -79, -52, -15, 24, 59, 83, 91, 81, 56, 20
+    dd 88, 67, 31, -13, -54, -82, -90, -78, -46, -4, 38, 73, 90, 85, 61, 22
+    dd -22, -61, -85, -90, -73, -38, 4, 46, 78, 90, 82, 54, 13, -31, -67, -88
+    dd 87, 62, 20, -28, -69, -90, -84, -56, -11, 37, 73, 90, 81, 48, 2, -44
+    dd -79, -91, -77, -41, 7, 52, 83, 90, 71, 33, -15, -59, -86, -88, -65, -24
+    dd 87, 57, 9, -43, -80, -90, -70, -25, 25, 70, 90, 80, 43, -9, -57, -87
+    dd -87, -57, -9, 43, 80, 90, 70, 25, -25, -70, -90, -80, -43, 9, 57, 87
+    dd 86, 52, -2, -56, -87, -84, -48, 7, 59, 88, 83, 44, -11, -62, -90, -81
+    dd -41, 15, 65, 90, 79, 37, -20, -69, -90, -77, -33, 24, 71, 91, 73, 28
+    dd 85, 46, -13, -67, -90, -73, -22, 38, 82, 88, 54, -4, -61, -90, -78, -31
+    dd 31, 78, 90, 61, 4, -54, -88, -82, -38, 22, 73, 90, 67, 13, -46, -85
+    dd 84, 41, -24, -77, -90, -56, 7, 65, 91, 69, 11, -52, -88, -79, -28, 37
+    dd 83, 86, 44, -20, -73, -90, -59, 2, 62, 90, 71, 15, -48, -87, -81, -33
+    dd 83, 36, -36, -83, -83, -36, 36, 83, 83, 36, -36, -83, -83, -36, 36, 83
+    dd 83, 36, -36, -83, -83, -36, 36, 83, 83, 36, -36, -83, -83, -36, 36, 83
+    dd 83, 28, -44, -88, -73, -11, 59, 91, 62, -7, -71, -90, -48, 24, 81, 84
+    dd 33, -41, -87, -77, -15, 56, 90, 65, -2, -69, -90, -52, 20, 79, 86, 37
+    dd 82, 22, -54, -90, -61, 13, 78, 85, 31, -46, -90, -67, 4, 73, 88, 38
+    dd -38, -88, -73, -4, 67, 90, 46, -31, -85, -78, -13, 61, 90, 54, -22, -82
+    dd 81, 15, -62, -90, -44, 37, 88, 69, -7, -77, -84, -24, 56, 91, 52, -28
+    dd -86, -73, -2, 71, 87, 33, -48, -90, -59, 20, 83, 79, 11, -65, -90, -41
+    dd 80, 9, -70, -87, -25, 57, 90, 43, -43, -90, -57, 25, 87, 70, -9, -80
+    dd -80, -9, 70, 87, 25, -57, -90, -43, 43, 90, 57, -25, -87, -70, 9, 80
+    dd 79, 2, -77, -81, -7, 73, 83, 11, -71, -84, -15, 69, 86, 20, -65, -87
+    dd -24, 62, 88, 28, -59, -90, -33, 56, 90, 37, -52, -90, -41, 48, 91, 44
+    dd 78, -4, -82, -73, 13, 85, 67, -22, -88, -61, 31, 90, 54, -38, -90, -46
+    dd 46, 90, 38, -54, -90, -31, 61, 88, 22, -67, -85, -13, 73, 82, 4, -78
+    dd 77, -11, -86, -62, 33, 90, 44, -52, -90, -24, 69, 83, 2, -81, -71, 20
+    dd 88, 56, -41, -91, -37, 59, 87, 15, -73, -79, 7, 84, 65, -28, -90, -48
+    dd 75, -18, -89, -50, 50, 89, 18, -75, -75, 18, 89, 50, -50, -89, -18, 75
+    dd 75, -18, -89, -50, 50, 89, 18, -75, -75, 18, 89, 50, -50, -89, -18, 75
+    dd 73, -24, -90, -37, 65, 81, -11, -88, -48, 56, 86, 2, -84, -59, 44, 90
+    dd 15, -79, -69, 33, 91, 28, -71, -77, 20, 90, 41, -62, -83, 7, 87, 52
+    dd 73, -31, -90, -22, 78, 67, -38, -90, -13, 82, 61, -46, -88, -4, 85, 54
+    dd -54, -85, 4, 88, 46, -61, -82, 13, 90, 38, -67, -78, 22, 90, 31, -73
+    dd 71, -37, -90, -7, 86, 48, -62, -79, 24, 91, 20, -81, -59, 52, 84, -11
+    dd -90, -33, 73, 69, -41, -88, -2, 87, 44, -65, -77, 28, 90, 15, -83, -56
+    dd 70, -43, -87, 9, 90, 25, -80, -57, 57, 80, -25, -90, -9, 87, 43, -70
+    dd -70, 43, 87, -9, -90, -25, 80, 57, -57, -80, 25, 90, 9, -87, -43, 70
+    dd 69, -48, -83, 24, 90, 2, -90, -28, 81, 52, -65, -71, 44, 84, -20, -90
+    dd -7, 88, 33, -79, -56, 62, 73, -41, -86, 15, 91, 11, -87, -37, 77, 59
+    dd 67, -54, -78, 38, 85, -22, -90, 4, 90, 13, -88, -31, 82, 46, -73, -61
+    dd 61, 73, -46, -82, 31, 88, -13, -90, -4, 90, 22, -85, -38, 78, 54, -67
+    dd 65, -59, -71, 52, 77, -44, -81, 37, 84, -28, -87, 20, 90, -11, -90, 2
+    dd 91, 7, -90, -15, 88, 24, -86, -33, 83, 41, -79, -48, 73, 56, -69, -62
+dct2w_16:
+    dw  64,  89,  64,  75,  64,  50,  64,  18,  64, -18,  64, -50,  64, -75,  
64, -89
+    dw  90,  87,  87,  57,  80,   9,  70, -43,  57, -80,  43, -90,  25, -70,   
9, -25
+    dw  83,  75,  36, -18, -36, -89, -83, -50, -83,  50, -36,  89,  36,  18,  
83, -75
+    dw  80,  70,   9, -43, -70, -87, -87,   9, -25,  90,  57,  25,  90, -80,  
43, -57
+    dw  64,  50, -64, -89, -64,  18,  64,  75,  64, -75, -64, -18, -64,  89,  
64, -50
+    dw  57,  43, -80, -90, -25,  57,  90,  25,  -9, -87, -87,  70,  43,   9,  
70, -80
+    dw  36,  18, -83, -50,  83,  75, -36, -89, -36,  89,  83, -75, -83,  50,  
36, -18
+    dw  25,   9, -70, -25,  90,  43, -80, -57,  43,  70,   9, -80, -57,  87,  
87, -90
+dct2w_32:
+    dw 64, 90, 64, 87, 64, 80, 64, 70, 64, 57, 64, 43, 64, 25, 64, 9
+    dw 64, -9, 64, -25, 64, -43, 64, -57, 64, -70, 64, -80, 64, -87, 64, -90
+    dw 90, 90, 90, 82, 88, 67, 85, 46, 82, 22, 78, -4, 73, -31, 67, -54
+    dw 61, -73, 54, -85, 46, -90, 38, -88, 31, -78, 22, -61, 13, -38, 4, -13
+    dw 89, 87, 75, 57, 50, 9, 18, -43, -18, -80, -50, -90, -75, -70, -89, -25
+    dw -89, 25, -75, 70, -50, 90, -18, 80, 18, 43, 50, -9, 75, -57, 89, -87
+    dw 88, 85, 67, 46, 31, -13, -13, -67, -54, -90, -82, -73, -90, -22, -78, 38
+    dw -46, 82, -4, 88, 38, 54, 73, -4, 90, -61, 85, -90, 61, -78, 22, -31
+    dw 83, 80, 36, 9, -36, -70, -83, -87, -83, -25, -36, 57, 36, 90, 83, 43
+    dw 83, -43, 36, -90, -36, -57, -83, 25, -83, 87, -36, 70, 36, -9, 83, -80
+    dw 82, 78, 22, -4, -54, -82, -90, -73, -61, 13, 13, 85, 78, 67, 85, -22
+    dw 31, -88, -46, -61, -90, 31, -67, 90, 4, 54, 73, -38, 88, -90, 38, -46
+    dw 75, 70, -18, -43, -89, -87, -50, 9, 50, 90, 89, 25, 18, -80, -75, -57
+    dw -75, 57, 18, 80, 89, -25, 50, -90, -50, -9, -89, 87, -18, 43, 75, -70
+    dw 73, 67, -31, -54, -90, -78, -22, 38, 78, 85, 67, -22, -38, -90, -90, 4
+    dw -13, 90, 82, 13, 61, -88, -46, -31, -88, 82, -4, 46, 85, -73, 54, -61
+    dw 64, 57, -64, -80, -64, -25, 64, 90, 64, -9, -64, -87, -64, 43, 64, 70
+    dw 64, -70, -64, -43, -64, 87, 64, 9, 64, -90, -64, 25, -64, 80, 64, -57
+    dw 61, 54, -73, -85, -46, -4, 82, 88, 31, -46, -88, -61, -13, 82, 90, 13
+    dw -4, -90, -90, 38, 22, 67, 85, -78, -38, -22, -78, 90, 54, -31, 67, -73
+    dw 50, 43, -89, -90, 18, 57, 75, 25, -75, -87, -18, 70, 89, 9, -50, -80
+    dw -50, 80, 89, -9, -18, -70, -75, 87, 75, -25, 18, -57, -89, 90, 50, -43
+    dw 46, 38, -90, -88, 38, 73, 54, -4, -90, -67, 31, 90, 61, -46, -88, -31
+    dw 22, 85, 67, -78, -85, 13, 13, 61, 73, -90, -82, 54, 4, 22, 78, -82
+    dw 36, 25, -83, -70, 83, 90, -36, -80, -36, 43, 83, 9, -83, -57, 36, 87
+    dw 36, -87, -83, 57, 83, -9, -36, -43, -36, 80, 83, -90, -83, 70, 36, -25
+    dw 31, 22, -78, -61, 90, 85, -61, -90, 4, 73, 54, -38, -88, -4, 82, 46
+    dw -38, -78, -22, 90, 73, -82, -90, 54, 67, -13, -13, -31, -46, 67, 85, -88
+    dw 18, 9, -50, -25, 75, 43, -89, -57, 89, 70, -75, -80, 50, 87, -18, -90
+    dw -18, 90, 50, -87, -75, 80, 89, -70, -89, 57, 75, -43, -50, 25, 18, -9
+    dw 13, 4, -38, -13, 61, 22, -78, -31, 88, 38, -90, -46, 85, 54, -73, -61
+    dw 54, 67, -31, -73, 4, 78, 22, -82, -46, 85, 67, -88, -82, 90, 90, -90
+dct2w_64:
+    dw 64, 90, 64, 90, 64, 88, 64, 85, 64, 82, 64, 78, 64, 73, 64, 67
+    dw 64, 61, 64, 54, 64, 46, 64, 38, 64, 31, 64, 22, 64, 13, 64, 4
+    dw 64, -4, 64, -13, 64, -22, 64, -31, 64, -38, 64, -46, 64, -54, 64, -61
+    dw 64, -67, 64, -73, 64, -78, 64, -82, 64, -85, 64, -88, 64, -90, 64, -90
+    dw 91, 90, 90, 88, 90, 84, 90, 79, 88, 71, 87, 62, 86, 52, 84, 41
+    dw 83, 28, 81, 15, 79, 2, 77, -11, 73, -24, 71, -37, 69, -48, 65, -59
+    dw 62, -69, 59, -77, 56, -83, 52, -87, 48, -90, 44, -91, 41, -90, 37, -86
+    dw 33, -81, 28, -73, 24, -65, 20, -56, 15, -44, 11, -33, 7, -20, 2, -7
+    dw 90, 90, 87, 82, 80, 67, 70, 46, 57, 22, 43, -4, 25, -31, 9, -54
+    dw -9, -73, -25, -85, -43, -90, -57, -88, -70, -78, -80, -61, -87, -38, 
-90, -13
+    dw -90, 13, -87, 38, -80, 61, -70, 78, -57, 88, -43, 90, -25, 85, -9, 73
+    dw 9, 54, 25, 31, 43, 4, 57, -22, 70, -46, 80, -67, 87, -82, 90, -90
+    dw 90, 90, 84, 79, 73, 59, 59, 33, 41, 2, 20, -28, -2, -56, -24, -77
+    dw -44, -88, -62, -90, -77, -81, -86, -62, -90, -37, -90, -7, -83, 24, 
-71, 52
+    dw -56, 73, -37, 87, -15, 90, 7, 83, 28, 65, 48, 41, 65, 11, 79, -20
+    dw 87, -48, 91, -71, 88, -86, 81, -91, 69, -84, 52, -69, 33, -44, 11, -15
+    dw 89, 88, 75, 67, 50, 31, 18, -13, -18, -54, -50, -82, -75, -90, -89, -78
+    dw -89, -46, -75, -4, -50, 38, -18, 73, 18, 90, 50, 85, 75, 61, 89, 22
+    dw 89, -22, 75, -61, 50, -85, 18, -90, -18, -73, -50, -38, -75, 4, -89, 46
+    dw -89, 78, -75, 90, -50, 82, -18, 54, 18, 13, 50, -31, 75, -67, 89, -88
+    dw 88, 87, 71, 62, 41, 20, 2, -28, -37, -69, -69, -90, -87, -84, -90, -56
+    dw -73, -11, -44, 37, -7, 73, 33, 90, 65, 81, 86, 48, 90, 2, 77, -44
+    dw 48, -79, 11, -91, -28, -77, -62, -41, -84, 7, -90, 52, -79, 83, -52, 90
+    dw -15, 71, 24, 33, 59, -15, 83, -59, 91, -86, 81, -88, 56, -65, 20, -24
+    dw 87, 85, 57, 46, 9, -13, -43, -67, -80, -90, -90, -73, -70, -22, -25, 38
+    dw 25, 82, 70, 88, 90, 54, 80, -4, 43, -61, -9, -90, -57, -78, -87, -31
+    dw -87, 31, -57, 78, -9, 90, 43, 61, 80, 4, 90, -54, 70, -88, 25, -82
+    dw -25, -38, -70, 22, -90, 73, -80, 90, -43, 67, 9, 13, 57, -46, 87, -85
+    dw 86, 84, 52, 41, -2, -24, -56, -77, -87, -90, -84, -56, -48, 7, 7, 65
+    dw 59, 91, 88, 69, 83, 11, 44, -52, -11, -88, -62, -79, -90, -28, -81, 37
+    dw -41, 83, 15, 86, 65, 44, 90, -20, 79, -73, 37, -90, -20, -59, -69, 2
+    dw -90, 62, -77, 90, -33, 71, 24, 15, 71, -48, 91, -87, 73, -81, 28, -33
+    dw 83, 82, 36, 22, -36, -54, -83, -90, -83, -61, -36, 13, 36, 78, 83, 85
+    dw 83, 31, 36, -46, -36, -90, -83, -67, -83, 4, -36, 73, 36, 88, 83, 38
+    dw 83, -38, 36, -88, -36, -73, -83, -4, -83, 67, -36, 90, 36, 46, 83, -31
+    dw 83, -85, 36, -78, -36, -13, -83, 61, -83, 90, -36, 54, 36, -22, 83, -82
+    dw 83, 81, 28, 15, -44, -62, -88, -90, -73, -44, -11, 37, 59, 88, 91, 69
+    dw 62, -7, -7, -77, -71, -84, -90, -24, -48, 56, 24, 91, 81, 52, 84, -28
+    dw 33, -86, -41, -73, -87, -2, -77, 71, -15, 87, 56, 33, 90, -48, 65, -90
+    dw -2, -59, -69, 20, -90, 83, -52, 79, 20, 11, 79, -65, 86, -90, 37, -41
+    dw 80, 78, 9, -4, -70, -82, -87, -73, -25, 13, 57, 85, 90, 67, 43, -22
+    dw -43, -88, -90, -61, -57, 31, 25, 90, 87, 54, 70, -38, -9, -90, -80, -46
+    dw -80, 46, -9, 90, 70, 38, 87, -54, 25, -90, -57, -31, -90, 61, -43, 88
+    dw 43, 22, 90, -67, 57, -85, -25, -13, -87, 73, -70, 82, 9, 4, 80, -78
+    dw 79, 77, 2, -11, -77, -86, -81, -62, -7, 33, 73, 90, 83, 44, 11, -52
+    dw -71, -90, -84, -24, -15, 69, 69, 83, 86, 2, 20, -81, -65, -71, -87, 20
+    dw -24, 88, 62, 56, 88, -41, 28, -91, -59, -37, -90, 59, -33, 87, 56, 15
+    dw 90, -73, 37, -79, -52, 7, -90, 84, -41, 65, 48, -28, 91, -90, 44, -48
+    dw 75, 73, -18, -31, -89, -90, -50, -22, 50, 78, 89, 67, 18, -38, -75, -90
+    dw -75, -13, 18, 82, 89, 61, 50, -46, -50, -88, -89, -4, -18, 85, 75, 54
+    dw 75, -54, -18, -85, -89, 4, -50, 88, 50, 46, 89, -61, 18, -82, -75, 13
+    dw -75, 90, 18, 38, 89, -67, 50, -78, -50, 22, -89, 90, -18, 31, 75, -73
+    dw 73, 71, -24, -37, -90, -90, -37, -7, 65, 86, 81, 48, -11, -62, -88, -79
+    dw -48, 24, 56, 91, 86, 20, 2, -81, -84, -59, -59, 52, 44, 84, 90, -11
+    dw 15, -90, -79, -33, -69, 73, 33, 69, 91, -41, 28, -88, -71, -2, -77, 87
+    dw 20, 44, 90, -65, 41, -77, -62, 28, -83, 90, 7, 15, 87, -83, 52, -56
+    dw 70, 67, -43, -54, -87, -78, 9, 38, 90, 85, 25, -22, -80, -90, -57, 4
+    dw 57, 90, 80, 13, -25, -88, -90, -31, -9, 82, 87, 46, 43, -73, -70, -61
+    dw -70, 61, 43, 73, 87, -46, -9, -82, -90, 31, -25, 88, 80, -13, 57, -90
+    dw -57, -4, -80, 90, 25, 22, 90, -85, 9, -38, -87, 78, -43, 54, 70, -67
+    dw 69, 65, -48, -59, -83, -71, 24, 52, 90, 77, 2, -44, -90, -81, -28, 37
+    dw 81, 84, 52, -28, -65, -87, -71, 20, 44, 90, 84, -11, -20, -90, -90, 2
+    dw -7, 91, 88, 7, 33, -90, -79, -15, -56, 88, 62, 24, 73, -86, -41, -33
+    dw -86, 83, 15, 41, 91, -79, 11, -48, -87, 73, -37, 56, 77, -69, 59, -62
+
+perm_rev: dd 7, 6, 5, 4, 3, 2, 1, 0
+pd_32768: dd 32768
+
+SECTION .text
+
+%if ARCH_X86_64
+
+; store the lanes of m%1 to [%2] with step %3, %4 = 3 * %3, %5 is a scratch 
register
+%macro SCATTER 5
+    vextracti128 xm %+ %5, m %+ %1, 1
+    movd     [%2], xm %+ %1
+    pextrd   [%2 + %3], xm %+ %1, 1
+    pextrd   [%2 + %3 * 2], xm %+ %1, 2
+    pextrd   [%2 + %4], xm %+ %1, 3
+    lea        %2, [%2 + %3 * 4]
+    movd     [%2], xm %+ %5
+    pextrd   [%2 + %3], xm %+ %5, 1
+    pextrd   [%2 + %3 * 2], xm %+ %5, 2
+    pextrd   [%2 + %4], xm %+ %5, 3
+    lea        %2, [%2 + %3 * 4]
+%endmacro
+
+; m%1.. += m%2 * [tabq + %3..], %4 = pmulld or pmaddwd
+%macro ACCUM 4
+%assign %%v 0
+%rep V
+%assign %%a %1 + %%v
+    %4        m %+ P, m %+ %2, [tabq + %3 + %%v * mmsize]
+    paddd     m %+ %%a, m %+ P
+%assign %%v %%v + 1
+%endrep
+%endmacro
+
+;-----------------------------------------------------------------------------
+; void ff_vvc_inv_dct2_N(int *coeffs, ptrdiff_t stride, size_t nz)
+;-----------------------------------------------------------------------------
+; %1 = N, %2 = vector registers per half, %3 = stack bytes for N + 8 inputs
+; m0.. accumulate E, m%2.. accumulate O
+%macro INV_DCT2 3
+%assign V     %2
+%assign ROW   (%1 / 2) * 4
+%assign B     2 * V
+%assign B2    2 * V + 1
+%assign P     2 * V + 2
+cglobal vvc_inv_dct2_%1, 3, 8, 2 * V + 3, %3, coeffs, stride, nz, tab, cnt, 
dst, tmp, val
+    shl      strideq, 2
+    mov         dstq, coeffsq
+    lea         tabq, [nzq + 7]
+    shr         tabq, 3
+    cmp      strideq, 4
+    jne .gather
+    xor         tmpd, tmpd
+.copy:
+    movu          m0, [coeffsq + tmpq]
+    movu  [rsp + tmpq], m0
+    add         tmpq, mmsize
+    dec         tabq
+    jnz .copy
+    jmp .check
+.gather:
+    lea         tabq, [strideq * 3]
+    lea         cntq, [nzq + 3]
+    shr         cntq, 2
+    mov         tmpq, rsp
+.gather_loop:
+    mov         vald, [coeffsq]
+    mov       [tmpq], vald
+    mov         vald, [coeffsq + strideq]
+    mov   [tmpq + 4], vald
+    mov         vald, [coeffsq + strideq * 2]
+    mov   [tmpq + 8], vald
+    mov         vald, [coeffsq + tabq]
+    mov  [tmpq + 12], vald
+    lea      coeffsq, [coeffsq + strideq * 4]
+    add         tmpq, 16
+    dec         cntq
+    jnz .gather_loop
+.check:
+    pxor          m0, m0
+    movu [rsp + nzq * 4], m0
+    ; take the 16-bit path when every input fits in a word
+    vpbroadcastd  m1, [pd_32768]
+    lea         cntq, [nzq + 7]
+    shr         cntq, 3
+    xor         tmpd, tmpd
+.check_loop:
+    paddd         m2, m1, [rsp + tmpq]
+    por           m0, m2
+    add         tmpq, mmsize
+    dec         cntq
+    jnz .check_loop
+    psrld         m0, 16
+    ptest         m0, m0
+    jnz .wide
+%assign %%v 0
+%rep 2 * V
+    pxor      m %+ %%v, m %+ %%v
+%assign %%v %%v + 1
+%endrep
+    lea         cntq, [nzq + 3]
+    shr         cntq, 2
+    lea         tabq, [dct2w_%1]
+    mov      coeffsq, rsp
+.quad:
+    movu         xm %+ B, [coeffsq]
+    pshufd       xm %+ B, xm %+ B, q3120
+    packssdw     xm %+ B, xm %+ B
+    vpbroadcastq  m %+ B, xm %+ B
+    pshufd        m %+ B2, m %+ B, q1111
+    pshufd        m %+ B, m %+ B, q0000
+    ACCUM 0, B, 0, pmaddwd
+    ACCUM V, B2, ROW, pmaddwd
+    add      coeffsq, 16
+    add         tabq, 2 * ROW
+    dec         cntq
+    jnz .quad
+    jmp .sum
+.wide:
+%assign %%v 0
+%rep 2 * V
+    pxor      m %+ %%v, m %+ %%v
+%assign %%v %%v + 1
+%endrep
+    lea         cntq, [nzq + 1]
+    shr         cntq, 1
+    lea         tabq, [dct2_%1]
+    mov      coeffsq, rsp
+.pair:
+    vpbroadcastd  m %+ B, [coeffsq]
+    vpbroadcastd  m %+ B2, [coeffsq + 4]
+    ACCUM 0, B, 0, pmulld
+    ACCUM V, B2, ROW, pmulld
+    add      coeffsq, 8
+    add         tabq, 2 * ROW
+    dec         cntq
+    jnz .pair
+.sum:
+%assign %%v 0
+%rep V
+%assign %%o V + %%v
+    psubd     m %+ P, m %+ %%v, m %+ %%o
+    paddd     m %+ %%v, m %+ %%o
+    mova      m %+ %%o, m %+ P
+%assign %%v %%v + 1
+%endrep
+    cmp      strideq, 4
+    jne .scatter
+    mova      m %+ B, [perm_rev]
+%assign %%v 0
+%rep V
+%assign %%o V + %%v
+    movu   [dstq + %%v * mmsize], m %+ %%v
+    vpermd    m %+ %%o, m %+ B, m %+ %%o
+    movu   [dstq + %1 * 4 - (%%v + 1) * mmsize], m %+ %%o
+%assign %%v %%v + 1
+%endrep
+    RET
+.scatter:
+    imul        cntq, strideq, %1 - 1
+    add         cntq, dstq
+    mov         tmpq, strideq
+    neg         tmpq
+    lea         tabq, [strideq * 3]
+    lea         valq, [tmpq * 3]
+%assign %%v 0
+%rep V
+%assign %%o V + %%v
+    SCATTER   %%v, dstq, strideq, tabq, P
+    SCATTER   %%o, cntq, tmpq, valq, P
+%assign %%v %%v + 1
+%endrep
+    RET
+%endmacro
+
+INIT_YMM avx2
+INV_DCT2 16, 1, 96
+INV_DCT2 32, 2, 160
+INV_DCT2 64, 4, 288
+
+%endif ; ARCH_X86_64
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to