533 Commits
Author SHA1 Message Date
Jeongkeun Kim 8105ae2afe avcodec/aarch64: add NEON lfe_fir_fixed for DCA DSP
Add a NEON implementation of the fixed-point DCA LFE FIR interpolation
filter.

Each vector lane holds one of four consecutive LFE samples, so the
filter coefficients are used as by-element multipliers and can be
loaded contiguously without any permutes. One load of c[8j..8j+7] and
c[248-8j..255-8j] covers outputs j, 32+j, 31-j and 63-j. The 8-tap
sums are accumulated in 64 bits with SMULL/SMLAL, rounded with SQRSHRN,
clipped to 23 bits with SQSHL/SSHR and written with ST2 lane stores.

Recent clang versions auto-vectorize the C version, so the speedup
depends a lot on the compiler. On Neoverse-N1 (64 LFE samples):

  C compiler   speedup
  clang 14     4.84x
  gcc 11       1.75x
  clang 20     1.21x
  clang 22     1.21x

Signed-off-by: Jeongkeun Kim <variety0724@gmail.com>
2026-11-05 21:16:11 +00:00
Gyula Sebok ea4162f223 avcodec/aarch64: Add NEON llviddsp left and gradient prediction
Like the x86 versions, these may read and write past the end, here by
up to 15 bytes. The main loops process eight vectors per iteration;
with four, the in-order Cortex-A510 stalls on the latency of the prefix
sums, and add_left_pred_int16 was only 1.25x faster than C there.

checkasm --bench (CPU cycles via perf), seed 12345 (width 983), on a
Dimensity 9000:

                            Cortex-X2      Cortex-A710    Cortex-A510
add_gradient_pred_c:         2138.4         2183.6         4450.3
add_gradient_pred_neon:       225.7 (9.48x)  380.3 (5.74x)  711.6 (6.25x)
add_left_pred_int16_c:       1926.4         1941.4         2112.0
add_left_pred_int16_neon:     370.6 (5.20x)  630.6 (3.08x) 1058.6 (2.00x)
add_left_pred_rnd_acc_c:     1056.5         1029.6         1743.4
add_left_pred_rnd_acc_neon:   201.9 (5.23x)  347.5 (2.96x)  585.2 (2.98x)
add_left_pred_zero_c:        1056.0         1029.2         1742.3
add_left_pred_zero_neon:      201.8 (5.23x)  347.5 (2.96x)  585.2 (2.98x)

and on a Google Tensor (Pixel 6a):

                            Cortex-X1      Cortex-A76     Cortex-A55
add_gradient_pred_c:         2137.4         2848.2         6892.2
add_gradient_pred_neon:       238.2 (8.97x)  408.2 (6.98x) 1117.5 (6.17x)
add_left_pred_int16_c:       1935.0         2177.2         3950.8
add_left_pred_int16_neon:     398.0 (4.86x)  664.4 (3.28x) 1690.0 (2.34x)
add_left_pred_rnd_acc_c:     1059.7         1533.9         2967.1
add_left_pred_rnd_acc_neon:   214.5 (4.94x)  378.2 (4.06x)  925.4 (3.21x)
add_left_pred_zero_c:        1059.8         1533.9         2967.1
add_left_pred_zero_neon:      214.5 (4.94x)  378.2 (4.06x)  925.4 (3.21x)

Signed-off-by: Gyula Sebok <gyula.sbk@gmail.com>
2026-11-03 18:33:02 +00:00
Gyula Sebok fa59c23a59 aarch64/sbrdsp: rewrite hf_gen to remove faddp reduction
The original implementation was slower than C on all tested cores.

The new version computes 8 outputs per iteration. The caller always
passes even start and end, which the x86 version also relies on, so
the tail only handles 4 and 2 outputs.

checkasm --bench (cycles, median of 7 runs). A55/A76/X1: Pixel 6a,
A510/A710/X2: Vivo Pad 2.

clang         c   neon_original      neon_new
A55         900    2303 (0.39x)   576 (1.56x)
A76         302     550 (0.55x)   204 (1.48x)
X1          173     322 (0.54x)   109 (1.59x)
A510        952    2398 (0.40x)   459 (2.07x)
A710        262     498 (0.53x)   194 (1.35x)
X2          169     298 (0.57x)   106 (1.58x)

gcc           c   neon_original      neon_new
A55         990    2301 (0.43x)   575 (1.72x)
A76         382     549 (0.69x)   205 (1.87x)
X1          208     322 (0.65x)   108 (1.91x)
A510        971    2395 (0.41x)   449 (2.16x)
A710        338     498 (0.68x)   194 (1.74x)
X2          202     298 (0.68x)   107 (1.89x)

5.1 HE-AAC decoding with -threads 1 is about 1-2.5% faster.

Signed-off-by: Gyula Sebok <gyula.sbk@gmail.com>
2026-11-03 18:29:15 +00:00
Patryk Darmofalski d943d90925 avcodec/aarch64/audiodsp: add NEON vector_clip_int32 and vector_clipf
vector_clip_int32 is based on the 32-bit ARM NEON version. Unrolling to
16 or 32 elements per iteration gave no measurable improvement over 8.

vector_clipf applies fmin before fmaxnm, so any NaN input, including a
signaling one, yields min as in C and as documented for av_clipf.

checkasm --bench on Apple M4:
vector_clip_int32_c:      1029.6
vector_clip_int32_neon:    180.7 ( 5.38x)
vector_clipf_c:            682.9
vector_clipf_neon:         190.8 ( 3.34x)

