Commit 9d2d5b1aa3 for ffmpeg

commit 9d2d5b1aa39a714ad92cd3dd0253bd3aa7ee8be7
Author: Mark Thompson <sw@jkqxz.net>
Date:   Fri Oct 16 20:13:00 2026 +0000

    lavc/apv: aarch64 NEON APV decode transquant

    CPU: ARM Cortex-A53
      decode_transquant_10_c:       966.4
      decode_transquant_10_neon:    292.7 ( 3.30x)
    CPU: ARM Cortex-A73
      decode_transquant_10_c:       898.4
      decode_transquant_10_neon:    253.4 ( 3.55x)

diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile
index 0fe117748f..06bbb9152f 100644
--- a/libavcodec/aarch64/Makefile
+++ b/libavcodec/aarch64/Makefile
@@ -23,6 +23,7 @@ OBJS-$(CONFIG_VP8DSP)                   += aarch64/vp8dsp_init_aarch64.o
 OBJS-$(CONFIG_AAC_DECODER)              += aarch64/aacpsdsp_init_aarch64.o \
                                            aarch64/sbrdsp_init_aarch64.o
 OBJS-$(CONFIG_AAC_ENCODER)              += aarch64/aacencdsp_init.o
+OBJS-$(CONFIG_APV_DECODER)              += aarch64/apv_dsp_init_aarch64.o
 OBJS-$(CONFIG_BITPACKED_DECODER)        += aarch64/bitpacked_init_aarch64.o
 OBJS-$(CONFIG_DCA_DECODER)              += aarch64/dcadsp_init_aarch64.o \
                                            aarch64/synth_filter_init.o
@@ -69,6 +70,7 @@ NEON-OBJS-$(CONFIG_VP8DSP)              += aarch64/vp8dsp_neon.o

 # decoders/encoders
 NEON-OBJS-$(CONFIG_AAC_DECODER)         += aarch64/aacpsdsp_neon.o
+NEON-OBJS-$(CONFIG_APV_DECODER)         += aarch64/apv_dsp_neon.o
 NEON-OBJS-$(CONFIG_BITPACKED_DECODER)   += aarch64/bitpacked_neon.o
 NEON-OBJS-$(CONFIG_DCA_DECODER)         += aarch64/dcadsp_neon.o             \
                                            aarch64/synth_filter_neon.o
