From e1d3a62d495e8c4c95733c7da7a6fdd886fb9c7e Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Fri, 24 Jul 2026 04:15:10 +0000 Subject: [PATCH 09/38] avcodec/ppc: add AltiVec ac3dsp (float_to_fixed24, sum_square_butterfly_float) New libavcodec/ppc/ac3dsp.c, dispatched via ff_ac3dsp_init_ppc (first ARCH_PPC branch in the shared ac3dsp.c -- no PPC ac3dsp existed before): - float_to_fixed24: vec_round (PowerPC round-to-nearest-even) then vec_cts, matching lrintf's default rounding exactly -- plain vec_cts alone truncates toward zero and would mismatch at .5 boundaries. Same round-then-convert idiom as CTS() in fdctdsp.c. - sum_square_butterfly_float: vec_madd reduction into 4 accumulators (lt*lt, rt*rt, md*md, sd*sd), horizontal-summed via an aligned stack temp; scalar tail loop for len not a multiple of 4. sum_square_butterfly_int32 (needs int64-widening multiply-accumulate, no vec_msum equivalent for genuine 64-bit accumulation) and extract_exponents (needs a per-lane av_log2/bit-scan-reverse) are intentionally left on the C path this pass -- both need more careful design than a mechanical vectorization to get right. VALIDATED: checkasm ac3dsp passes under the cross-PPC/qemu harness (qemu-ppc-static -cpu 7400) across 5 random seeds, real ALTIVEC dispatch confirmed, exact memcmp match (float_to_fixed24 has zero tolerance in the checkasm test, confirming the rounding fix is right). Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_0194bzLUrg6cVCQ7u4NNDpaB --- libavcodec/ac3dsp.c | 2 + libavcodec/ac3dsp.h | 1 + libavcodec/ppc/Makefile | 1 + libavcodec/ppc/ac3dsp.c | 112 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 libavcodec/ppc/ac3dsp.c diff --git a/libavcodec/ac3dsp.c b/libavcodec/ac3dsp.c index a4a28c8..8166278 100644 --- a/libavcodec/ac3dsp.c +++ b/libavcodec/ac3dsp.c @@ -393,6 +393,8 @@ av_cold void ff_ac3dsp_init(AC3DSPContext *c) ff_ac3dsp_init_aarch64(c); #elif ARCH_ARM ff_ac3dsp_init_arm(c); +#elif ARCH_PPC + ff_ac3dsp_init_ppc(c); #elif ARCH_X86 && HAVE_X86ASM ff_ac3dsp_init_x86(c); #elif ARCH_MIPS diff --git a/libavcodec/ac3dsp.h b/libavcodec/ac3dsp.h index b1b2bce..bbb56bd 100644 --- a/libavcodec/ac3dsp.h +++ b/libavcodec/ac3dsp.h @@ -109,6 +109,7 @@ typedef struct AC3DSPContext { void ff_ac3dsp_init(AC3DSPContext *c); void ff_ac3dsp_init_aarch64(AC3DSPContext *c); void ff_ac3dsp_init_arm(AC3DSPContext *c); +void ff_ac3dsp_init_ppc(AC3DSPContext *c); void ff_ac3dsp_init_x86(AC3DSPContext *c); void ff_ac3dsp_init_mips(AC3DSPContext *c); void ff_ac3dsp_init_riscv(AC3DSPContext *c); diff --git a/libavcodec/ppc/Makefile b/libavcodec/ppc/Makefile index 2be552f..7dbdda2 100644 --- a/libavcodec/ppc/Makefile +++ b/libavcodec/ppc/Makefile @@ -1,4 +1,5 @@ # subsystems +OBJS-$(CONFIG_AC3DSP) += ppc/ac3dsp.o OBJS-$(CONFIG_AUDIODSP) += ppc/audiodsp.o OBJS-$(CONFIG_BLOCKDSP) += ppc/blockdsp.o OBJS-$(CONFIG_FDCTDSP) += ppc/fdctdsp.o diff --git a/libavcodec/ppc/ac3dsp.c b/libavcodec/ppc/ac3dsp.c new file mode 100644 index 0000000..059512d --- /dev/null +++ b/libavcodec/ppc/ac3dsp.c @@ -0,0 +1,112 @@ +/* + * AC-3 DSP functions, AltiVec optimized + * + * Copyright (c) 2026 + * + * 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/mem_internal.h" +#include "libavutil/ppc/cpu.h" +#include "libavutil/ppc/util_altivec.h" + +#include "libavcodec/ac3dsp.h" + +#if HAVE_ALTIVEC && HAVE_BIGENDIAN + +/* dst[i] = lrintf(src[i] * (1<<24)): vec_round is PowerPC round-to-nearest + * (ties to even), matching lrintf's default rounding mode -- plain vec_cts + * alone would truncate toward zero instead. Same round-then-convert idiom + * as CTS() in fdctdsp.c. */ +static void float_to_fixed24_altivec(int32_t *dst, const float *src, size_t len) +{ + size_t i; + const vec_f scale = vec_splats((float)(1 << 24)); + vec_f s0, s1; + vec_s32 d0, d1; + + for (i = 0; i < len; i += 8) { + s0 = vec_ld( 0, src + i); + s1 = vec_ld(16, src + i); + s0 = vec_round(vec_madd(s0, scale, (vec_f)vec_splat_u32(0))); + s1 = vec_round(vec_madd(s1, scale, (vec_f)vec_splat_u32(0))); + d0 = vec_cts(s0, 0); + d1 = vec_cts(s1, 0); + vec_st(d0, 0, dst + i); + vec_st(d1, 16, dst + i); + } +} + +static void ac3_sum_square_butterfly_float_altivec(float sum[4], + const float *coef0, + const float *coef1, + int len) +{ + int i; + vec_f vlt, vrt, vmd, vsd; + vec_f zero = (vec_f)vec_splat_u32(0); + vec_f acc0 = zero, acc1 = zero, acc2 = zero, acc3 = zero; + DECLARE_ALIGNED(16, float, tmp)[4]; + + for (i = 0; i < len - 3; i += 4) { + vlt = vec_ld(0, coef0 + i); + vrt = vec_ld(0, coef1 + i); + vmd = vec_add(vlt, vrt); + vsd = vec_sub(vlt, vrt); + acc0 = vec_madd(vlt, vlt, acc0); + acc1 = vec_madd(vrt, vrt, acc1); + acc2 = vec_madd(vmd, vmd, acc2); + acc3 = vec_madd(vsd, vsd, acc3); + } + + vec_st(acc0, 0, tmp); + sum[0] = tmp[0] + tmp[1] + tmp[2] + tmp[3]; + vec_st(acc1, 0, tmp); + sum[1] = tmp[0] + tmp[1] + tmp[2] + tmp[3]; + vec_st(acc2, 0, tmp); + sum[2] = tmp[0] + tmp[1] + tmp[2] + tmp[3]; + vec_st(acc3, 0, tmp); + sum[3] = tmp[0] + tmp[1] + tmp[2] + tmp[3]; + + for (; i < len; i++) { + float lt = coef0[i]; + float rt = coef1[i]; + float md = lt + rt; + float sd = lt - rt; + sum[0] += lt * lt; + sum[1] += rt * rt; + sum[2] += md * md; + sum[3] += sd * sd; + } +} + +#endif /* HAVE_ALTIVEC && HAVE_BIGENDIAN */ + +av_cold void ff_ac3dsp_init_ppc(AC3DSPContext *c) +{ +#if HAVE_ALTIVEC && HAVE_BIGENDIAN + if (!PPC_ALTIVEC(av_get_cpu_flags())) + return; + + c->float_to_fixed24 = float_to_fixed24_altivec; + c->sum_square_butterfly_float = ac3_sum_square_butterfly_float_altivec; +#endif /* HAVE_ALTIVEC && HAVE_BIGENDIAN */ +} -- 2.43.0