Signed-off-by: Patryk Darmofalski <darpat039@gmail.com>
2026-11-03 18:26:07 +00:00
Mark Thompson 693195b518 lavc/apv: Precompute transquant constants once per tile component
Adds a new dsp function to compute a constants buffer in the form most
suitable to the specific implementation.  This gets called once per
tile component to prepare the constants buffer, and then the transquant
functions get a pointer to that buffer to use.

CPU: Intel(R) Xeon(R) Gold 6252 CPU @ 2.10GHz
Before:
  decode_transquant_10_c:       333.2
  decode_transquant_10_avx2:     65.5 ( 5.09x)
After:
  decode_transquant_10_c:       330.9
  decode_transquant_10_avx2:     57.3 ( 5.78x)

No significant difference on ARM Cortex-A53/A73.
2026-11-01 14:33:45 +00:00
Mark Thompson 9d2d5b1aa3 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)
2026-10-24 04:45:33 +00:00
Zhao Zhili c569ebacce aarch64/h26x: reuse the shared qpel hv window rotation
The eight positions of the eight-row window are the same walk for every
vertical tail, and calc_all already carries it. The wider weighted tails stay
as they are: calc_all2 fixes its window to v16..v31, so handing them over means
moving their accumulators and weight vectors out of that range first.

No functional changes.
2026-10-23 03:42:41 +00:00
Zhao Zhili 9a0e010a9c aarch64/h26x: load a weighted qpel hv row with one instruction
The unweighted step macros in this file let a post-indexed load walk the
intermediate plane, while these weighted steps loaded a row and then advanced
sp with a separate add. Fold the advance into the load.

