diff --git a/libavcodec/alac.c b/libavcodec/alac.c index 146668ec26..c47d64e38d 100644 --- a/libavcodec/alac.c +++ b/libavcodec/alac.c @@ -494,11 +494,11 @@ static int allocate_buffers(ALACContext *alac) alac->direct_output = alac->sample_size > 16; if (!alac->direct_output) { FF_ALLOC_OR_GOTO(alac->avctx, alac->output_samples_buffer[ch], - buf_size, buf_alloc_fail); + buf_size + AV_INPUT_BUFFER_PADDING_SIZE, buf_alloc_fail); } FF_ALLOC_OR_GOTO(alac->avctx, alac->extra_bits_buffer[ch], - buf_size, buf_alloc_fail); + buf_size + AV_INPUT_BUFFER_PADDING_SIZE, buf_alloc_fail); } return 0; buf_alloc_fail: diff --git a/libavcodec/alacdsp.c b/libavcodec/alacdsp.c index 608c0d8915..ecbaedb067 100644 --- a/libavcodec/alacdsp.c +++ b/libavcodec/alacdsp.c @@ -57,4 +57,7 @@ av_cold void ff_alacdsp_init(ALACDSPContext *c) c->decorrelate_stereo = decorrelate_stereo; c->append_extra_bits[0] = c->append_extra_bits[1] = append_extra_bits; + + if (ARCH_X86) + ff_alacdsp_init_x86(c); } diff --git a/libavcodec/alacdsp.h b/libavcodec/alacdsp.h index a7acdbb56a..f8b56dd5dc 100644 --- a/libavcodec/alacdsp.h +++ b/libavcodec/alacdsp.h @@ -29,5 +29,6 @@ typedef struct ALACDSPContext { } ALACDSPContext; void ff_alacdsp_init(ALACDSPContext *c); +void ff_alacdsp_init_x86(ALACDSPContext *c); #endif /* AVCODEC_ALACDSP_H */ diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index 5ff3a77e37..d8b091a266 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -42,6 +42,7 @@ OBJS-$(CONFIG_AAC_DECODER) += x86/aacpsdsp_init.o \ x86/sbrdsp_init.o OBJS-$(CONFIG_ADPCM_G722_DECODER) += x86/g722dsp_init.o OBJS-$(CONFIG_ADPCM_G722_ENCODER) += x86/g722dsp_init.o +OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp_init.o OBJS-$(CONFIG_APNG_DECODER) += x86/pngdsp_init.o OBJS-$(CONFIG_CAVS_DECODER) += x86/cavsdsp.o OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp_init.o @@ -134,6 +135,7 @@ YASM-OBJS-$(CONFIG_AAC_DECODER) += x86/aacpsdsp.o \ x86/sbrdsp.o YASM-OBJS-$(CONFIG_ADPCM_G722_DECODER) += x86/g722dsp.o YASM-OBJS-$(CONFIG_ADPCM_G722_ENCODER) += x86/g722dsp.o +YASM-OBJS-$(CONFIG_ALAC_DECODER) += x86/alacdsp.o YASM-OBJS-$(CONFIG_APNG_DECODER) += x86/pngdsp.o YASM-OBJS-$(CONFIG_DCA_DECODER) += x86/dcadsp.o YASM-OBJS-$(CONFIG_HEVC_DECODER) += x86/hevc_mc.o \ diff --git a/libavcodec/x86/alacdsp.asm b/libavcodec/x86/alacdsp.asm new file mode 100644 index 0000000000..bb2069f785 --- /dev/null +++ b/libavcodec/x86/alacdsp.asm @@ -0,0 +1,133 @@ +;****************************************************************************** +;* ALAC DSP SIMD optimizations +;* +;* Copyright (C) 2015 James Almer +;* +;* 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 .text + +INIT_XMM sse4 +%if ARCH_X86_64 +cglobal alac_decorrelate_stereo, 2, 5, 8, buf0, len, shift, weight, buf1 +%else +cglobal alac_decorrelate_stereo, 2, 3, 8, buf0, len, shift, weight +%define buf1q r2q +%endif + movd m6, shiftm + movd m7, weightm + SPLATD m7 + shl lend, 2 + mov buf1q, [buf0q + gprsize] + mov buf0q, [buf0q] + add buf1q, lenq + add buf0q, lenq + neg lenq + +align 16 +.loop: + mova m0, [buf0q + lenq] + mova m1, [buf0q + lenq + mmsize] + mova m2, [buf1q + lenq] + mova m3, [buf1q + lenq + mmsize] + pmulld m4, m2, m7 + pmulld m5, m3, m7 + psrad m4, m6 + psrad m5, m6 + psubd m0, m4 + psubd m1, m5 + paddd m2, m0 + paddd m3, m1 + mova [buf1q + lenq], m0 + mova [buf1q + lenq + mmsize], m1 + mova [buf0q + lenq], m2 + mova [buf0q + lenq + mmsize], m3 + + add lenq, mmsize*2 + jl .loop + RET + +INIT_XMM sse2 +cglobal alac_append_extra_bits_stereo, 2, 5, 5, buf0, exbuf0, buf1, exbuf1, len + movifnidn lend, lenm + movd m4, r2m ; exbits + shl lend, 2 + mov buf1q, [buf0q + gprsize] + mov buf0q, [buf0q] + mov exbuf1q, [exbuf0q + gprsize] + mov exbuf0q, [exbuf0q] + add buf1q, lenq + add buf0q, lenq + add exbuf1q, lenq + add exbuf0q, lenq + neg lenq + +align 16 +.loop: + mova m0, [buf0q + lenq] + mova m1, [buf0q + lenq + mmsize] + pslld m0, m4 + pslld m1, m4 + mova m2, [buf1q + lenq] + mova m3, [buf1q + lenq + mmsize] + pslld m2, m4 + pslld m3, m4 + por m0, [exbuf0q + lenq] + por m1, [exbuf0q + lenq + mmsize] + por m2, [exbuf1q + lenq] + por m3, [exbuf1q + lenq + mmsize] + mova [buf0q + lenq ], m0 + mova [buf0q + lenq + mmsize], m1 + mova [buf1q + lenq ], m2 + mova [buf1q + lenq + mmsize], m3 + + add lenq, mmsize*2 + jl .loop + REP_RET + +%if ARCH_X86_64 +cglobal alac_append_extra_bits_mono, 2, 5, 3, buf, exbuf, exbits, ch, len +%else +cglobal alac_append_extra_bits_mono, 2, 3, 3, buf, exbuf, len +%define exbitsm r2m +%endif + movifnidn lend, r4m + movd m2, exbitsm + shl lend, 2 + mov bufq, [bufq] + mov exbufq, [exbufq] + add bufq, lenq + add exbufq, lenq + neg lenq + +align 16 +.loop: + mova m0, [bufq + lenq] + mova m1, [bufq + lenq + mmsize] + pslld m0, m2 + pslld m1, m2 + por m0, [exbufq + lenq] + por m1, [exbufq + lenq + mmsize] + mova [bufq + lenq], m0 + mova [bufq + lenq + mmsize], m1 + + add lenq, mmsize*2 + jl .loop + REP_RET diff --git a/libavcodec/x86/alacdsp_init.c b/libavcodec/x86/alacdsp_init.c new file mode 100644 index 0000000000..de5dae6c77 --- /dev/null +++ b/libavcodec/x86/alacdsp_init.c @@ -0,0 +1,44 @@ +/* + * 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/attributes.h" +#include "libavutil/x86/cpu.h" +#include "libavcodec/alacdsp.h" +#include "config.h" + +void ff_alac_decorrelate_stereo_sse4(int32_t *buffer[2], int nb_samples, + int decorr_shift, int decorr_left_weight); +void ff_alac_append_extra_bits_stereo_sse2(int32_t *buffer[2], int32_t *extra_bits_buffer[2], + int extra_bits, int channels, int nb_samples); +void ff_alac_append_extra_bits_mono_sse2(int32_t *buffer[2], int32_t *extra_bits_buffer[2], + int extra_bits, int channels, int nb_samples); + +av_cold void ff_alacdsp_init_x86(ALACDSPContext *c) +{ +#if HAVE_YASM + int cpu_flags = av_get_cpu_flags(); + + if (EXTERNAL_SSE2(cpu_flags)) { + c->append_extra_bits[0] = ff_alac_append_extra_bits_mono_sse2; + c->append_extra_bits[1] = ff_alac_append_extra_bits_stereo_sse2; + } + if (EXTERNAL_SSE4(cpu_flags)) { + c->decorrelate_stereo = ff_alac_decorrelate_stereo_sse4; + } +#endif /* HAVE_YASM */ +}