diff --git a/libavcodec/aarch64/apv_dsp_init_aarch64.c b/libavcodec/aarch64/apv_dsp_init_aarch64.c
new file mode 100644
index 0000000000..22d4598f91
--- /dev/null
+++ b/libavcodec/aarch64/apv_dsp_init_aarch64.c
@@ -0,0 +1,38 @@
+/*
+ * 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 "config.h"
+#include "libavutil/attributes.h"
+#include "libavutil/cpu.h"
+#include "libavutil/aarch64/cpu.h"
+#include "libavcodec/apv_dsp.h"
+
+void ff_apv_decode_transquant_neon(void *output,
+                                   ptrdiff_t pitch,
+                                   const int16_t *input,
+                                   const int16_t *qmatrix,
+                                   int bit_depth,
+                                   int qp_shift);
+
+av_cold void ff_apv_dsp_init_aarch64(APVDSPContext *dsp)
+{
+    int cpu_flags = av_get_cpu_flags();
+
+    if (have_neon(cpu_flags))
+        dsp->decode_transquant = ff_apv_decode_transquant_neon;
+}
diff --git a/libavcodec/aarch64/apv_dsp_neon.S b/libavcodec/aarch64/apv_dsp_neon.S
new file mode 100644
index 0000000000..3110a4f6fb
--- /dev/null
+++ b/libavcodec/aarch64/apv_dsp_neon.S
@@ -0,0 +1,342 @@
+/*
+ * 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/aarch64/asm.S"
+#include "neon.S"
+
+/* Dequant one row in 16x8
+ * Input levels at x2 + off, qmatrix at x3 + off (function args)
+ * Output row in out vector
+ */
+.macro dequant out, off
+        ldr             q16, [x2, \off]
+        ldr             q17, [x3, \off]
+        smull           v18.4s, v16.4h, v17.4h
+        smull2          v19.4s, v16.8h, v17.8h
+        sshl            v18.4s, v18.4s, v24.4s
+        sshl            v19.4s, v19.4s, v24.4s
+        add             v18.4s, v18.4s, v25.4s
+        add             v19.4s, v19.4s, v25.4s
+        sshl            v18.4s, v18.4s, v26.4s
+        sshl            v19.4s, v19.4s, v26.4s
+        sqxtn           \out\().4h, v18.4s
+        sqxtn2          \out\().8h, v19.4s
+.endm
+
+
+/* Vertical butterfly of 8x16x8 -> 16x32x4
+ * Input rows in v0-v7
+ * Output rows in pairs v16-v23
+ */
+.macro butterfly_mul
+        movi            v16.8h, #64
+        mvni            v17.8h, #63 /* -64 */
+        movi            v18.8h, #84
+        movi            v19.8h, #35
+        mvni            v20.8h, #83 /* -84 */
+        smull           v24.4s, v0.4h, v16.4h
+        smlal           v24.4s, v4.4h, v16.4h
+        smull2          v25.4s, v0.8h, v16.8h
+        smlal2          v25.4s, v4.8h, v16.8h
+        smull           v26.4s, v0.4h, v16.4h
+        smlal           v26.4s, v4.4h, v17.4h
+        smull2          v27.4s, v0.8h, v16.8h
+        smlal2          v27.4s, v4.8h, v17.8h
+        smull           v28.4s, v2.4h, v18.4h
+        smlal           v28.4s, v6.4h, v19.4h
+        smull2          v29.4s, v2.8h, v18.8h
+        smlal2          v29.4s, v6.8h, v19.8h
+        smull           v30.4s, v2.4h, v19.4h
+        smlal           v30.4s, v6.4h, v20.4h
+        smull2          v31.4s, v2.8h, v19.8h
+        smlal2          v31.4s, v6.8h, v20.8h
+        movi            v0.8h, #89
+        movi            v2.8h, #75
+        movi            v4.8h, #50
+        movi            v6.8h, #18
+        smull           v16.4s, v1.4h, v0.4h
+        smull2          v17.4s, v1.8h, v0.8h
+        smlal           v16.4s, v3.4h, v2.4h
+        smlal2          v17.4s, v3.8h, v2.8h
+        smlal           v16.4s, v5.4h, v4.4h
+        smlal2          v17.4s, v5.8h, v4.8h
+        smlal           v16.4s, v7.4h, v6.4h
+        smlal2          v17.4s, v7.8h, v6.8h
+        smull           v18.4s, v1.4h, v2.4h
+        smull2          v19.4s, v1.8h, v2.8h
+        smull           v20.4s, v1.4h, v4.4h
+        smull2          v21.4s, v1.8h, v4.8h
+        smlal           v20.4s, v5.4h, v6.4h
+        smlal2          v21.4s, v5.8h, v6.8h
+        smlal           v20.4s, v7.4h, v2.4h
+        smlal2          v21.4s, v7.8h, v2.8h
+        smull           v22.4s, v1.4h, v6.4h
+        smull2          v23.4s, v1.8h, v6.8h
+        smlal           v22.4s, v5.4h, v2.4h
+        smlal2          v23.4s, v5.8h, v2.8h
+        mvni            v0.8h, #17 /* -18 */
+        mvni            v2.8h, #88 /* -89 */
+        mvni            v4.8h, #49 /* -50 */
+        smlal           v18.4s, v3.4h, v0.4h
+        smlal2          v19.4s, v3.8h, v0.8h
+        smlal           v18.4s, v5.4h, v2.4h
+        smlal2          v19.4s, v5.8h, v2.8h
+        smlal           v18.4s, v7.4h, v4.4h
+        smlal2          v19.4s, v7.8h, v4.8h
+        smlal           v20.4s, v3.4h, v2.4h
+        smlal2          v21.4s, v3.8h, v2.8h
+        smlal           v22.4s, v3.4h, v4.4h
+        smlal2          v23.4s, v3.8h, v4.8h
+        smlal           v22.4s, v7.4h, v2.4h
+        smlal2          v23.4s, v7.8h, v2.8h
+.endm
+
+/* Column combine and renormalise 16x32x4 -> 8x16x8
+ * Input rows in pairs v16-v31
+ * Output rows in v0-v7
+ */
+.macro col_combine
+        add             v2.4s, v24.4s, v28.4s
+        add             v3.4s, v25.4s, v29.4s
+        add             v0.4s, v16.4s, v2.4s
+        add             v4.4s, v17.4s, v3.4s
+        sqrshrn         v0.4h, v0.4s, #7
+        sqrshrn2        v0.8h, v4.4s, #7
+        sub             v7.4s, v2.4s, v16.4s
+        sub             v4.4s, v3.4s, v17.4s
+        sqrshrn         v7.4h, v7.4s, #7
+        sqrshrn2        v7.8h, v4.4s, #7
+        sub             v2.4s, v24.4s, v28.4s
+        sub             v1.4s, v25.4s, v29.4s
+        add             v3.4s, v22.4s, v2.4s
+        add             v4.4s, v23.4s, v1.4s
+        sqrshrn         v3.4h, v3.4s, #7
+        sqrshrn2        v3.8h, v4.4s, #7
+        sub             v4.4s, v2.4s, v22.4s
+        sub             v1.4s, v1.4s, v23.4s
+        sqrshrn         v4.4h, v4.4s, #7
+        sqrshrn2        v4.8h, v1.4s, #7
+        add             v2.4s, v26.4s, v30.4s
+        add             v1.4s, v27.4s, v31.4s
+        add             v17.4s, v19.4s, v1.4s
+        add             v1.4s,  v18.4s, v2.4s
+        sqrshrn         v1.4h, v1.4s,  #7
+        sqrshrn2        v1.8h, v17.4s, #7
+        sub             v6.4s, v2.4s, v18.4s
+        add             v17.4s, v27.4s, v31.4s
+        sub             v17.4s, v17.4s, v19.4s
+        sqrshrn         v6.4h, v6.4s,  #7
+        sqrshrn2        v6.8h, v17.4s, #7
+        sub             v2.4s,  v26.4s, v30.4s
+        sub             v18.4s, v27.4s, v31.4s
+        add             v2.4s,  v20.4s, v2.4s
+        add             v18.4s, v21.4s, v18.4s
+        sqrshrn         v2.4h, v2.4s,  #7
+        sqrshrn2        v2.8h, v18.4s, #7
+        sub             v5.4s,  v26.4s, v30.4s
+        sub             v5.4s,  v5.4s,  v20.4s
+        sub             v18.4s, v27.4s, v31.4s
+        sub             v18.4s, v18.4s, v21.4s
+        sqrshrn         v5.4h, v5.4s,  #7
+        sqrshrn2        v5.8h, v18.4s, #7
+.endm
+
+/* Row combine and output scaling 16x32x4 -> 8x16x8
+ * Input rows in pairs v16-v31
+ * Output rows in v0-v7
+ */
+.macro row_combine
+        movi            v1.4s, #0
+        dup             v7.4s, w17
+        add             v2.4s, v24.4s, v28.4s
+        add             v3.4s, v25.4s, v29.4s
+        add             v0.4s, v16.4s, v2.4s
+        add             v4.4s, v17.4s, v3.4s
+        add             v0.4s, v0.4s,  v5.4s
+        add             v4.4s, v4.4s,  v5.4s
+        sshl            v0.4s, v0.4s, v7.4s
+        sshl            v4.4s, v4.4s, v7.4s
+        smin            v0.4s, v0.4s, v6.4s
+        smin            v4.4s, v4.4s, v6.4s
+        smax            v0.4s, v0.4s, v1.4s
+        smax            v4.4s, v4.4s, v1.4s
+        uqxtn           v0.4h, v0.4s
+        uqxtn2          v0.8h, v4.4s
+        sub             v4.4s, v3.4s, v17.4s
+        sub             v7.4s, v2.4s, v16.4s
+        dup             v16.4s, w17
+        add             v7.4s, v7.4s, v5.4s
+        add             v4.4s, v4.4s, v5.4s
+        sshl            v7.4s, v7.4s, v16.4s
+        sshl            v4.4s, v4.4s, v16.4s
+        smin            v7.4s, v7.4s, v6.4s
+        smin            v4.4s, v4.4s, v6.4s
+        smax            v7.4s, v7.4s, v1.4s
+        smax            v4.4s, v4.4s, v1.4s
+        uqxtn           v7.4h, v7.4s
+        uqxtn2          v7.8h, v4.4s
+        sub             v2.4s,  v24.4s, v28.4s
+        sub             v17.4s, v25.4s, v29.4s
+        add             v3.4s,  v22.4s, v2.4s
+        add             v17.4s, v23.4s, v17.4s
+        add             v3.4s,  v3.4s,  v5.4s
+        add             v17.4s, v17.4s, v5.4s
+        sshl            v3.4s,  v3.4s,  v16.4s
+        sshl            v17.4s, v17.4s, v16.4s
+        smin            v3.4s,  v3.4s,  v6.4s
+        smin            v17.4s, v17.4s, v6.4s
+        smax            v3.4s,  v3.4s,  v1.4s
+        smax            v17.4s, v17.4s, v1.4s
+        uqxtn           v3.4h, v3.4s
+        uqxtn2          v3.8h, v17.4s
+        sub             v4.4s,  v2.4s,  v22.4s
+        sub             v17.4s, v25.4s, v29.4s
+        sub             v17.4s, v17.4s, v23.4s
+        add             v4.4s,  v4.4s,  v5.4s
+        add             v17.4s, v17.4s, v5.4s
+        sshl            v4.4s,  v4.4s,  v16.4s
+        sshl            v17.4s, v17.4s, v16.4s
+        smin            v4.4s,  v4.4s,  v6.4s
+        smin            v17.4s, v17.4s, v6.4s
+        smax            v4.4s,  v4.4s,  v1.4s
+        smax            v17.4s, v17.4s, v1.4s
+        uqxtn           v4.4h, v4.4s
+        uqxtn2          v4.8h, v17.4s
+        dup             v28.4s, w10
+        dup             v29.4s, w13
+        sub             v22.4s, v29.4s, v29.4s
+        add             v2.4s, v26.4s, v30.4s
+        add             v1.4s, v27.4s, v31.4s
+        add             v17.4s, v19.4s, v1.4s
+        add             v1.4s,  v18.4s, v2.4s
+        add             v1.4s,  v1.4s,  v28.4s
+        add             v17.4s, v17.4s, v28.4s
+        sshl            v1.4s,  v1.4s,  v16.4s
+        sshl            v17.4s, v17.4s, v16.4s
+        smin            v1.4s,  v1.4s,  v29.4s
+        smin            v17.4s, v17.4s, v29.4s
+        smax            v1.4s,  v1.4s,  v22.4s
+        smax            v17.4s, v17.4s, v22.4s
+        uqxtn           v1.4h, v1.4s
+        uqxtn2          v1.8h, v17.4s
+        sub             v6.4s, v2.4s, v18.4s
+        add             v17.4s, v27.4s, v31.4s
+        sub             v17.4s, v17.4s, v19.4s
+        add             v6.4s,  v6.4s,  v28.4s
+        add             v17.4s, v17.4s, v28.4s
+        sshl            v6.4s,  v6.4s,  v16.4s
+        sshl            v17.4s, v17.4s, v16.4s
+        smin            v6.4s,  v6.4s,  v29.4s
+        smin            v17.4s, v17.4s, v29.4s
+        smax            v6.4s,  v6.4s,  v22.4s
+        smax            v17.4s, v17.4s, v22.4s
+        uqxtn           v6.4h, v6.4s
+        uqxtn2          v6.8h, v17.4s
+        sub             v2.4s,  v26.4s, v30.4s
+        sub             v18.4s, v27.4s, v31.4s
+        add             v17.4s, v21.4s, v18.4s
+        add             v2.4s,  v20.4s, v2.4s
+        add             v2.4s,  v2.4s,  v28.4s
+        add             v17.4s, v17.4s, v28.4s
+        sshl            v2.4s,  v2.4s,  v16.4s
+        sshl            v17.4s, v17.4s, v16.4s
+        smin            v2.4s,  v2.4s,  v29.4s
+        smin            v17.4s, v17.4s, v29.4s
+        smax            v2.4s,  v2.4s,  v22.4s
+        smax            v17.4s, v17.4s, v22.4s
+        uqxtn           v2.4h, v2.4s
+        uqxtn2          v2.8h, v17.4s
+        sub             v18.4s, v27.4s, v31.4s
+        sub             v18.4s, v18.4s, v21.4s
+        sub             v5.4s,  v26.4s, v30.4s
+        sub             v5.4s,  v5.4s,  v20.4s
+        add             v5.4s,  v5.4s,  v28.4s
+        add             v18.4s, v18.4s, v28.4s
+        sshl            v5.4s,  v5.4s,  v16.4s
+        sshl            v18.4s, v18.4s, v16.4s
+        smin            v5.4s,  v5.4s,  v29.4s
+        smin            v18.4s, v18.4s, v29.4s
+        smax            v5.4s,  v5.4s,  v22.4s
+        smax            v18.4s, v18.4s, v22.4s
+        uqxtn           v5.4h, v5.4s
+        uqxtn2          v5.8h, v18.4s
+.endm
+
+/*
+ * void ff_apv_decode_transquant_neon(void *output,           = x0
+ *                                    ptrdiff_t pitch,        = x1
+ *                                    const int16_t *input,   = x2
+ *                                    const int16_t *qmatrix, = x3
+ *                                    int bit_depth,          = w4
+ *                                    int qp_shift)           = w5
+ */
+function ff_apv_decode_transquant_neon, export=1
+        sub             w7, w4, #2       /* w7 = bd_shift */
+        movz            w14, #1
+
+        /* Dequant */
+        sub             w15, w7, #1
+        lsl             w10, w14, w15
+        neg             w15, w7
+        dup             v24.4s, w5       /* v24 = qp_shift */
+        dup             v25.4s, w10      /* v25 = 1 << (bd_shift - 1) */
+        dup             v26.4s, w15      /* v26 = -bd_shift */
+        dequant         v0, #0
+        dequant         v1, #16
+        dequant         v2, #32
+        dequant         v3, #48
+        dequant         v4, #64
+        dequant         v5, #80
+        dequant         v6, #96
+        dequant         v7, #112
+
+        /* Row scaling constants */
+        movz            w16, #8, lsl #16 /* w16 = 1 << 19 */
+        lsr             w10, w16, w4
+        orr             w10, w10, w16    /* w10 = (1 << (19 - bit_depth)) + (1 << 19) */
+        lsl             w15, w14, w4
+        sub             w13, w15, #1     /* w13 = (1 << bit_depth) - 1 */
+
+        /* Column butterfly and normalise */
+        butterfly_mul
+        col_combine
+
+        /* Transpose */
+        transpose_8x8H  v0, v1, v2, v3, v4, v5, v6, v7, v16, v17
+
+        /* Row butterfly and output scaling */
+        butterfly_mul
+        dup             v5.4s, w10       /* v5 = output offset */
+        dup             v6.4s, w13       /* v6 = output max clip (min clip is zero) */
+        sub             w17, w4, #20     /* w17 = bit_depth - 20 (row_combine shift) */
+        row_combine
+
+        /* Transpose back */
+        transpose_8x8H  v0, v1, v2, v3, v4, v5, v6, v7, v16, v17
+
+        /* Store output */
+        st1             {v0.16b}, [x0], x1
+        st1             {v1.16b}, [x0], x1
+        st1             {v2.16b}, [x0], x1
+        st1             {v3.16b}, [x0], x1
+        st1             {v4.16b}, [x0], x1
+        st1             {v5.16b}, [x0], x1
+        st1             {v6.16b}, [x0], x1
+        st1             {v7.16b}, [x0]
+        ret
+endfunc
diff --git a/libavcodec/apv_dsp.c b/libavcodec/apv_dsp.c
index 22446d25a4..7351e34b6a 100644
--- a/libavcodec/apv_dsp.c
+++ b/libavcodec/apv_dsp.c
@@ -124,4 +124,7 @@ av_cold void ff_apv_dsp_init(APVDSPContext *dsp)
 #if ARCH_X86_64 && HAVE_X86ASM
     ff_apv_dsp_init_x86_64(dsp);
 #endif
+#if ARCH_AARCH64
+    ff_apv_dsp_init_aarch64(dsp);
+#endif
 }
diff --git a/libavcodec/apv_dsp.h b/libavcodec/apv_dsp.h
index c63d6a88ee..c0836f3e2c 100644
--- a/libavcodec/apv_dsp.h
+++ b/libavcodec/apv_dsp.h
@@ -36,4 +36,6 @@ void ff_apv_dsp_init(APVDSPContext *dsp);

 void ff_apv_dsp_init_x86_64(APVDSPContext *dsp);

+void ff_apv_dsp_init_aarch64(APVDSPContext *dsp);
+
 #endif /* AVCODEC_APV_DSP_H */