The step macro now names its row register without a width letter, which is
what the next change needs in order to drive these tails from calc_all.
2026-10-23 03:42:41 +00:00
Zhao Zhili dd04dc6fc6 aarch64/h26x: share the weighted qpel hv vertical tail up to 8 wide
No functional changes.
2026-10-23 03:42:41 +00:00
Zhao Zhili e79dcfabf0 aarch64/h26x: factor the weighted qpel hv vertical row step into macros
No functional changes.
2026-10-23 03:42:41 +00:00
Zhao Zhili adfe258a6a aarch64/h26x: share the qpel_uni_w narrowing across widths
The weighted narrowing after the horizontal filter was repeated at every
width. Sharing one stage at a time rather than a whole block at a time
keeps the serial sqxtn/sqxtn2/sqxtun chain of a block from stalling an
in-order core.
2026-10-21 17:53:37 +00:00
Zhao Zhili b9305c490f aarch64/h26x: fold qpel horizontal variant tails into macros
post_h_2reg and post_h_4reg hold the blend-and-narrow sequence shared by
the qpel_uni and qpel_bi width wrappers.
2026-10-21 17:53:37 +00:00
Jun Zhao 2344518cc5 avcodec/aarch64: build pngdsp for the APNG and LSCR decoders
pngdsp.c calls ff_pngdsp_init_aarch64 on this architecture, and both
decoders link pngdsp.o. The init and NEON objects were selected only
for the PNG decoder, so a build with APNG or LSCR and without PNG
failed to link.

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
2026-10-19 07:58:26 +00:00
Devin Heitmueller 098dd9f46a 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.
2026-10-15 18:46:02 +00:00
Zhao Zhili a25ba44c0c aarch64/h26x: drop the dead epel vertical accumulator zeroing
calc_epelb and calc_epelb2 open with a widening multiply, which writes its
destination instead of accumulating into it, so the movi that cleared the
accumulator ahead of them had no effect. The zeroing that feeds a usdot or
an umlsl stays, since both add into their destination.
2026-10-08 09:52:28 +00:00
Zhao Zhili c4fd2d3e8b aarch64/h26x: drop the dead qpel vertical accumulator zeroing
calc_qpelb and calc_qpelb2 open with a widening multiply, which writes its
destination instead of accumulating into it, so the movi that cleared the
accumulator ahead of them had no effect. The plain vertical steps at widths
4 to 64 and the bi steps at widths 4 to 32 carried it.
2026-10-08 09:52:28 +00:00
Zhao Zhili 26c6816846 avcodec/aarch64: add NEON VVC SAO edge 10 and 12 bit
Cortex-A510       Cortex-A715       Cortex-A725         Cortex-X3       Cortex-X925
vvc_sao_edge_8_10_neon:     308.9 (4.29x)      57.1 (5.47x)      57.4 (4.66x)      36.4 (7.35x)      23.7 (8.13x)
vvc_sao_edge_8_12_neon:     314.6 (4.19x)      57.3 (5.58x)      58.3 (4.59x)      36.4 (7.34x)      23.9 (8.08x)
vvc_sao_edge_16_10_neon:   1202.1 (4.28x)     228.1 (5.26x)     228.6 (4.54x)     144.6 (7.28x)      95.0 (8.39x)
vvc_sao_edge_16_12_neon:   1203.3 (4.28x)     229.4 (5.37x)     239.4 (4.33x)     144.6 (7.22x)      95.0 (8.38x)
vvc_sao_edge_32_10_neon:   4718.8 (4.28x)     913.1 (5.12x)     911.5 (4.42x)     571.5 (7.30x)     366.9 (9.08x)
vvc_sao_edge_32_12_neon:   4737.9 (4.26x)     913.3 (5.28x)     913.0 (4.41x)     571.8 (7.31x)     365.6 (9.15x)
vvc_sao_edge_48_10_neon:  10970.3 (4.16x)    2035.0 (5.13x)    2036.2 (4.43x)    1307.6 (7.14x)     823.6 (9.19x)
vvc_sao_edge_48_12_neon:  10980.7 (4.15x)    2037.3 (5.29x)    2035.0 (4.43x)    1311.2 (7.14x)     824.1 (9.20x)
vvc_sao_edge_64_10_neon:  19127.9 (4.23x)    3605.3 (5.13x)    3628.5 (4.41x)    2315.9 (7.17x)    1452.7 (9.33x)
vvc_sao_edge_64_12_neon:  19136.2 (4.23x)    3606.3 (5.29x)    3629.0 (4.40x)    2320.9 (7.17x)    1448.9 (9.36x)
vvc_sao_edge_80_10_neon:  29560.9 (4.29x)    5624.0 (5.30x)    5657.5 (4.64x)    3610.8 (7.17x)    2252.1 (9.44x)
vvc_sao_edge_80_12_neon:  29644.8 (4.28x)    5626.8 (5.48x)    5661.2 (4.64x)    3614.4 (7.18x)    2250.3 (9.46x)
vvc_sao_edge_96_10_neon:  42316.0 (4.29x)    8088.8 (5.28x)    8135.3 (4.61x)    5188.5 (7.20x)    3236.3 (9.49x)
vvc_sao_edge_96_12_neon:  42863.0 (4.23x)    8091.9 (5.45x)    8136.9 (4.61x)    5190.6 (7.21x)    3236.1 (9.48x)
vvc_sao_edge_112_10_neon: 57410.2 (4.30x)   11001.8 (5.27x)   11056.2 (4.59x)    7066.3 (7.19x)    4407.8 (9.48x)
vvc_sao_edge_112_12_neon: 57372.5 (4.30x)   11006.7 (5.44x)   11054.2 (4.59x)    7074.3 (7.19x)    4400.6 (9.52x)
vvc_sao_edge_128_10_neon: 75737.0 (4.26x)   14401.4 (5.26x)   14468.5 (4.57x)    9227.8 (7.22x)    5729.6 (9.54x)
vvc_sao_edge_128_12_neon: 75824.1 (4.25x)   14404.0 (5.42x)   14472.1 (4.57x)    9222.1 (7.20x)    5730.8 (9.55x)

Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
2026-10-05 12:58:53 +00:00
Zhao Zhili b37f08942b avcodec/aarch64: add NEON HEVC SAO edge 10 and 12 bit
Cortex-A510       Cortex-A715       Cortex-A725         Cortex-X3       Cortex-X925
hevc_sao_edge_8_10_neon:    332.5 (4.07x)      56.9 (5.50x)      57.4 (4.64x)      37.0 (7.38x)      24.2 (7.96x)
hevc_sao_edge_8_12_neon:    321.9 (4.22x)      57.1 (5.58x)      57.7 (4.70x)      37.0 (7.27x)      23.7 (8.12x)
hevc_sao_edge_16_10_neon:  1280.4 (4.11x)     227.3 (5.30x)     227.9 (4.61x)     146.4 (7.27x)      94.9 (8.38x)
hevc_sao_edge_16_12_neon:  1353.7 (3.96x)     227.9 (5.40x)     227.1 (4.63x)     146.4 (7.22x)      94.7 (8.40x)
hevc_sao_edge_32_10_neon:  5249.9 (3.84x)     912.9 (5.15x)     911.5 (4.48x)     592.8 (7.21x)     372.7 (8.95x)
hevc_sao_edge_32_12_neon:  5483.8 (3.67x)     912.6 (5.29x)     912.3 (4.47x)     579.8 (7.21x)     365.2 (9.11x)
hevc_sao_edge_48_10_neon: 11147.5 (4.07x)    2035.5 (5.14x)    2033.9 (4.48x)    1324.3 (7.27x)     815.7 (9.29x)
hevc_sao_edge_48_12_neon: 11179.6 (4.06x)    2035.5 (5.29x)    2035.9 (4.47x)    1324.9 (7.05x)     816.8 (9.25x)
hevc_sao_edge_64_10_neon: 19965.6 (4.03x)    3606.1 (5.15x)    3603.6 (4.49x)    2340.0 (7.27x)    1440.0 (9.42x)
hevc_sao_edge_64_12_neon: 20015.7 (4.02x)    3604.2 (5.30x)    3603.3 (4.49x)    2342.3 (7.07x)    1439.2 (9.40x)

Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
2026-10-05 12:58:53 +00:00
Zhao Zhili 7cb2863b8e avcodec/sao: fix swapped 45 and 135 degree EO class comments
The position tables are indexed by sao_eo_class: index 2 is SAO_EO_135D,
with neighbours at (-1,-1) and (1,1), and index 3 is SAO_EO_45D.

Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
2026-10-05 12:58:53 +00:00
Zuxy Meng 9c852d9e23 avcodec/arm|aarch64/h264dsp: Fix edge cases of bi-weight for neon
S16 saturating sum must be computed dot-product-first. The NEON code
accumulated the offset into the dot product with wrapping
multiply-accumate, so large-magnitude sums wrapped instead of saturating.

Accumulate the dot product from zero (wrapping is exact: the dot product
cannot overflow S16 for 8-bit with log2_denom < 7), then add the offset
with a saturating add.

This fixes bi-weight checkasm test for NEON.

