ffmpeg | branch: master | Clément Bœsch <u...@pkh.me> | Wed Mar 22 11:11:28 2017 +0100| [e39d4ff150f45d82aabafa5a34f5c9ec7a829d15] | committer: Clément Bœsch
Merge commit '43717469f9daa402f6acb48997255827a56034e9' * commit '43717469f9daa402f6acb48997255827a56034e9': ac3dsp: Reverse matrix in/out order in downmix() Merged-by: Clément Bœsch <u...@pkh.me> > http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=e39d4ff150f45d82aabafa5a34f5c9ec7a829d15 --- libavcodec/ac3dec.c | 46 +++++++++++++++++++++++++++++--------------- libavcodec/ac3dec.h | 2 +- libavcodec/ac3dec_fixed.c | 8 ++++---- libavcodec/ac3dsp.c | 16 +++++++-------- libavcodec/ac3dsp.h | 4 ++-- libavcodec/x86/ac3dsp_init.c | 36 ++++++++++++++++++---------------- 6 files changed, 64 insertions(+), 48 deletions(-) diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index 003ce17..f9bab94 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -362,52 +362,62 @@ static int parse_frame_header(AC3DecodeContext *s) * Set stereo downmixing coefficients based on frame header info. * reference: Section 7.8.2 Downmixing Into Two Channels */ -static void set_downmix_coeffs(AC3DecodeContext *s) +static int set_downmix_coeffs(AC3DecodeContext *s) { int i; float cmix = gain_levels[s-> center_mix_level]; float smix = gain_levels[s->surround_mix_level]; float norm0, norm1; - float downmix_coeffs[AC3_MAX_CHANNELS][2]; + float downmix_coeffs[2][AC3_MAX_CHANNELS]; + + if (!s->downmix_coeffs[0]) { + s->downmix_coeffs[0] = av_malloc_array(2 * AC3_MAX_CHANNELS, + sizeof(**s->downmix_coeffs)); + if (!s->downmix_coeffs[0]) + return AVERROR(ENOMEM); + s->downmix_coeffs[1] = s->downmix_coeffs[0] + AC3_MAX_CHANNELS; + } for (i = 0; i < s->fbw_channels; i++) { - downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]]; - downmix_coeffs[i][1] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]]; + downmix_coeffs[0][i] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]]; + downmix_coeffs[1][i] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]]; } if (s->channel_mode > 1 && s->channel_mode & 1) { - downmix_coeffs[1][0] = downmix_coeffs[1][1] = cmix; + downmix_coeffs[0][1] = downmix_coeffs[1][1] = cmix; } if (s->channel_mode == AC3_CHMODE_2F1R || s->channel_mode == AC3_CHMODE_3F1R) { int nf = s->channel_mode - 2; - downmix_coeffs[nf][0] = downmix_coeffs[nf][1] = smix * LEVEL_MINUS_3DB; + downmix_coeffs[0][nf] = downmix_coeffs[1][nf] = smix * LEVEL_MINUS_3DB; } if (s->channel_mode == AC3_CHMODE_2F2R || s->channel_mode == AC3_CHMODE_3F2R) { int nf = s->channel_mode - 4; - downmix_coeffs[nf][0] = downmix_coeffs[nf+1][1] = smix; + downmix_coeffs[0][nf] = downmix_coeffs[1][nf+1] = smix; } /* renormalize */ norm0 = norm1 = 0.0; for (i = 0; i < s->fbw_channels; i++) { - norm0 += downmix_coeffs[i][0]; - norm1 += downmix_coeffs[i][1]; + norm0 += downmix_coeffs[0][i]; + norm1 += downmix_coeffs[1][i]; } norm0 = 1.0f / norm0; norm1 = 1.0f / norm1; for (i = 0; i < s->fbw_channels; i++) { - downmix_coeffs[i][0] *= norm0; - downmix_coeffs[i][1] *= norm1; + downmix_coeffs[0][i] *= norm0; + downmix_coeffs[1][i] *= norm1; } if (s->output_mode == AC3_CHMODE_MONO) { for (i = 0; i < s->fbw_channels; i++) - downmix_coeffs[i][0] = (downmix_coeffs[i][0] + - downmix_coeffs[i][1]) * LEVEL_MINUS_3DB; + downmix_coeffs[0][i] = (downmix_coeffs[0][i] + + downmix_coeffs[1][i]) * LEVEL_MINUS_3DB; } for (i = 0; i < s->fbw_channels; i++) { - s->downmix_coeffs[i][0] = FIXR12(downmix_coeffs[i][0]); - s->downmix_coeffs[i][1] = FIXR12(downmix_coeffs[i][1]); + s->downmix_coeffs[0][i] = FIXR12(downmix_coeffs[0][i]); + s->downmix_coeffs[1][i] = FIXR12(downmix_coeffs[1][i]); } + + return 0; } /** @@ -1562,7 +1572,10 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, /* set downmixing coefficients if needed */ if (s->channels != s->out_channels && !((s->output_mode & AC3_OUTPUT_LFEON) && s->fbw_channels == s->out_channels)) { - set_downmix_coeffs(s); + if ((ret = set_downmix_coeffs(s)) < 0) { + av_log(avctx, AV_LOG_ERROR, "error setting downmix coeffs\n"); + return ret; + } } } else if (!s->channels) { av_log(avctx, AV_LOG_ERROR, "unable to determine channel mode\n"); @@ -1685,6 +1698,7 @@ static av_cold int ac3_decode_end(AVCodecContext *avctx) ff_mdct_end(&s->imdct_512); ff_mdct_end(&s->imdct_256); av_freep(&s->fdsp); + av_freep(&s->downmix_coeffs[0]); return 0; } diff --git a/libavcodec/ac3dec.h b/libavcodec/ac3dec.h index 495e9a6..bac661c 100644 --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@ -159,7 +159,7 @@ typedef struct AC3DecodeContext { int fbw_channels; ///< number of full-bandwidth channels int channels; ///< number of total channels int lfe_ch; ///< index of LFE channel - SHORTFLOAT downmix_coeffs[AC3_MAX_CHANNELS][2]; ///< stereo downmix coefficients + SHORTFLOAT *downmix_coeffs[2]; ///< stereo downmix coefficients int downmixed; ///< indicates if coeffs are currently downmixed int output_mode; ///< output channel configuration int out_channels; ///< number of output channels diff --git a/libavcodec/ac3dec_fixed.c b/libavcodec/ac3dec_fixed.c index 1f79ade..682fe93 100644 --- a/libavcodec/ac3dec_fixed.c +++ b/libavcodec/ac3dec_fixed.c @@ -139,7 +139,7 @@ static void scale_coefs ( * Downmix samples from original signal to stereo or mono (this is for 16-bit samples * and fixed point decoder - original (for 32-bit samples) is in ac3dsp.c). */ -static void ac3_downmix_c_fixed16(int16_t **samples, int16_t (*matrix)[2], +static void ac3_downmix_c_fixed16(int16_t **samples, int16_t **matrix, int out_ch, int in_ch, int len) { int i, j; @@ -148,8 +148,8 @@ static void ac3_downmix_c_fixed16(int16_t **samples, int16_t (*matrix)[2], for (i = 0; i < len; i++) { v0 = v1 = 0; for (j = 0; j < in_ch; j++) { - v0 += samples[j][i] * matrix[j][0]; - v1 += samples[j][i] * matrix[j][1]; + v0 += samples[j][i] * matrix[0][j]; + v1 += samples[j][i] * matrix[1][j]; } samples[0][i] = (v0+2048)>>12; samples[1][i] = (v1+2048)>>12; @@ -158,7 +158,7 @@ static void ac3_downmix_c_fixed16(int16_t **samples, int16_t (*matrix)[2], for (i = 0; i < len; i++) { v0 = 0; for (j = 0; j < in_ch; j++) - v0 += samples[j][i] * matrix[j][0]; + v0 += samples[j][i] * matrix[0][j]; samples[0][i] = (v0+2048)>>12; } } diff --git a/libavcodec/ac3dsp.c b/libavcodec/ac3dsp.c index 9902f90..23abc56 100644 --- a/libavcodec/ac3dsp.c +++ b/libavcodec/ac3dsp.c @@ -213,7 +213,7 @@ static void ac3_sum_square_butterfly_float_c(float sum[4], } } -static void ac3_downmix_c(float **samples, float (*matrix)[2], +static void ac3_downmix_c(float **samples, float **matrix, int out_ch, int in_ch, int len) { int i, j; @@ -222,8 +222,8 @@ static void ac3_downmix_c(float **samples, float (*matrix)[2], for (i = 0; i < len; i++) { v0 = v1 = 0.0f; for (j = 0; j < in_ch; j++) { - v0 += samples[j][i] * matrix[j][0]; - v1 += samples[j][i] * matrix[j][1]; + v0 += samples[j][i] * matrix[0][j]; + v1 += samples[j][i] * matrix[1][j]; } samples[0][i] = v0; samples[1][i] = v1; @@ -232,13 +232,13 @@ static void ac3_downmix_c(float **samples, float (*matrix)[2], for (i = 0; i < len; i++) { v0 = 0.0f; for (j = 0; j < in_ch; j++) - v0 += samples[j][i] * matrix[j][0]; + v0 += samples[j][i] * matrix[0][j]; samples[0][i] = v0; } } } -static void ac3_downmix_c_fixed(int32_t **samples, int16_t (*matrix)[2], +static void ac3_downmix_c_fixed(int32_t **samples, int16_t **matrix, int out_ch, int in_ch, int len) { int i, j; @@ -247,8 +247,8 @@ static void ac3_downmix_c_fixed(int32_t **samples, int16_t (*matrix)[2], for (i = 0; i < len; i++) { v0 = v1 = 0; for (j = 0; j < in_ch; j++) { - v0 += (int64_t)samples[j][i] * matrix[j][0]; - v1 += (int64_t)samples[j][i] * matrix[j][1]; + v0 += (int64_t)samples[j][i] * matrix[0][j]; + v1 += (int64_t)samples[j][i] * matrix[1][j]; } samples[0][i] = (v0+2048)>>12; samples[1][i] = (v1+2048)>>12; @@ -257,7 +257,7 @@ static void ac3_downmix_c_fixed(int32_t **samples, int16_t (*matrix)[2], for (i = 0; i < len; i++) { v0 = 0; for (j = 0; j < in_ch; j++) - v0 += (int64_t)samples[j][i] * matrix[j][0]; + v0 += (int64_t)samples[j][i] * matrix[0][j]; samples[0][i] = (v0+2048)>>12; } } diff --git a/libavcodec/ac3dsp.h b/libavcodec/ac3dsp.h index ed98c8c..b4de307 100644 --- a/libavcodec/ac3dsp.h +++ b/libavcodec/ac3dsp.h @@ -132,10 +132,10 @@ typedef struct AC3DSPContext { void (*sum_square_butterfly_float)(float sum[4], const float *coef0, const float *coef1, int len); - void (*downmix)(float **samples, float (*matrix)[2], int out_ch, + void (*downmix)(float **samples, float **matrix, int out_ch, int in_ch, int len); - void (*downmix_fixed)(int32_t **samples, int16_t (*matrix)[2], int out_ch, + void (*downmix_fixed)(int32_t **samples, int16_t **matrix, int out_ch, int in_ch, int len); /** diff --git a/libavcodec/x86/ac3dsp_init.c b/libavcodec/x86/ac3dsp_init.c index 9fd0aef..edb6c60 100644 --- a/libavcodec/x86/ac3dsp_init.c +++ b/libavcodec/x86/ac3dsp_init.c @@ -76,8 +76,8 @@ void ff_apply_window_int16_ssse3_atom(int16_t *output, const int16_t *input, #define MIX5(mono, stereo) \ __asm__ volatile ( \ "movss 0(%1), %%xmm5 \n" \ - "movss 8(%1), %%xmm6 \n" \ - "movss 24(%1), %%xmm7 \n" \ + "movss 4(%1), %%xmm6 \n" \ + "movss 12(%1), %%xmm7 \n" \ "shufps $0, %%xmm5, %%xmm5 \n" \ "shufps $0, %%xmm6, %%xmm6 \n" \ "shufps $0, %%xmm7, %%xmm7 \n" \ @@ -102,7 +102,7 @@ void ff_apply_window_int16_ssse3_atom(int16_t *output, const int16_t *input, "add $16, %0 \n" \ "jl 1b \n" \ : "+&r"(i) \ - : "r"(matrix), \ + : "r"(matrix[0]), \ "r"(samples[0] + len), \ "r"(samples[1] + len), \ "r"(samples[2] + len), \ @@ -146,22 +146,22 @@ void ff_apply_window_int16_ssse3_atom(int16_t *output, const int16_t *input, : "memory" \ ); -static void ac3_downmix_sse(float **samples, float (*matrix)[2], +static void ac3_downmix_sse(float **samples, float **matrix, int out_ch, int in_ch, int len) { - int (*matrix_cmp)[2] = (int(*)[2])matrix; + int **matrix_cmp = (int **)matrix; intptr_t i, j, k, m; i = -len * sizeof(float); if (in_ch == 5 && out_ch == 2 && - !(matrix_cmp[0][1] | matrix_cmp[2][0] | - matrix_cmp[3][1] | matrix_cmp[4][0] | - (matrix_cmp[1][0] ^ matrix_cmp[1][1]) | - (matrix_cmp[0][0] ^ matrix_cmp[2][1]))) { + !(matrix_cmp[1][0] | matrix_cmp[0][2] | + matrix_cmp[1][3] | matrix_cmp[0][4] | + (matrix_cmp[0][1] ^ matrix_cmp[1][1]) | + (matrix_cmp[0][0] ^ matrix_cmp[1][2]))) { MIX5(IF0, IF1); } else if (in_ch == 5 && out_ch == 1 && - matrix_cmp[0][0] == matrix_cmp[2][0] && - matrix_cmp[3][0] == matrix_cmp[4][0]) { + matrix_cmp[0][0] == matrix_cmp[0][2] && + matrix_cmp[0][3] == matrix_cmp[0][4]) { MIX5(IF1, IF0); } else { LOCAL_ALIGNED(16, float, matrix_simd, [AC3_MAX_CHANNELS], [2][4]); @@ -171,18 +171,20 @@ static void ac3_downmix_sse(float **samples, float (*matrix)[2], samp[j] = samples[j] + len; j = 2 * in_ch * sizeof(float); + k = in_ch * sizeof(float); __asm__ volatile ( "1: \n" + "sub $4, %1 \n" "sub $8, %0 \n" - "movss (%2, %0), %%xmm4 \n" - "movss 4(%2, %0), %%xmm5 \n" + "movss (%3, %1), %%xmm4 \n" + "movss (%4, %1), %%xmm5 \n" "shufps $0, %%xmm4, %%xmm4 \n" "shufps $0, %%xmm5, %%xmm5 \n" - "movaps %%xmm4, (%1, %0, 4) \n" - "movaps %%xmm5, 16(%1, %0, 4) \n" + "movaps %%xmm4, (%2, %0, 4) \n" + "movaps %%xmm5, 16(%2, %0, 4) \n" "jg 1b \n" - : "+&r"(j) - : "r"(matrix_simd), "r"(matrix) + : "+&r"(j), "+&r"(k) + : "r"(matrix_simd), "r"(matrix[0]), "r"(matrix[1]) : "memory" ); if (out_ch == 2) { ====================================================================== diff --cc libavcodec/ac3dec.c index 003ce17,aba3119..f9bab94 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@@ -368,46 -338,51 +368,56 @@@ static int set_downmix_coeffs(AC3Decode float cmix = gain_levels[s-> center_mix_level]; float smix = gain_levels[s->surround_mix_level]; float norm0, norm1; - float downmix_coeffs[AC3_MAX_CHANNELS][2]; ++ float downmix_coeffs[2][AC3_MAX_CHANNELS]; + + if (!s->downmix_coeffs[0]) { - s->downmix_coeffs[0] = av_malloc(2 * AC3_MAX_CHANNELS * - sizeof(**s->downmix_coeffs)); ++ s->downmix_coeffs[0] = av_malloc_array(2 * AC3_MAX_CHANNELS, ++ sizeof(**s->downmix_coeffs)); + if (!s->downmix_coeffs[0]) + return AVERROR(ENOMEM); + s->downmix_coeffs[1] = s->downmix_coeffs[0] + AC3_MAX_CHANNELS; + } for (i = 0; i < s->fbw_channels; i++) { - downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]]; - downmix_coeffs[i][1] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]]; - s->downmix_coeffs[0][i] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]]; - s->downmix_coeffs[1][i] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]]; ++ downmix_coeffs[0][i] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]]; ++ downmix_coeffs[1][i] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]]; } if (s->channel_mode > 1 && s->channel_mode & 1) { - downmix_coeffs[1][0] = downmix_coeffs[1][1] = cmix; - s->downmix_coeffs[0][1] = s->downmix_coeffs[1][1] = cmix; ++ downmix_coeffs[0][1] = downmix_coeffs[1][1] = cmix; } if (s->channel_mode == AC3_CHMODE_2F1R || s->channel_mode == AC3_CHMODE_3F1R) { int nf = s->channel_mode - 2; - downmix_coeffs[nf][0] = downmix_coeffs[nf][1] = smix * LEVEL_MINUS_3DB; - s->downmix_coeffs[0][nf] = s->downmix_coeffs[1][nf] = smix * LEVEL_MINUS_3DB; ++ downmix_coeffs[0][nf] = downmix_coeffs[1][nf] = smix * LEVEL_MINUS_3DB; } if (s->channel_mode == AC3_CHMODE_2F2R || s->channel_mode == AC3_CHMODE_3F2R) { int nf = s->channel_mode - 4; - downmix_coeffs[nf][0] = downmix_coeffs[nf+1][1] = smix; - s->downmix_coeffs[0][nf] = s->downmix_coeffs[1][nf+1] = smix; ++ downmix_coeffs[0][nf] = downmix_coeffs[1][nf+1] = smix; } /* renormalize */ norm0 = norm1 = 0.0; for (i = 0; i < s->fbw_channels; i++) { - norm0 += downmix_coeffs[i][0]; - norm1 += downmix_coeffs[i][1]; - norm0 += s->downmix_coeffs[0][i]; - norm1 += s->downmix_coeffs[1][i]; ++ norm0 += downmix_coeffs[0][i]; ++ norm1 += downmix_coeffs[1][i]; } norm0 = 1.0f / norm0; norm1 = 1.0f / norm1; for (i = 0; i < s->fbw_channels; i++) { - downmix_coeffs[i][0] *= norm0; - downmix_coeffs[i][1] *= norm1; - s->downmix_coeffs[0][i] *= norm0; - s->downmix_coeffs[1][i] *= norm1; ++ downmix_coeffs[0][i] *= norm0; ++ downmix_coeffs[1][i] *= norm1; } if (s->output_mode == AC3_CHMODE_MONO) { for (i = 0; i < s->fbw_channels; i++) - downmix_coeffs[i][0] = (downmix_coeffs[i][0] + - downmix_coeffs[i][1]) * LEVEL_MINUS_3DB; - s->downmix_coeffs[0][i] = (s->downmix_coeffs[0][i] + - s->downmix_coeffs[1][i]) * LEVEL_MINUS_3DB; ++ downmix_coeffs[0][i] = (downmix_coeffs[0][i] + ++ downmix_coeffs[1][i]) * LEVEL_MINUS_3DB; + } + for (i = 0; i < s->fbw_channels; i++) { - s->downmix_coeffs[i][0] = FIXR12(downmix_coeffs[i][0]); - s->downmix_coeffs[i][1] = FIXR12(downmix_coeffs[i][1]); ++ s->downmix_coeffs[0][i] = FIXR12(downmix_coeffs[0][i]); ++ s->downmix_coeffs[1][i] = FIXR12(downmix_coeffs[1][i]); } + + return 0; } /** @@@ -1684,7 -1579,7 +1697,8 @@@ static av_cold int ac3_decode_end(AVCod AC3DecodeContext *s = avctx->priv_data; ff_mdct_end(&s->imdct_512); ff_mdct_end(&s->imdct_256); + av_freep(&s->fdsp); + av_freep(&s->downmix_coeffs[0]); return 0; } diff --cc libavcodec/ac3dec.h index 495e9a6,4a7e281..bac661c --- a/libavcodec/ac3dec.h +++ b/libavcodec/ac3dec.h @@@ -159,7 -147,7 +159,7 @@@ typedef struct AC3DecodeContext int fbw_channels; ///< number of full-bandwidth channels int channels; ///< number of total channels int lfe_ch; ///< index of LFE channel - SHORTFLOAT downmix_coeffs[AC3_MAX_CHANNELS][2]; ///< stereo downmix coefficients - float *downmix_coeffs[2]; ///< stereo downmix coefficients ++ SHORTFLOAT *downmix_coeffs[2]; ///< stereo downmix coefficients int downmixed; ///< indicates if coeffs are currently downmixed int output_mode; ///< output channel configuration int out_channels; ///< number of output channels diff --cc libavcodec/ac3dec_fixed.c index 1f79ade,0000000..682fe93 mode 100644,000000..100644 --- a/libavcodec/ac3dec_fixed.c +++ b/libavcodec/ac3dec_fixed.c @@@ -1,197 -1,0 +1,197 @@@ +/* + * Copyright (c) 2012 + * MIPS Technologies, Inc., California. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE MIPS TECHNOLOGIES, INC. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Author: Stanislav Ocovaj (soco...@mips.com) + * + * AC3 fixed-point decoder for MIPS platforms + * + * 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 + */ + +#define FFT_FLOAT 0 +#define USE_FIXED 1 +#define FFT_FIXED_32 1 +#include "ac3dec.h" + + +static const int end_freq_inv_tab[8] = +{ + 50529027, 44278013, 39403370, 32292987, 27356480, 23729101, 20951060, 18755316 +}; + +static void scale_coefs ( + int32_t *dst, + const int32_t *src, + int dynrng, + int len) +{ + int i, shift, round; + int16_t mul; + int temp, temp1, temp2, temp3, temp4, temp5, temp6, temp7; + + mul = (dynrng & 0x1f) + 0x20; + shift = 4 - ((dynrng << 23) >> 28); + if (shift > 0 ) { + round = 1 << (shift-1); + for (i=0; i<len; i+=8) { + + temp = src[i] * mul; + temp1 = src[i+1] * mul; + temp = temp + round; + temp2 = src[i+2] * mul; + + temp1 = temp1 + round; + dst[i] = temp >> shift; + temp3 = src[i+3] * mul; + temp2 = temp2 + round; + + dst[i+1] = temp1 >> shift; + temp4 = src[i + 4] * mul; + temp3 = temp3 + round; + dst[i+2] = temp2 >> shift; + + temp5 = src[i+5] * mul; + temp4 = temp4 + round; + dst[i+3] = temp3 >> shift; + temp6 = src[i+6] * mul; + + dst[i+4] = temp4 >> shift; + temp5 = temp5 + round; + temp7 = src[i+7] * mul; + temp6 = temp6 + round; + + dst[i+5] = temp5 >> shift; + temp7 = temp7 + round; + dst[i+6] = temp6 >> shift; + dst[i+7] = temp7 >> shift; + + } + } else { + shift = -shift; + for (i=0; i<len; i+=8) { + + temp = src[i] * mul; + temp1 = src[i+1] * mul; + temp2 = src[i+2] * mul; + + dst[i] = temp << shift; + temp3 = src[i+3] * mul; + + dst[i+1] = temp1 << shift; + temp4 = src[i + 4] * mul; + dst[i+2] = temp2 << shift; + + temp5 = src[i+5] * mul; + dst[i+3] = temp3 << shift; + temp6 = src[i+6] * mul; + + dst[i+4] = temp4 << shift; + temp7 = src[i+7] * mul; + + dst[i+5] = temp5 << shift; + dst[i+6] = temp6 << shift; + dst[i+7] = temp7 << shift; + + } + } +} + +/** + * Downmix samples from original signal to stereo or mono (this is for 16-bit samples + * and fixed point decoder - original (for 32-bit samples) is in ac3dsp.c). + */ - static void ac3_downmix_c_fixed16(int16_t **samples, int16_t (*matrix)[2], ++static void ac3_downmix_c_fixed16(int16_t **samples, int16_t **matrix, + int out_ch, int in_ch, int len) +{ + int i, j; + int v0, v1; + if (out_ch == 2) { + for (i = 0; i < len; i++) { + v0 = v1 = 0; + for (j = 0; j < in_ch; j++) { - v0 += samples[j][i] * matrix[j][0]; - v1 += samples[j][i] * matrix[j][1]; ++ v0 += samples[j][i] * matrix[0][j]; ++ v1 += samples[j][i] * matrix[1][j]; + } + samples[0][i] = (v0+2048)>>12; + samples[1][i] = (v1+2048)>>12; + } + } else if (out_ch == 1) { + for (i = 0; i < len; i++) { + v0 = 0; + for (j = 0; j < in_ch; j++) - v0 += samples[j][i] * matrix[j][0]; ++ v0 += samples[j][i] * matrix[0][j]; + samples[0][i] = (v0+2048)>>12; + } + } +} + +#include "eac3dec.c" +#include "ac3dec.c" + +static const AVOption options[] = { + { "cons_noisegen", "enable consistent noise generation", OFFSET(consistent_noise_generation), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, PAR }, + { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR }, + { "heavy_compr", "enable heavy dynamic range compression", OFFSET(heavy_compression), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, PAR }, + { NULL}, +}; + +static const AVClass ac3_decoder_class = { + .class_name = "Fixed-Point AC-3 Decoder", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVCodec ff_ac3_fixed_decoder = { + .name = "ac3_fixed", + .type = AVMEDIA_TYPE_AUDIO, + .id = AV_CODEC_ID_AC3, + .priv_data_size = sizeof (AC3DecodeContext), + .init = ac3_decode_init, + .close = ac3_decode_end, + .decode = ac3_decode_frame, + .capabilities = AV_CODEC_CAP_DR1, + .long_name = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"), + .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16P, + AV_SAMPLE_FMT_NONE }, + .priv_class = &ac3_decoder_class, +}; diff --cc libavcodec/ac3dsp.c index 9902f90,d1bf37e..23abc56 --- a/libavcodec/ac3dsp.c +++ b/libavcodec/ac3dsp.c @@@ -171,49 -171,7 +171,49 @@@ static void ac3_extract_exponents_c(uin } } +static void ac3_sum_square_butterfly_int32_c(int64_t sum[4], + const int32_t *coef0, + const int32_t *coef1, + int len) +{ + int i; + + sum[0] = sum[1] = sum[2] = sum[3] = 0; + + for (i = 0; i < len; i++) { + int lt = coef0[i]; + int rt = coef1[i]; + int md = lt + rt; + int sd = lt - rt; + MAC64(sum[0], lt, lt); + MAC64(sum[1], rt, rt); + MAC64(sum[2], md, md); + MAC64(sum[3], sd, sd); + } +} + +static void ac3_sum_square_butterfly_float_c(float sum[4], + const float *coef0, + const float *coef1, + int len) +{ + int i; + + sum[0] = sum[1] = sum[2] = sum[3] = 0; + + for (i = 0; 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; + } +} + - static void ac3_downmix_c(float **samples, float (*matrix)[2], + static void ac3_downmix_c(float **samples, float **matrix, int out_ch, int in_ch, int len) { int i, j; @@@ -238,31 -196,6 +238,31 @@@ } } - static void ac3_downmix_c_fixed(int32_t **samples, int16_t (*matrix)[2], ++static void ac3_downmix_c_fixed(int32_t **samples, int16_t **matrix, + int out_ch, int in_ch, int len) +{ + int i, j; + int64_t v0, v1; + if (out_ch == 2) { + for (i = 0; i < len; i++) { + v0 = v1 = 0; + for (j = 0; j < in_ch; j++) { - v0 += (int64_t)samples[j][i] * matrix[j][0]; - v1 += (int64_t)samples[j][i] * matrix[j][1]; ++ v0 += (int64_t)samples[j][i] * matrix[0][j]; ++ v1 += (int64_t)samples[j][i] * matrix[1][j]; + } + samples[0][i] = (v0+2048)>>12; + samples[1][i] = (v1+2048)>>12; + } + } else if (out_ch == 1) { + for (i = 0; i < len; i++) { + v0 = 0; + for (j = 0; j < in_ch; j++) - v0 += (int64_t)samples[j][i] * matrix[j][0]; ++ v0 += (int64_t)samples[j][i] * matrix[0][j]; + samples[0][i] = (v0+2048)>>12; + } + } +} + static void apply_window_int16_c(int16_t *output, const int16_t *input, const int16_t *window, unsigned int len) { diff --cc libavcodec/ac3dsp.h index ed98c8c,cdce21a..b4de307 --- a/libavcodec/ac3dsp.h +++ b/libavcodec/ac3dsp.h @@@ -126,18 -126,9 +126,18 @@@ typedef struct AC3DSPContext void (*extract_exponents)(uint8_t *exp, int32_t *coef, int nb_coefs); + void (*sum_square_butterfly_int32)(int64_t sum[4], const int32_t *coef0, + const int32_t *coef1, int len); + + void (*sum_square_butterfly_float)(float sum[4], const float *coef0, + const float *coef1, int len); + - void (*downmix)(float **samples, float (*matrix)[2], int out_ch, + void (*downmix)(float **samples, float **matrix, int out_ch, int in_ch, int len); - void (*downmix_fixed)(int32_t **samples, int16_t (*matrix)[2], int out_ch, ++ void (*downmix_fixed)(int32_t **samples, int16_t **matrix, int out_ch, + int in_ch, int len); + /** * Apply symmetric window in 16-bit fixed-point. * @param output destination array diff --cc libavcodec/x86/ac3dsp_init.c index 9fd0aef,9036389..edb6c60 --- a/libavcodec/x86/ac3dsp_init.c +++ b/libavcodec/x86/ac3dsp_init.c @@@ -154,17 -149,17 +154,17 @@@ static void ac3_downmix_sse(float **sam i = -len * sizeof(float); if (in_ch == 5 && out_ch == 2 && - !(matrix_cmp[0][1] | matrix_cmp[2][0] | - matrix_cmp[3][1] | matrix_cmp[4][0] | - (matrix_cmp[1][0] ^ matrix_cmp[1][1]) | - (matrix_cmp[0][0] ^ matrix_cmp[2][1]))) { + !(matrix_cmp[1][0] | matrix_cmp[0][2] | + matrix_cmp[1][3] | matrix_cmp[0][4] | + (matrix_cmp[0][1] ^ matrix_cmp[1][1]) | + (matrix_cmp[0][0] ^ matrix_cmp[1][2]))) { MIX5(IF0, IF1); } else if (in_ch == 5 && out_ch == 1 && - matrix_cmp[0][0] == matrix_cmp[2][0] && - matrix_cmp[3][0] == matrix_cmp[4][0]) { + matrix_cmp[0][0] == matrix_cmp[0][2] && + matrix_cmp[0][3] == matrix_cmp[0][4]) { MIX5(IF1, IF0); } else { - DECLARE_ALIGNED(16, float, matrix_simd)[AC3_MAX_CHANNELS][2][4]; + LOCAL_ALIGNED(16, float, matrix_simd, [AC3_MAX_CHANNELS], [2][4]); float *samp[AC3_MAX_CHANNELS]; for (j = 0; j < in_ch; j++) _______________________________________________ ffmpeg-cvslog mailing list ffmpeg-cvslog@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog