This is an automated email from the git hooks/post-receive script. Git pushed a commit to branch master in repository ffmpeg.
commit 098dd9f46a4962bfe6c50bbb7bc0d05db1a39843 Author: Devin Heitmueller <[email protected]> AuthorDate: Wed Sep 16 14:50:28 2026 -0400 Commit: Martin Storsjö <[email protected]> CommitDate: Thu Oct 15 18:46:02 2026 +0000 avcodec/bitpacked: add AArch64 NEON unpacking Unpack packed 10-bit YUV 4:2:2 in 16-pixel NEON blocks and unroll the main loop to 32 pixels. Keep exact-width source loads and use the scalar implementation for decoder tails smaller than eight pixels. Enable the optimized implementation on little-endian AArch64. Retain the C fallback on big-endian AArch64, where the byte layout expected by this implementation does not apply. The implementation passed 300 consecutive checkasm repetitions and produced bit-exact output in a 100-frame UHD decode. Thanks to Martin Storsjö for feedback and suggestions for improvement. Correctness command: ./tests/checkasm/checkasm --test=bitpackeddec --repeat=300 66000 Benchmark command: ./tests/checkasm/checkasm --bench --test=bitpackeddec \ --function=bitpacked_unpack_yuv422p10 --duration=1000000 95000 Apple M4 Mac mini, Apple clang 17.0.0: bitpacked_unpack_yuv422p10_c: 876.8 ns bitpacked_unpack_yuv422p10_neon: 227.2 ns (3.86x) Clang auto-vectorizes the C reference with NEON, so the result measures the hand-written implementation against compiler-generated SIMD rather than against purely scalar machine code. --- libavcodec/aarch64/Makefile | 2 + .../{opusdsp_init.c => bitpacked_init_aarch64.c} | 20 ++-- libavcodec/aarch64/bitpacked_neon.S | 102 +++++++++++++++++++++ libavcodec/bitpacked_dec.h | 2 + libavcodec/bitpacked_dec_init.h | 3 + 5 files changed, 120 insertions(+), 9 deletions(-) diff --git a/libavcodec/aarch64/Makefile b/libavcodec/aarch64/Makefile index e0762e3fa1..b1ceb36668 100644 --- a/libavcodec/aarch64/Makefile +++ b/libavcodec/aarch64/Makefile @@ -21,6 +21,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_BITPACKED_DECODER) += aarch64/bitpacked_init_aarch64.o OBJS-$(CONFIG_DCA_DECODER) += aarch64/dcadsp_init_aarch64.o \ aarch64/synth_filter_init.o OBJS-$(CONFIG_OPUS_DECODER) += aarch64/opusdsp_init.o @@ -64,6 +65,7 @@ NEON-OBJS-$(CONFIG_VP8DSP) += aarch64/vp8dsp_neon.o # decoders/encoders NEON-OBJS-$(CONFIG_AAC_DECODER) += aarch64/aacpsdsp_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 NEON-OBJS-$(CONFIG_OPUS_DECODER) += aarch64/opusdsp_neon.o diff --git a/libavcodec/aarch64/opusdsp_init.c b/libavcodec/aarch64/bitpacked_init_aarch64.c similarity index 64% copy from libavcodec/aarch64/opusdsp_init.c copy to libavcodec/aarch64/bitpacked_init_aarch64.c index 5452ea6240..a9c875a5b0 100644 --- a/libavcodec/aarch64/opusdsp_init.c +++ b/libavcodec/aarch64/bitpacked_init_aarch64.c @@ -1,4 +1,6 @@ /* + * Copyright (c) 2026 Devin Heitmueller <[email protected]> + * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or @@ -16,21 +18,21 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "config.h" +#include <stdint.h> +#include "config.h" #include "libavutil/attributes.h" #include "libavutil/aarch64/cpu.h" -#include "libavcodec/opus/dsp.h" +#include "libavcodec/bitpacked_dec.h" -void ff_opus_postfilter_neon(float *data, int period, float *gains, int len); -float ff_opus_deemphasis_neon(float *out, float *in, float coeff, const float *weights, int len); +void ff_bitpacked_unpack_yuv422p10_neon(const uint8_t *src, + uint16_t *y, uint16_t *u, uint16_t *v, + int width); -av_cold void ff_opus_dsp_init_aarch64(OpusDSP *ctx) +av_cold void ff_bitpacked_init_aarch64(struct BitpackedContext *s) { int cpu_flags = av_get_cpu_flags(); - if (have_neon(cpu_flags)) { - ctx->postfilter = ff_opus_postfilter_neon; - ctx->deemphasis = ff_opus_deemphasis_neon; - } + if (!HAVE_BIGENDIAN && have_neon(cpu_flags)) + s->unpack_yuv422p10 = ff_bitpacked_unpack_yuv422p10_neon; } diff --git a/libavcodec/aarch64/bitpacked_neon.S b/libavcodec/aarch64/bitpacked_neon.S new file mode 100644 index 0000000000..f7bbd51b85 --- /dev/null +++ b/libavcodec/aarch64/bitpacked_neon.S @@ -0,0 +1,102 @@ +/* + * Bitpacked 10-bit YUV 4:2:2 unpacking + * Copyright (c) 2026 Devin Heitmueller <[email protected]> + * + * 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" + +const bitpacked_tbl, align=4 + // Byte-pair indices for Y samples 0-7 and 8-15. + .byte 2, 1, 4, 3, 7, 6, 9, 8, 12, 11, 14, 13, 17, 16, 19, 18 + .byte 22, 21, 24, 23, 27, 26, 29, 28 + .byte 32, 31, 34, 33, 37, 36, 39, 38 + // Byte-pair indices for the U and V samples. + .byte 1, 0, 6, 5, 11, 10, 16, 15, 21, 20, 26, 25, 31, 30, 36, 35 + .byte 3, 2, 8, 7, 13, 12, 18, 17, 23, 22, 28, 27, 33, 32, 38, 37 + // Per-lane multipliers align the alternating Y fields. + .hword 4, 64, 4, 64, 4, 64, 4, 64 +endconst + +// Consume 40 bytes and produce 16 Y, 8 U and 8 V samples. TBL reverses +// each big-endian byte pair; 16-bit multiply/shift overflow discards unwanted +// high bits before the common right shift. The main loop unrolls to 80 bytes. +.macro unpack_16 + ld1 {v0.16b, v1.16b}, [x0] + ldr d2, [x0, #32] + add x0, x0, #40 + + tbl v3.16b, {v0.16b-v2.16b}, v16.16b + tbl v4.16b, {v0.16b-v2.16b}, v17.16b + tbl v5.16b, {v0.16b-v2.16b}, v18.16b + tbl v6.16b, {v0.16b-v2.16b}, v19.16b + + mul v3.8h, v3.8h, v20.8h + mul v4.8h, v4.8h, v20.8h + shl v6.8h, v6.8h, #4 + ushr v3.8h, v3.8h, #6 + ushr v4.8h, v4.8h, #6 + ushr v5.8h, v5.8h, #6 + ushr v6.8h, v6.8h, #6 + + st1 {v3.8h, v4.8h}, [x1], #32 + str q5, [x2], #16 + str q6, [x3], #16 +.endm + +// ff_bitpacked_unpack_yuv422p10_neon(const uint8_t *src, +// uint16_t *y, uint16_t *u, uint16_t *v, +// int width) +function ff_bitpacked_unpack_yuv422p10_neon, export=1 + movrel x5, bitpacked_tbl + ld1 {v16.16b-v19.16b}, [x5], #64 + ldr q20, [x5] + + subs w4, w4, #32 + b.lt 2f + +1: unpack_16 + unpack_16 + subs w4, w4, #32 + b.ge 1b + +2: add w4, w4, #32 + tbz w4, #4, 3f + unpack_16 + sub w4, w4, #16 + +3: cbz w4, 4f + ldr q0, [x0], #16 + ldr s1, [x0] + + tbl v3.16b, {v0.16b-v1.16b}, v16.16b + tbl v5.16b, {v0.16b-v1.16b}, v18.16b + tbl v6.16b, {v0.16b-v1.16b}, v19.16b + + mul v3.8h, v3.8h, v20.8h + shl v6.8h, v6.8h, #4 + ushr v3.8h, v3.8h, #6 + ushr v5.8h, v5.8h, #6 + ushr v6.8h, v6.8h, #6 + + str q3, [x1] + str d5, [x2] + str d6, [x3] + +4: ret +endfunc diff --git a/libavcodec/bitpacked_dec.h b/libavcodec/bitpacked_dec.h index a92c94ab29..637f3789ef 100644 --- a/libavcodec/bitpacked_dec.h +++ b/libavcodec/bitpacked_dec.h @@ -36,4 +36,6 @@ struct BitpackedContext { int width); }; +void ff_bitpacked_init_aarch64(struct BitpackedContext *s); + #endif /* AVCODEC_BITPACKED_DEC_H */ diff --git a/libavcodec/bitpacked_dec_init.h b/libavcodec/bitpacked_dec_init.h index a7a0d257c3..f0b19f04fa 100644 --- a/libavcodec/bitpacked_dec_init.h +++ b/libavcodec/bitpacked_dec_init.h @@ -46,6 +46,9 @@ av_unused static av_cold void ff_bitpackeddec_init(struct BitpackedContext *s) { s->unpack_yuv422p10 = bitpacked_unpack_yuv422p10_c; +#if ARCH_AARCH64 + ff_bitpacked_init_aarch64(s); +#endif } #endif /* AVCODEC_BITPACKED_DEC_INIT_H */ -- To stop receiving notification emails like this one, please contact [email protected]. _______________________________________________ ffmpeg-cvslog mailing list -- [email protected] To unsubscribe send an email to [email protected]