Signed-off-by: Zuxy Meng <zuxy.meng@gmail.com>
2026-10-01 17:49:31 -07:00
Zuxy Meng c80bfd962f avcodec/arm|aarch64/h264dsp: Fix edge cases for weight
Add/sub with saturation is used only on log2_denom > 1 path, but with
log2_denom == 1 (block[x]*weight + offset << 1) can fall below S16_MIN.
Use saturation in all paths for safety.

This fixes the weight checkasm test for arm and aarch64

Signed-off-by: Zuxy Meng <zuxy.meng@gmail.com>
2026-10-01 17:49:31 -07:00
Zhao Zhili b0d1545911 aarch64/h26x: load the qpel hv plane pitch in the vertical tail
The plain hv4 and hv6 vertical tails walk the intermediate plane using
a row pitch in x7 that their entry glue loads before the horizontal
kernel call. The neon kernels reuse x7 as their destination stride and
return with it set to 128, and the i8mm ones happen not to touch it, so
the value survives the call by accident even though x7 is caller-saved.
Load the pitch in the tails, as hv8, hv12, hv16 and hv32 already do.
2026-09-24 16:42:49 +00:00
Andreas Rheinhardt 680504e965 avcodec/ac3dsp: Constify
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2026-09-02 22:31:34 +02:00
Andreas Rheinhardt b6e90cc92c avcodec/fmtconvert: Remove now unused subsystem
Unused since 2312ae4d10.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2026-08-19 22:25:07 +02:00
Andreas Rheinhardt b397eba2f0 avcodec/h264dsp: Use ptrdiff_t for stride in idct functions
Reviewed-by: Martin Storsjö <martin@martin.st>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2026-08-13 00:29:25 +02:00
Jeongkeun Kim 280fd60916 avcodec/aarch64: add NEON lfe_x96_fixed for DCA DSP
Implement the fixed-point LFE x96 interpolation filter in AArch64
NEON. Four input samples are processed per iteration. The history
sample is kept in a vector lane, and ext constructs the delayed input.

Benchmarks by Martin Storsjö using checkasm:
               a53     a55    a520     a72     a76    a720
              1.86x   1.88x   1.24x   1.99x   1.62x   2.30x

Author's measurement on Neoverse-N1 (Oracle Cloud, clang 14): 1.29x.

Signed-off-by: Jeongkeun Kim <variety0724@gmail.com>
2026-08-09 00:18:08 +03:00
Andreas Rheinhardt 95c43d7df7 avcodec/fmtconvert: Remove int32_to_float_fmul_array8
Unused since aebf07075f.

Reviewed-by: Martin Storsjö <martin@martin.st>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2026-08-06 11:26:35 +02:00
Zhao Zhili f1dbe5252b avcodec/aarch64: rewrite lfe_fir1 to remove faddp reduction
The original implementation was a regression on Cortex-X925 (0.88x).

               X925 clang    X925 gcc      A725 clang   A725 gcc     A510 clang
c:              891          1638          792          1475         8084
neon_original: 1015 (0.88x)  1016 (1.61x)  747 (1.06x)  747 (1.97x)  6126 (1.31x)
neon_new:       696 (1.28x)   696 (2.35x)  623 (1.27x)  623 (2.37x)  3697 (2.18x)

Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
2026-08-05 11:49:17 +00:00
Kacper Michajłow 9862dd83b1 avcodec/aarch64/vc1dsp_neon: reduce literal pool alignment to 16 bytes
armasm64 warns "A4228: Alignment value exceeds AREA alignment; alignment
not guaranteed" on the .Lcoeffs literal pool. gas-preprocessor.pl emits
the text section as "AREA |.text|, CODE, READONLY, ALIGN=4", i.e. a
16-byte section alignment, so a 32-byte ALIGN inside it cannot be
guaranteed by the assembler.

16 is enough here: the pool holds .quad values that are read with
"ldr d0, .Lcoeffs" literal loads, which only require 8-byte alignment.
It also matches the rest of the aarch64 asm, where the function and
const macros both default to .align 4.

Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
2026-08-03 18:16:24 +00:00
Andreas Rheinhardt a59498db08 avcodec/huffyuvdsp: Remove pix_fmt parameter from ff_huffyuvdsp_init()
It is unused since the mmx add_hfyu_median_pred_int16 function
has been removed.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2026-08-02 02:19:05 +02:00
Zhao Zhili 45bc6c0c08 aarch64/h26x: move step macros before their functions
No functional changes.

Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
2026-07-08 03:37:41 +00:00
Zhao Zhili ee9aba4c55 aarch64/h26x: give step macros distinct names per function
Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
2026-07-08 03:37:41 +00:00
Zhao Zhili 741e563077 aarch64/h26x: parameterize calc_all step macro name
So callers can pass a named step macro instead of relying on a locally
redefined `calc` followed by `.purgem calc`.

Signed-off-by: Zhao Zhili <zhilizhao@tencent.com>
2026-07-08 03:37:41 +00:00
Andreas Rheinhardt baad19d0b5 avcodec/hevc/dsp: Combine offsets early for biweight prediction
Only the sum of the offsets is ever used
(see equation 8-279 in the 2019 version of the H.265 spec).

Tested-by: Martin Storsjö <martin@martin.st>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
2026-06-27 00:06:08 +02:00
Martin Storsjö d05786cf23 aarch64: vp9lpf: Fix GCS violations
The aarch64 VP9 loopfilters actually violate aarch64 GCS
(Guarded Control Stack), even though we marked the code as GCS
compliant in 846746be4b.

This means that builds with GCS enabled, after that commit,
will crash when decoding VP9, on future hardware (or current
QEMU) that supports GCS. This also goes for ffmpeg version 8.1.1
where the GCS enabling was backported.

This matches the fix that was done for hevcdsp in
1f7ed8a78d.

This issue wasn't observed if running checkasm in QEMU - therefore,
I thought all GCS issues had been fixed by
846746be4b. (If I would have
tested the full "make fate" with QEMU, the issue would
have appeared though.)

However with the new checkasm, some of the GCS violations
do appear even in checkasm.

The reason is that the checkasm vp9 test intentionally craft
input pixels that attempt to trigger all the individual
separate cases in each input buffer (in
randomize_loopfilter_buffers). This means that the checkasm
tests actually never test or exercise the early exit cases,
which are the ones that violate GCS.

With the new checkasm, the call to "bench_new" always test
running the code at least once, even if not benchmarking.

As the input buffers weren't reinitialized between the test
and "bench_new", the pixel differences now differ from the
initial setup, so that the code now some times (often) would
end up hitting the early exit cases.

Ideally, the vp9 checkasm test would be repeated to cover all
cases of input buffers that allow early exits, in addition to
covering the case with all different cases in one block.
2026-06-10 18:03:01 +00:00
Jun Zhao cfa3ceac7a lavc/hevc: add aarch64 NEON for angular modes 10 and 26
Add NEON-optimized implementations for HEVC angular intra prediction
modes 10 (pure horizontal) and 26 (pure vertical) at 8-bit depth.

Mode 10 (Horizontal):
- Broadcasts left[y] to fill each row using ld2r/ld4r for efficiency
- Applies edge smoothing for luma blocks smaller than 32x32

Mode 26 (Vertical):
- Copies top reference row to all output rows
- Applies edge smoothing for luma blocks smaller than 32x32

Edge smoothing uses uhsub+usqadd to compute the filtered result
directly in 8-bit, avoiding widening to 16-bit intermediates.

The C pred_angular wrappers are made non-static with ff_ prefix to
allow the NEON dispatch to fall back to C for modes not yet optimized.
This will be reverted once all angular modes are implemented.

Note: since pred_angular[] is a per-size function pointer (not
per-mode), checkasm benchmarks will show '_neon' for all 33 modes
even though only modes 10/26 are truly accelerated; unoptimized
modes show ~1.0x speedup as they pass through the NEON wrapper to
the C fallback with negligible overhead.

Speedup over C on Apple M4 (checkasm --bench, 15-run average):

  Mode 10 (Horizontal):
    4x4: 4.66x    8x8: 5.80x    16x16: 16.86x    32x32: 24.89x

  Mode 26 (Vertical):
    4x4: 1.16x    8x8: 1.83x    16x16: 2.45x    32x32: 4.50x

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
2026-06-07 23:29:33 +00:00
Zhao Zhili 200914853d aarch64/sbrdsp: unroll sum64x5 to 16 floats/iter
The C version is faster than the previous asm with clang and gcc > 12 on
rpi5, since compiler basically does the same unroll.

sum64x5_neon:             before          after
  Cortex-A76 (gcc 12.4):  72.3 (3.63x)    47.4 (5.56x)
  Cortex-A76 (gcc 14.2):  72.3 (0.69x)    47.4 (1.05x)
  Apple M1 (clang 16):     0.2 (0.98x)     0.2 (0.99x)

Signed-off-by: Zhao Zhili <quinkblack@foxmail.com>
2026-06-03 10:40:20 +00:00
Jeongkeun Kim 4ea59d5665 avcodec/aarch64: add NEON DCA LFE FIR filter functions
Port lfe_fir0_float and lfe_fir1_float to AArch64 NEON. These polyphase
FIR interpolation filters have an x86 SSE/AVX path but no AArch64
equivalent, falling back to scalar C.

The inner loop computes two dot products per output pair. Precomputing a
reversed LFE sample vector before the inner loop avoids per-iteration
shuffle overhead.

Benchmarks on AWS Graviton3 (Neoverse V1, c7g.xlarge):
  lfe_fir0_float: C 5902.0 cycles -> NEON 2135.0 cycles (2.77x)
  lfe_fir1_float: C 2836.3 cycles -> NEON 1527.8 cycles (1.86x)
Measured with: taskset -c 0 ./tests/checkasm/checkasm --test=dcadsp --bench,
3-run average, Ubuntu 22.04 (kernel 6.8.0-1052-aws), perf_event_paranoid=0.

Signed-off-by: Jeongkeun Kim <variety0724@gmail.com>
2026-04-27 20:13:23 +00:00
Georgii Zagoruiko 1ced59326a aarch64/vvc: Optimisations of put_chroma_hv() functions for 10/12-bit
Apple M4:
put_chroma_hv_10_2x2_c:                                  9.1 ( 1.00x)
put_chroma_hv_10_4x4_c:                                 20.1 ( 1.00x)
put_chroma_hv_10_8x8_c:                                 35.6 ( 1.00x)
put_chroma_hv_10_8x8_neon:                              15.4 ( 2.31x)
put_chroma_hv_10_16x16_c:                              113.7 ( 1.00x)
put_chroma_hv_10_16x16_neon:                            57.0 ( 1.99x)
put_chroma_hv_10_32x32_c:                              406.9 ( 1.00x)
put_chroma_hv_10_32x32_neon:                           225.7 ( 1.80x)
put_chroma_hv_10_64x64_c:                             1498.8 ( 1.00x)
put_chroma_hv_10_64x64_neon:                           876.2 ( 1.71x)
put_chroma_hv_10_128x128_c:                           5757.0 ( 1.00x)
put_chroma_hv_10_128x128_neon:                        3446.6 ( 1.67x)
put_chroma_hv_12_2x2_c:                                  9.9 ( 1.00x)
put_chroma_hv_12_4x4_c:                                 19.2 ( 1.00x)
put_chroma_hv_12_8x8_c:                                 36.1 ( 1.00x)
put_chroma_hv_12_8x8_neon:                              17.9 ( 2.02x)
put_chroma_hv_12_16x16_c:                              112.2 ( 1.00x)
put_chroma_hv_12_16x16_neon:                            55.6 ( 2.02x)
put_chroma_hv_12_32x32_c:                              416.6 ( 1.00x)
put_chroma_hv_12_32x32_neon:                           224.3 ( 1.86x)
put_chroma_hv_12_64x64_c:                             1464.8 ( 1.00x)
put_chroma_hv_12_64x64_neon:                           860.1 ( 1.70x)
put_chroma_hv_12_128x128_c:                           5776.8 ( 1.00x)
put_chroma_hv_12_128x128_neon:                        3445.2 ( 1.68x)

RPi5:
put_chroma_hv_10_2x2_c:                                118.5 ( 1.00x)
put_chroma_hv_10_4x4_c:                                190.6 ( 1.00x)
put_chroma_hv_10_8x8_c:                                303.1 ( 1.00x)
put_chroma_hv_10_8x8_neon:                             172.6 ( 1.76x)
put_chroma_hv_10_16x16_c:                             1036.1 ( 1.00x)
put_chroma_hv_10_16x16_neon:                           626.7 ( 1.65x)
put_chroma_hv_10_32x32_c:                             3624.4 ( 1.00x)
put_chroma_hv_10_32x32_neon:                          2386.9 ( 1.52x)
put_chroma_hv_10_64x64_c:                            13612.1 ( 1.00x)
put_chroma_hv_10_64x64_neon:                          9314.8 ( 1.46x)
put_chroma_hv_10_128x128_c:                          52975.4 ( 1.00x)
put_chroma_hv_10_128x128_neon:                       37083.5 ( 1.43x)
put_chroma_hv_12_2x2_c:                                118.6 ( 1.00x)
put_chroma_hv_12_4x4_c:                                188.1 ( 1.00x)
put_chroma_hv_12_8x8_c:                                303.4 ( 1.00x)
put_chroma_hv_12_8x8_neon:                             176.7 ( 1.72x)
put_chroma_hv_12_16x16_c:                             1037.9 ( 1.00x)
put_chroma_hv_12_16x16_neon:                           626.5 ( 1.66x)
put_chroma_hv_12_32x32_c:                             3629.0 ( 1.00x)
put_chroma_hv_12_32x32_neon:                          2386.6 ( 1.52x)
put_chroma_hv_12_64x64_c:                            13649.0 ( 1.00x)
put_chroma_hv_12_64x64_neon:                          9313.6 ( 1.47x)
put_chroma_hv_12_128x128_c:                          52978.0 ( 1.00x)
put_chroma_hv_12_128x128_neon:                       37101.2 ( 1.43x)
2026-04-27 20:10:57 +00:00
Jun Zhao 75838b9c89 lavc/hevc: add aarch64 NEON for reference sample filtering
3-tap [1,2,1]>>2: shared implementation body across size-specialized
entry points (8x8/16x16/32x32) to reduce code size. Fold the 3-tap
kernel into uhadd + urhadd: uhadd gives floor((prev+next)/2), then
urhadd rounds with curr to produce (prev + 2*curr + next + 2) >> 2
on 16 bytes in-place (no widen/narrow needed). Overlap-last technique
for tail avoids partial stores. Caller pads input arrays by 16 bytes
to guarantee safe over-read.

Strong smoothing (32x32): preloaded weight tables, interleaved
umull/umlal pairs (two 16-byte blocks at a time) to hide
rshrn-to-store latency, with paired st1 for 32-byte writes.

checkasm --bench --runs=15 (Apple M4, average of 3 trials):
  ref_filter_3tap_8x8_8_neon:    4.1x
  ref_filter_3tap_16x16_8_neon:  3.3x
  ref_filter_3tap_32x32_8_neon:  2.5x
  ref_filter_strong_8_neon:      1.9x

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
2026-04-21 07:50:49 +00:00
Jun Zhao 89c21b5ab7 lavc/hevc: add aarch64 NEON for Planar prediction
Add NEON-optimized implementation for HEVC intra Planar prediction at
8-bit depth, supporting all block sizes (4x4 to 32x32).

Planar prediction implements bilinear interpolation using an incremental
base update: base_{y+1}[x] = base_y[x] - (top[x] - left[N]), reducing
per-row computation from 4 multiply-adds to 1 subtract + 1 multiply.
Uses rshrn for rounded narrowing shifts, eliminating manual rounding
bias. All left[y] values are broadcast in the NEON domain, avoiding
GP-to-NEON transfers.

4x4 interleaves row computations across 4 rows to break dependencies.
16x16 uses v19-v22 for persistent base/decrement vectors, avoiding
callee-saved register spills. 32x32 processes 8 rows per loop iteration
(4 iterations total) to reduce code size while maintaining full NEON
utilization.

Speedup over C on Apple M4 (checkasm --bench):

    4x4: 2.25x    8x8: 6.40x    16x16: 9.72x    32x32: 3.21x

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
2026-03-30 14:32:10 +00:00
Jun Zhao 60b372c934 lavc/hevc: add aarch64 NEON for DC prediction
Add NEON-optimized implementation for HEVC intra DC prediction at 8-bit
depth, supporting all block sizes (4x4 to 32x32).

DC prediction computes the average of top and left reference samples
using uaddlv, with urshr for rounded division. For luma blocks smaller
than 32x32, edge smoothing is applied: the first row and column are
blended toward the reference using (ref[i] + 3*dc + 2) >> 2 computed
entirely in the NEON domain. Fill stores use pre-computed address
patterns to break dependency chains.

Also adds the aarch64 initialization framework (Makefile, pred.c/pred.h
hooks, hevcpred_init_aarch64.c).

Speedup over C on Apple M4 (checkasm --bench):

    4x4: 2.28x    8x8: 3.14x    16x16: 3.29x    32x32: 3.02x

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
2026-03-30 14:32:10 +00:00
Georgii Zagoruiko 1c385023aa aarch64/vvc: Optimisations of put_chroma_v() functions for 10/12-bit
Apple M4:
put_chroma_v_10_2x2_c:                                   5.8 ( 1.00x)
put_chroma_v_10_4x4_c:                                   9.0 ( 1.00x)
put_chroma_v_10_4x4_neon:                                1.7 ( 5.29x)
put_chroma_v_10_8x8_c:                                  22.1 ( 1.00x)
put_chroma_v_10_8x8_neon:                                5.8 ( 3.79x)
put_chroma_v_10_16x16_c:                                56.3 ( 1.00x)
put_chroma_v_10_16x16_neon:                             21.2 ( 2.66x)
put_chroma_v_10_32x32_c:                               181.6 ( 1.00x)
put_chroma_v_10_32x32_neon:                             86.9 ( 2.09x)
put_chroma_v_10_64x64_c:                               680.3 ( 1.00x)
put_chroma_v_10_64x64_neon:                            337.4 ( 2.02x)
put_chroma_v_10_128x128_c:                            2567.3 ( 1.00x)
put_chroma_v_10_128x128_neon:                         1374.8 ( 1.87x)
put_chroma_v_12_2x2_c:                                   6.4 ( 1.00x)
put_chroma_v_12_4x4_c:                                   8.2 ( 1.00x)
put_chroma_v_12_4x4_neon:                                1.5 ( 5.56x)
put_chroma_v_12_8x8_c:                                  18.9 ( 1.00x)
put_chroma_v_12_8x8_neon:                                5.7 ( 3.29x)
put_chroma_v_12_16x16_c:                                52.6 ( 1.00x)
put_chroma_v_12_16x16_neon:                             19.9 ( 2.65x)
put_chroma_v_12_32x32_c:                               185.7 ( 1.00x)
put_chroma_v_12_32x32_neon:                             81.9 ( 2.27x)
put_chroma_v_12_64x64_c:                               661.8 ( 1.00x)
put_chroma_v_12_64x64_neon:                            342.1 ( 1.93x)
put_chroma_v_12_128x128_c:                            2547.8 ( 1.00x)
put_chroma_v_12_128x128_neon:                         1368.0 ( 1.86x)

RPi4:
put_chroma_v_10_2x2_c:                                  64.8 ( 1.00x)
put_chroma_v_10_4x4_c:                                 157.2 ( 1.00x)
put_chroma_v_10_4x4_neon:                               39.7 ( 3.96x)
put_chroma_v_10_8x8_c:                                 562.1 ( 1.00x)
put_chroma_v_10_8x8_neon:                               98.8 ( 5.69x)
put_chroma_v_10_16x16_c:                              1170.7 ( 1.00x)
put_chroma_v_10_16x16_neon:                            380.7 ( 3.07x)
put_chroma_v_10_32x32_c:                              3696.6 ( 1.00x)
put_chroma_v_10_32x32_neon:                           1723.8 ( 2.14x)
put_chroma_v_10_64x64_c:                             13170.9 ( 1.00x)
put_chroma_v_10_64x64_neon:                           7284.1 ( 1.81x)
put_chroma_v_10_128x128_c:                           46068.3 ( 1.00x)
put_chroma_v_10_128x128_neon:                        27219.5 ( 1.69x)
put_chroma_v_12_2x2_c:                                  63.8 ( 1.00x)
put_chroma_v_12_4x4_c:                                 156.5 ( 1.00x)
put_chroma_v_12_4x4_neon:                               39.3 ( 3.98x)
put_chroma_v_12_8x8_c:                                 560.9 ( 1.00x)
put_chroma_v_12_8x8_neon:                               98.7 ( 5.68x)
put_chroma_v_12_16x16_c:                              1169.9 ( 1.00x)
put_chroma_v_12_16x16_neon:                            380.8 ( 3.07x)
put_chroma_v_12_32x32_c:                              3693.9 ( 1.00x)
put_chroma_v_12_32x32_neon:                           1728.4 ( 2.14x)
put_chroma_v_12_64x64_c:                             13170.9 ( 1.00x)
put_chroma_v_12_64x64_neon:                           7284.9 ( 1.81x)
put_chroma_v_12_128x128_c:                           46068.0 ( 1.00x)
put_chroma_v_12_128x128_neon:                        27224.6 ( 1.69x)
2026-03-27 13:42:50 +00:00
Martin Storsjö f72f692afa aarch64: Add PAC sign/validation of the link register
Whenever the link register is stored on the stack, sign it
before storing it and validate at a symmetrical point (with the
stack at the same level as when it was signed).

These macros only have an effect if built with PAC enabled (e.g.
through -mbranch-protection=standard), otherwise they don't
generate any extra instructions.

None of these cases were present when PAC support was added
in 248986a0db in 2022.

Without these changes, PAC still had an effect in the compiler
generated code and in the existing cases where we these macros were
used - but make it apply to the remaining cases of link register
on the stack.
2026-03-20 13:16:06 +02:00
Martin Storsjö dbf7354d98 aarch64/inter_sme2: Remove needless backup/restore of x29/x30
The sme_entry/sme_exit macros already take care of backing up/restoring
these registers. Additionally, as long as no function calls are
made within the function, x30 doesn't need to be backed up at all.
2026-03-20 13:16:06 +02:00
Martin Storsjö 1f7ed8a78d aarch64: hevcdsp: Make returns match the call site
For cases when returning early without updating any pixels, we
previously returned to return address in the caller's scope,
bypassing one function entirely. While this may seem like a neat
optimization, it makes the return stack predictor mispredict
the returns - which potentially can cost more performance than
it gains.

Secondly, if the armv9.3 feature GCS (Guarded Control Stack) is
enabled, then returns _must_ match the expected value; this feature
is being enabled across linux distributions, and by fixing the
hevc assembly, we can enable the security feature on ffmpeg as well.
2026-03-17 20:37:53 +00:00
Jun Zhao 254b92ec8a lavc/hevc: reorder aarch64 NEON pel function assignments
Group assignments by filter family (qpel, epel), variant
(base, uni, bi, uni_w, bi_w) and direction (pixels, h, v, hv).
Add NEON8_FNASSIGN_QPEL_H macro to replace repeated manual
qpel horizontal assignments.

No functional change.

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
2026-03-13 21:43:37 +00:00
Jun Zhao 489d36b5e1 lavc/hevc: add aarch64 NEON for epel uni horizontal filter
Add NEON-optimized implementations for HEVC EPEL uni-directional
horizontal interpolation (put_hevc_epel_uni_h) at 8-bit depth.

These functions perform horizontal 4-tap EPEL filtering with
output directly to uint8_t pixels (no weighting):
- 4-tap horizontal EPEL filter
- Output: (filter_result + 32) >> 6, clipped to [0, 255]

Supports all block widths: 4, 6, 8, 12, 16, 24, 32, 48, 64.

Performance results on Apple M4:
./tests/checkasm/checkasm --test=hevc_pel --bench

put_hevc_epel_uni_h4_8_neon:   2.26x
put_hevc_epel_uni_h6_8_neon:   2.71x
put_hevc_epel_uni_h8_8_neon:   4.40x
put_hevc_epel_uni_h12_8_neon:  3.60x
put_hevc_epel_uni_h16_8_neon:  3.00x
put_hevc_epel_uni_h24_8_neon:  3.72x
put_hevc_epel_uni_h32_8_neon:  3.14x
put_hevc_epel_uni_h48_8_neon:  3.16x
put_hevc_epel_uni_h64_8_neon:  3.15x

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
2026-03-13 21:43:37 +00:00
Jun Zhao f5e6cca935 lavc/hevc: add aarch64 NEON for qpel uni-weighted HV filter
Add NEON-optimized implementations for HEVC QPEL uni-directional
weighted HV interpolation (put_hevc_qpel_uni_w_hv) at 8-bit depth,
for block widths 6, 12, 24, and 48.

These functions perform horizontal then vertical 8-tap QPEL filtering
with weighting (wx, ox, denom) and output to uint8_t. Previously
only widths 4, 8, 16, 32, 64 were implemented; this completes
coverage for all standard HEVC block widths.

Performance results on Apple M4:
./tests/checkasm/checkasm --test=hevc_pel --bench

put_hevc_qpel_uni_w_hv6_8_neon:   3.11x
put_hevc_qpel_uni_w_hv12_8_neon:  3.19x
put_hevc_qpel_uni_w_hv24_8_neon:  2.26x
put_hevc_qpel_uni_w_hv48_8_neon:  1.80x

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
2026-03-13 21:43:37 +00:00
Jun Zhao fe41ff7413 lavc/hevc: add aarch64 NEON for qpel uni-weighted vertical filter
Add NEON-optimized implementations for HEVC QPEL uni-weighted
vertical interpolation (put_hevc_qpel_uni_w_v) at 8-bit depth.

These functions perform weighted uni-directional prediction with
vertical QPEL filtering:
- 8-tap vertical QPEL filter
- Weighted prediction: (filter_result * wx + offset) >> shift

Previously only sizes 4, 8, 16, 64 were optimized. This patch adds
optimized implementations for all remaining sizes: 6, 12, 24, 32, 48.

Performance results on Apple M4:
./tests/checkasm/checkasm --test=hevc_pel --bench

put_hevc_qpel_uni_w_v6_8_neon:   3.40x
put_hevc_qpel_uni_w_v12_8_neon:  3.24x
put_hevc_qpel_uni_w_v24_8_neon:  3.06x
put_hevc_qpel_uni_w_v32_8_neon:  2.66x
put_hevc_qpel_uni_w_v48_8_neon:  2.67x

Signed-off-by: Jun Zhao <barryjzhao@tencent.com>
2026-03-13 21:43:37 +00:00