Merge commit 'a5ebe5d1217942238c641c83b24ef1106e53934a'
authorClément Bœsch <u@pkh.me>
Wed, 15 Mar 2017 20:43:59 +0000 (21:43 +0100)
committerClément Bœsch <u@pkh.me>
Wed, 15 Mar 2017 20:43:59 +0000 (21:43 +0100)
* commit 'a5ebe5d1217942238c641c83b24ef1106e53934a':
  ac3dec: Split spx-specific code from decode_audio_block()

Merged-by: Clément Bœsch <u@pkh.me>
1  2 
libavcodec/ac3dec.c

diff --combined libavcodec/ac3dec.c
@@@ -7,20 -7,20 +7,20 @@@
   * Copyright (c) 2007-2008 Bartlomiej Wolowiec <bartek.wolowiec@gmail.com>
   * Copyright (c) 2007 Justin Ruggles <justin.ruggles@gmail.com>
   *
 - * This file is part of Libav.
 + * This file is part of FFmpeg.
   *
 - * Libav is free software; you can redistribute it and/or
 + * 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.
   *
 - * Libav is distributed in the hope that it will be useful,
 + * 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 Libav; if not, write to the Free Software
 + * License along with FFmpeg; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
   */
  
@@@ -63,11 -63,8 +63,11 @@@ static const uint8_t quantization_tab[1
      5, 6, 7, 8, 9, 10, 11, 12, 14, 16
  };
  
 +#if (!USE_FIXED)
  /** dynamic range table. converts codes to scale factors. */
  static float dynamic_range_tab[256];
 +float ff_ac3_heavy_dynamic_range_tab[256];
 +#endif
  
  /** Adjustments in dB gain */
  static const float gain_levels[9] = {
@@@ -114,7 -111,7 +114,7 @@@ static const uint8_t ac3_default_coeffs
  static inline int
  symmetric_dequant(int code, int levels)
  {
 -    return ((code - (levels >> 1)) << 24) / levels;
 +    return ((code - (levels >> 1)) * (1 << 24)) / levels;
  }
  
  /*
@@@ -161,21 -158,12 +161,21 @@@ static av_cold void ac3_tables_init(voi
          b5_mantissas[i] = symmetric_dequant(i, 15);
      }
  
 +#if (!USE_FIXED)
      /* generate dynamic range table
         reference: Section 7.7.1 Dynamic Range Control */
      for (i = 0; i < 256; i++) {
          int v = (i >> 5) - ((i >> 7) << 3) - 5;
          dynamic_range_tab[i] = powf(2.0f, v) * ((i & 0x1F) | 0x20);
      }
 +
 +    /* generate compr dynamic range table
 +       reference: Section 7.7.2 Heavy Compression */
 +    for (i = 0; i < 256; i++) {
 +        int v = (i >> 4) - ((i >> 7) << 4) - 4;
 +        ff_ac3_heavy_dynamic_range_tab[i] = powf(2.0f, v) * ((i & 0xF) | 0x10);
 +    }
 +#endif
  }
  
  /**
@@@ -188,26 -176,18 +188,26 @@@ static av_cold int ac3_decode_init(AVCo
  
      s->avctx = avctx;
  
 -    ff_ac3_common_init();
      ac3_tables_init();
      ff_mdct_init(&s->imdct_256, 8, 1, 1.0);
      ff_mdct_init(&s->imdct_512, 9, 1, 1.0);
 -    ff_kbd_window_init(s->window, 5.0, 256);
 +    AC3_RENAME(ff_kbd_window_init)(s->window, 5.0, 256);
      ff_bswapdsp_init(&s->bdsp);
 -    avpriv_float_dsp_init(&s->fdsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
 -    ff_ac3dsp_init(&s->ac3dsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
 +
 +#if (USE_FIXED)
 +    s->fdsp = avpriv_alloc_fixed_dsp(avctx->flags & AV_CODEC_FLAG_BITEXACT);
 +#else
 +    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);
      ff_fmt_convert_init(&s->fmt_conv, avctx);
 +#endif
 +
 +    ff_ac3dsp_init(&s->ac3dsp, avctx->flags & AV_CODEC_FLAG_BITEXACT);
      av_lfg_init(&s->dith_state, 0);
  
 -    avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
 +    if (USE_FIXED)
 +        avctx->sample_fmt = AV_SAMPLE_FMT_S16P;
 +    else
 +        avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
  
      /* allow downmixing to stereo or mono */
      if (avctx->channels > 1 &&
@@@ -239,19 -219,9 +239,19 @@@ static int ac3_parse_header(AC3DecodeCo
      /* read the rest of the bsi. read twice for dual mono mode. */
      i = !s->channel_mode;
      do {
 -        skip_bits(gbc, 5); // skip dialog normalization
 -        if (get_bits1(gbc))
 -            skip_bits(gbc, 8); //skip compression
 +        s->dialog_normalization[(!s->channel_mode)-i] = -get_bits(gbc, 5);
 +        if (s->dialog_normalization[(!s->channel_mode)-i] == 0) {
 +            s->dialog_normalization[(!s->channel_mode)-i] = -31;
 +        }
 +        if (s->target_level != 0) {
 +            s->level_gain[(!s->channel_mode)-i] = powf(2.0f,
 +                (float)(s->target_level -
 +                s->dialog_normalization[(!s->channel_mode)-i])/6.0f);
 +        }
 +        if (s->compression_exists[(!s->channel_mode)-i] = get_bits1(gbc)) {
 +            s->heavy_dynamic_range[(!s->channel_mode)-i] =
 +                AC3_HEAVY_RANGE(get_bits(gbc, 8));
 +        }
          if (get_bits1(gbc))
              skip_bits(gbc, 8); //skip language code
          if (get_bits1(gbc))
   */
  static int parse_frame_header(AC3DecodeContext *s)
  {
 -    AC3HeaderInfo hdr;
 +    AC3HeaderInfo hdr, *phdr=&hdr;
      int err;
  
 -    err = avpriv_ac3_parse_header(&s->gbc, &hdr);
 +    err = avpriv_ac3_parse_header(&s->gbc, &phdr);
      if (err)
          return err;
  
@@@ -368,45 -338,40 +368,45 @@@ static void set_downmix_coeffs(AC3Decod
      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];
  
      for (i = 0; i < s->fbw_channels; i++) {
 -        s->downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[s->channel_mode][i][0]];
 -        s->downmix_coeffs[i][1] = gain_levels[ac3_default_coeffs[s->channel_mode][i][1]];
 +        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]];
      }
      if (s->channel_mode > 1 && s->channel_mode & 1) {
 -        s->downmix_coeffs[1][0] = s->downmix_coeffs[1][1] = cmix;
 +        downmix_coeffs[1][0] = downmix_coeffs[1][1] = cmix;
      }
      if (s->channel_mode == AC3_CHMODE_2F1R || s->channel_mode == AC3_CHMODE_3F1R) {
          int nf = s->channel_mode - 2;
 -        s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf][1] = smix * LEVEL_MINUS_3DB;
 +        downmix_coeffs[nf][0] = downmix_coeffs[nf][1] = smix * LEVEL_MINUS_3DB;
      }
      if (s->channel_mode == AC3_CHMODE_2F2R || s->channel_mode == AC3_CHMODE_3F2R) {
          int nf = s->channel_mode - 4;
 -        s->downmix_coeffs[nf][0] = s->downmix_coeffs[nf+1][1] = smix;
 +        downmix_coeffs[nf][0] = downmix_coeffs[nf+1][1] = smix;
      }
  
      /* renormalize */
      norm0 = norm1 = 0.0;
      for (i = 0; i < s->fbw_channels; i++) {
 -        norm0 += s->downmix_coeffs[i][0];
 -        norm1 += s->downmix_coeffs[i][1];
 +        norm0 += downmix_coeffs[i][0];
 +        norm1 += downmix_coeffs[i][1];
      }
      norm0 = 1.0f / norm0;
      norm1 = 1.0f / norm1;
      for (i = 0; i < s->fbw_channels; i++) {
 -        s->downmix_coeffs[i][0] *= norm0;
 -        s->downmix_coeffs[i][1] *= norm1;
 +        downmix_coeffs[i][0] *= norm0;
 +        downmix_coeffs[i][1] *= norm1;
      }
  
      if (s->output_mode == AC3_CHMODE_MONO) {
          for (i = 0; i < s->fbw_channels; i++)
 -            s->downmix_coeffs[i][0] = (s->downmix_coeffs[i][0] +
 -                                       s->downmix_coeffs[i][1]) * LEVEL_MINUS_3DB;
 +            downmix_coeffs[i][0] = (downmix_coeffs[i][0] +
 +                                    downmix_coeffs[i][1]) * 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]);
      }
  }
  
   * Decode the grouped exponents according to exponent strategy.
   * reference: Section 7.1.3 Exponent Decoding
   */
 -static int decode_exponents(GetBitContext *gbc, int exp_strategy, int ngrps,
 +static int decode_exponents(AC3DecodeContext *s,
 +                            GetBitContext *gbc, int exp_strategy, int ngrps,
                              uint8_t absexp, int8_t *dexps)
  {
      int i, j, grp, group_size;
      group_size = exp_strategy + (exp_strategy == EXP_D45);
      for (grp = 0, i = 0; grp < ngrps; grp++) {
          expacc = get_bits(gbc, 7);
 +        if (expacc >= 125) {
 +            av_log(s->avctx, AV_LOG_ERROR, "expacc %d is out-of-range\n", expacc);
 +            return AVERROR_INVALIDDATA;
 +        }
          dexp[i++] = ungroup_3_in_7_bits_tab[expacc][0];
          dexp[i++] = ungroup_3_in_7_bits_tab[expacc][1];
          dexp[i++] = ungroup_3_in_7_bits_tab[expacc][2];
      prevexp = absexp;
      for (i = 0, j = 0; i < ngrps * 3; i++) {
          prevexp += dexp[i] - 2;
 -        if (prevexp > 24U)
 +        if (prevexp > 24U) {
 +            av_log(s->avctx, AV_LOG_ERROR, "exponent %d is out-of-range\n", prevexp);
              return -1;
 +        }
          switch (group_size) {
          case 4: dexps[j++] = prevexp;
                  dexps[j++] = prevexp;
@@@ -471,7 -429,7 +471,7 @@@ static void calc_transform_coeffs_cpl(A
                  int cpl_coord = s->cpl_coords[ch][band] << 5;
                  for (bin = band_start; bin < band_end; bin++) {
                      s->fixed_coeffs[ch][bin] =
 -                        MULH(s->fixed_coeffs[CPL_CH][bin] << 4, cpl_coord);
 +                        MULH(s->fixed_coeffs[CPL_CH][bin] * (1 << 4), cpl_coord);
                  }
                  if (ch == 2 && s->phase_flags[band]) {
                      for (bin = band_start; bin < band_end; bin++)
@@@ -517,7 -475,7 +517,7 @@@ static void ac3_decode_transform_coeffs
          case 0:
              /* random noise with approximate range of -0.707 to 0.707 */
              if (dither)
 -                mantissa = (av_lfg_get(&s->dith_state) / 362) - 5932275;
 +                mantissa = (((av_lfg_get(&s->dith_state)>>8)*181)>>8) - 5931008;
              else
                  mantissa = 0;
              break;
              break;
          default: /* 6 to 15 */
              /* Shift mantissa and sign-extend it. */
 -            mantissa = get_sbits(gbc, quantization_tab[bap]);
 -            mantissa <<= 24 - quantization_tab[bap];
 +            if (bap > 15) {
 +                av_log(s->avctx, AV_LOG_ERROR, "bap %d is invalid in plain AC-3\n", bap);
 +                bap = 15;
 +            }
 +            mantissa = (unsigned)get_sbits(gbc, quantization_tab[bap]) << (24 - quantization_tab[bap]);
              break;
          }
          coeffs[freq] = mantissa >> exps[freq];
@@@ -602,7 -557,7 +602,7 @@@ static void decode_transform_coeffs_ch(
          /* if AHT is used, mantissas for all blocks are encoded in the first
             block of the frame. */
          int bin;
 -        if (!blk && CONFIG_EAC3_DECODER)
 +        if (CONFIG_EAC3_DECODER && !blk)
              ff_eac3_decode_transform_coeffs_aht_ch(s, ch);
          for (bin = s->start_freq[ch]; bin < s->end_freq[ch]; bin++) {
              s->fixed_coeffs[ch][bin] = s->pre_mantissa[ch][bin][blk] >> s->dexps[ch][bin];
@@@ -680,30 -635,20 +680,30 @@@ static inline void do_imdct(AC3DecodeCo
      for (ch = 1; ch <= channels; ch++) {
          if (s->block_switch[ch]) {
              int i;
 -            float *x = s->tmp_output + 128;
 +            FFTSample *x = s->tmp_output + 128;
              for (i = 0; i < 128; i++)
                  x[i] = s->transform_coeffs[ch][2 * i];
              s->imdct_256.imdct_half(&s->imdct_256, s->tmp_output, x);
 -            s->fdsp.vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
 +#if USE_FIXED
 +            s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1],
 +                                       s->tmp_output, s->window, 128, 8);
 +#else
 +            s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
                                         s->tmp_output, s->window, 128);
 +#endif
              for (i = 0; i < 128; i++)
                  x[i] = s->transform_coeffs[ch][2 * i + 1];
              s->imdct_256.imdct_half(&s->imdct_256, s->delay[ch - 1], x);
          } else {
              s->imdct_512.imdct_half(&s->imdct_512, s->tmp_output, s->transform_coeffs[ch]);
 -            s->fdsp.vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
 +#if USE_FIXED
 +            s->fdsp->vector_fmul_window_scaled(s->outptr[ch - 1], s->delay[ch - 1],
 +                                       s->tmp_output, s->window, 128, 8);
 +#else
 +            s->fdsp->vector_fmul_window(s->outptr[ch - 1], s->delay[ch - 1],
                                         s->tmp_output, s->window, 128);
 -            memcpy(s->delay[ch - 1], s->tmp_output + 128, 128 * sizeof(float));
 +#endif
 +            memcpy(s->delay[ch - 1], s->tmp_output + 128, 128 * sizeof(FFTSample));
          }
      }
  }
@@@ -801,6 -746,109 +801,140 @@@ static void decode_band_structure(GetBi
          memcpy(band_sizes, bnd_sz, n_bands);
  }
  
 -    s->spx_dst_end_freq   = dst_end_freq;
+ static inline int spx_strategy(AC3DecodeContext *s, int blk)
+ {
+     GetBitContext *bc = &s->gbc;
+     int fbw_channels = s->fbw_channels;
+     int dst_start_freq, dst_end_freq, src_start_freq,
+         start_subband, end_subband, ch;
+     /* determine which channels use spx */
+     if (s->channel_mode == AC3_CHMODE_MONO) {
+         s->channel_uses_spx[1] = 1;
+     } else {
+         for (ch = 1; ch <= fbw_channels; ch++)
+             s->channel_uses_spx[ch] = get_bits1(bc);
+     }
+     /* get the frequency bins of the spx copy region and the spx start
+        and end subbands */
+     dst_start_freq = get_bits(bc, 2);
+     start_subband  = get_bits(bc, 3) + 2;
+     if (start_subband > 7)
+         start_subband += start_subband - 7;
+     end_subband    = get_bits(bc, 3) + 5;
++#if USE_FIXED
++    s->spx_dst_end_freq = end_freq_inv_tab[end_subband-5];
++#endif
+     if (end_subband   > 7)
+         end_subband   += end_subband   - 7;
+     dst_start_freq = dst_start_freq * 12 + 25;
+     src_start_freq = start_subband  * 12 + 25;
+     dst_end_freq   = end_subband    * 12 + 25;
+     /* check validity of spx ranges */
+     if (start_subband >= end_subband) {
+         av_log(s->avctx, AV_LOG_ERROR, "invalid spectral extension "
+                "range (%d >= %d)\n", start_subband, end_subband);
+         return AVERROR_INVALIDDATA;
+     }
+     if (dst_start_freq >= src_start_freq) {
+         av_log(s->avctx, AV_LOG_ERROR, "invalid spectral extension "
+                "copy start bin (%d >= %d)\n", dst_start_freq, src_start_freq);
+         return AVERROR_INVALIDDATA;
+     }
+     s->spx_dst_start_freq = dst_start_freq;
+     s->spx_src_start_freq = src_start_freq;
 -
++    if (!USE_FIXED)
++        s->spx_dst_end_freq   = dst_end_freq;
+     decode_band_structure(bc, blk, s->eac3, 0,
+                           start_subband, end_subband,
+                           ff_eac3_default_spx_band_struct,
+                           &s->num_spx_bands,
+                           s->spx_band_sizes);
 -                float spx_blend;
+     return 0;
+ }
+ static inline void spx_coordinates(AC3DecodeContext *s)
+ {
+     GetBitContext *bc = &s->gbc;
+     int fbw_channels = s->fbw_channels;
+     int ch, bnd;
+     for (ch = 1; ch <= fbw_channels; ch++) {
+         if (s->channel_uses_spx[ch]) {
+             if (s->first_spx_coords[ch] || get_bits1(bc)) {
 -                spx_blend        = get_bits(bc, 5) * (1.0f / 32);
++                INTFLOAT spx_blend;
+                 int bin, master_spx_coord;
+                 s->first_spx_coords[ch] = 0;
 -                    int bandsize;
++                spx_blend = AC3_SPX_BLEND(get_bits(bc, 5));
+                 master_spx_coord = get_bits(bc, 2) * 3;
+                 bin = s->spx_src_start_freq;
+                 for (bnd = 0; bnd < s->num_spx_bands; bnd++) {
 -                    float nratio, sblend, nblend, spx_coord;
++                    int bandsize = s->spx_band_sizes[bnd];
+                     int spx_coord_exp, spx_coord_mant;
 -                    bandsize = s->spx_band_sizes[bnd];
++                    INTFLOAT nratio, sblend, nblend;
++#if USE_FIXED
++                    /* calculate blending factors */
++                    int64_t accu = ((bin << 23) + (bandsize << 22))
++                                 * (int64_t)s->spx_dst_end_freq;
++                    nratio = (int)(accu >> 32);
++                    nratio -= spx_blend << 18;
++
++                    if (nratio < 0) {
++                        nblend = 0;
++                        sblend = 0x800000;
++                    } else if (nratio > 0x7fffff) {
++                        nblend = 14529495; // sqrt(3) in FP.23
++                        sblend = 0;
++                    } else {
++                        nblend = fixed_sqrt(nratio, 23);
++                        accu = (int64_t)nblend * 1859775393;
++                        nblend = (int)((accu + (1<<29)) >> 30);
++                        sblend = fixed_sqrt(0x800000 - nratio, 23);
++                    }
++#else
++                    float spx_coord;
+                     /* calculate blending factors */
 -                    spx_coord = spx_coord_mant * (1.0f / (1 << 23));
+                     nratio = ((float)((bin + (bandsize >> 1))) / s->spx_dst_end_freq) - spx_blend;
+                     nratio = av_clipf(nratio, 0.0f, 1.0f);
+                     nblend = sqrtf(3.0f * nratio); // noise is scaled by sqrt(3)
+                                                    // to give unity variance
+                     sblend = sqrtf(1.0f - nratio);
++#endif
+                     bin += bandsize;
+                     /* decode spx coordinates */
+                     spx_coord_exp  = get_bits(bc, 4);
+                     spx_coord_mant = get_bits(bc, 2);
+                     if (spx_coord_exp == 15) spx_coord_mant <<= 1;
+                     else                     spx_coord_mant += 4;
+                     spx_coord_mant <<= (25 - spx_coord_exp - master_spx_coord);
+                     /* multiply noise and signal blending factors by spx coordinate */
++#if USE_FIXED
++                    accu = (int64_t)nblend * spx_coord_mant;
++                    s->spx_noise_blend[ch][bnd]  = (int)((accu + (1<<22)) >> 23);
++                    accu = (int64_t)sblend * spx_coord_mant;
++                    s->spx_signal_blend[ch][bnd] = (int)((accu + (1<<22)) >> 23);
++#else
++                    spx_coord = spx_coord_mant * (1.0f / (1 << 23));
+                     s->spx_noise_blend [ch][bnd] = nblend * spx_coord;
+                     s->spx_signal_blend[ch][bnd] = sblend * spx_coord;
++#endif
+                 }
+             }
+         } else {
+             s->first_spx_coords[ch] = 1;
+         }
+     }
+ }
  /**
   * Decode a single audio block from the AC-3 bitstream.
   */
@@@ -808,7 -856,7 +942,7 @@@ static int decode_audio_block(AC3Decode
  {
      int fbw_channels = s->fbw_channels;
      int channel_mode = s->channel_mode;
-     int i, bnd, seg, ch;
+     int i, bnd, seg, ch, ret;
      int different_transforms;
      int downmix_output;
      int cpl_in_use;
          if (get_bits1(gbc)) {
              /* Allow asymmetric application of DRC when drc_scale > 1.
                 Amplification of quiet sounds is enhanced */
 -            float range = dynamic_range_tab[get_bits(gbc, 8)];
 -            if (range > 1.0 || s->drc_scale <= 1.0)
 -                s->dynamic_range[i] = powf(range, s->drc_scale);
 +            int range_bits = get_bits(gbc, 8);
 +            INTFLOAT range = AC3_RANGE(range_bits);
 +            if (range_bits <= 127 || s->drc_scale <= 1.0)
 +                s->dynamic_range[i] = AC3_DYNAMIC_RANGE(range);
              else
                  s->dynamic_range[i] = range;
          } else if (blk == 0) {
 -            s->dynamic_range[i] = 1.0f;
 +            s->dynamic_range[i] = AC3_DYNAMIC_RANGE1;
          }
      } while (i--);
  
      if (s->eac3 && (!blk || get_bits1(gbc))) {
          s->spx_in_use = get_bits1(gbc);
          if (s->spx_in_use) {
-             int dst_start_freq, dst_end_freq, src_start_freq,
-                 start_subband, end_subband;
-             /* determine which channels use spx */
-             if (s->channel_mode == AC3_CHMODE_MONO) {
-                 s->channel_uses_spx[1] = 1;
-             } else {
-                 for (ch = 1; ch <= fbw_channels; ch++)
-                     s->channel_uses_spx[ch] = get_bits1(gbc);
-             }
-             /* get the frequency bins of the spx copy region and the spx start
-                and end subbands */
-             dst_start_freq = get_bits(gbc, 2);
-             start_subband  = get_bits(gbc, 3) + 2;
-             if (start_subband > 7)
-                 start_subband += start_subband - 7;
-             end_subband    = get_bits(gbc, 3) + 5;
- #if USE_FIXED
-             s->spx_dst_end_freq = end_freq_inv_tab[end_subband-5];
- #endif
-             if (end_subband   > 7)
-                 end_subband   += end_subband   - 7;
-             dst_start_freq = dst_start_freq * 12 + 25;
-             src_start_freq = start_subband  * 12 + 25;
-             dst_end_freq   = end_subband    * 12 + 25;
-             /* check validity of spx ranges */
-             if (start_subband >= end_subband) {
-                 av_log(s->avctx, AV_LOG_ERROR, "invalid spectral extension "
-                        "range (%d >= %d)\n", start_subband, end_subband);
-                 return AVERROR_INVALIDDATA;
-             }
-             if (dst_start_freq >= src_start_freq) {
-                 av_log(s->avctx, AV_LOG_ERROR, "invalid spectral extension "
-                        "copy start bin (%d >= %d)\n", dst_start_freq, src_start_freq);
-                 return AVERROR_INVALIDDATA;
-             }
-             s->spx_dst_start_freq = dst_start_freq;
-             s->spx_src_start_freq = src_start_freq;
-             if (!USE_FIXED)
-                 s->spx_dst_end_freq   = dst_end_freq;
-             decode_band_structure(gbc, blk, s->eac3, 0,
-                                   start_subband, end_subband,
-                                   ff_eac3_default_spx_band_struct,
-                                   &s->num_spx_bands,
-                                   s->spx_band_sizes);
+             if ((ret = spx_strategy(s, blk)) < 0)
+                 return ret;
 -        } else {
 -            for (ch = 1; ch <= fbw_channels; ch++) {
 -                s->channel_uses_spx[ch] = 0;
 -                s->first_spx_coords[ch] = 1;
 -            }
 +        }
 +    }
 +    if (!s->eac3 || !s->spx_in_use) {
 +        s->spx_in_use = 0;
 +        for (ch = 1; ch <= fbw_channels; ch++) {
 +            s->channel_uses_spx[ch] = 0;
 +            s->first_spx_coords[ch] = 1;
          }
      }
  
      /* spectral extension coordinates */
-     if (s->spx_in_use) {
-         for (ch = 1; ch <= fbw_channels; ch++) {
-             if (s->channel_uses_spx[ch]) {
-                 if (s->first_spx_coords[ch] || get_bits1(gbc)) {
-                     INTFLOAT spx_blend;
-                     int bin, master_spx_coord;
-                     s->first_spx_coords[ch] = 0;
-                     spx_blend = AC3_SPX_BLEND(get_bits(gbc, 5));
-                     master_spx_coord = get_bits(gbc, 2) * 3;
-                     bin = s->spx_src_start_freq;
-                     for (bnd = 0; bnd < s->num_spx_bands; bnd++) {
-                         int bandsize = s->spx_band_sizes[bnd];
-                         int spx_coord_exp, spx_coord_mant;
-                         INTFLOAT nratio, sblend, nblend;
- #if USE_FIXED
-                         /* calculate blending factors */
-                         int64_t accu = ((bin << 23) + (bandsize << 22))
-                                      * (int64_t)s->spx_dst_end_freq;
-                         nratio = (int)(accu >> 32);
-                         nratio -= spx_blend << 18;
-                         if (nratio < 0) {
-                             nblend = 0;
-                             sblend = 0x800000;
-                         } else if (nratio > 0x7fffff) {
-                             nblend = 14529495; // sqrt(3) in FP.23
-                             sblend = 0;
-                         } else {
-                             nblend = fixed_sqrt(nratio, 23);
-                             accu = (int64_t)nblend * 1859775393;
-                             nblend = (int)((accu + (1<<29)) >> 30);
-                             sblend = fixed_sqrt(0x800000 - nratio, 23);
-                         }
- #else
-                         float spx_coord;
-                         /* calculate blending factors */
-                         nratio = ((float)((bin + (bandsize >> 1))) / s->spx_dst_end_freq) - spx_blend;
-                         nratio = av_clipf(nratio, 0.0f, 1.0f);
-                         nblend = sqrtf(3.0f * nratio); // noise is scaled by sqrt(3)
-                                                        // to give unity variance
-                         sblend = sqrtf(1.0f - nratio);
- #endif
-                         bin += bandsize;
-                         /* decode spx coordinates */
-                         spx_coord_exp  = get_bits(gbc, 4);
-                         spx_coord_mant = get_bits(gbc, 2);
-                         if (spx_coord_exp == 15) spx_coord_mant <<= 1;
-                         else                     spx_coord_mant += 4;
-                         spx_coord_mant <<= (25 - spx_coord_exp - master_spx_coord);
-                         /* multiply noise and signal blending factors by spx coordinate */
- #if USE_FIXED
-                         accu = (int64_t)nblend * spx_coord_mant;
-                         s->spx_noise_blend[ch][bnd]  = (int)((accu + (1<<22)) >> 23);
-                         accu = (int64_t)sblend * spx_coord_mant;
-                         s->spx_signal_blend[ch][bnd] = (int)((accu + (1<<22)) >> 23);
- #else
-                         spx_coord = spx_coord_mant * (1.0f / (1 << 23));
-                         s->spx_noise_blend [ch][bnd] = nblend * spx_coord;
-                         s->spx_signal_blend[ch][bnd] = sblend * spx_coord;
- #endif
-                     }
-                 }
-             } else {
-                 s->first_spx_coords[ch] = 1;
-             }
-         }
-     }
+     if (s->spx_in_use)
+         spx_coordinates(s);
  
      /* coupling strategy */
      if (s->eac3 ? s->cpl_strategy_exists[blk] : get_bits1(gbc)) {
      for (ch = !cpl_in_use; ch <= s->channels; ch++) {
          if (s->exp_strategy[blk][ch] != EXP_REUSE) {
              s->dexps[ch][0] = get_bits(gbc, 4) << !ch;
 -            if (decode_exponents(gbc, s->exp_strategy[blk][ch],
 +            if (decode_exponents(s, gbc, s->exp_strategy[blk][ch],
                                   s->num_exp_groups[ch], s->dexps[ch][0],
                                   &s->dexps[ch][s->start_freq[ch]+!!ch])) {
 -                av_log(s->avctx, AV_LOG_ERROR, "exponent out-of-range\n");
                  return AVERROR_INVALIDDATA;
              }
              if (ch != CPL_CH && ch != s->lfe_ch)
  
      /* apply scaling to coefficients (headroom, dynrng) */
      for (ch = 1; ch <= s->channels; ch++) {
 -        float gain = 1.0 / 4194304.0f;
 -        if (s->channel_mode == AC3_CHMODE_DUALMONO) {
 -            gain *= s->dynamic_range[2 - ch];
 -        } else {
 -            gain *= s->dynamic_range[0];
 -        }
 +        int audio_channel = 0;
 +        INTFLOAT gain;
 +        if (s->channel_mode == AC3_CHMODE_DUALMONO)
 +            audio_channel = 2-ch;
 +        if (s->heavy_compression && s->compression_exists[audio_channel])
 +            gain = s->heavy_dynamic_range[audio_channel];
 +        else
 +            gain = s->dynamic_range[audio_channel];
 +
 +#if USE_FIXED
 +        scale_coefs(s->transform_coeffs[ch], s->fixed_coeffs[ch], gain, 256);
 +#else
 +        if (s->target_level != 0)
 +          gain = gain * s->level_gain[audio_channel];
 +        gain *= 1.0 / 4194304.0f;
          s->fmt_conv.int32_to_float_fmul_scalar(s->transform_coeffs[ch],
                                                 s->fixed_coeffs[ch], gain, 256);
 +#endif
      }
  
      /* apply spectral extension to high frequency bins */
 -    if (s->spx_in_use && CONFIG_EAC3_DECODER) {
 +    if (CONFIG_EAC3_DECODER && s->spx_in_use) {
          ff_eac3_apply_spectral_extension(s);
      }
  
          do_imdct(s, s->channels);
  
          if (downmix_output) {
 +#if USE_FIXED
 +            ac3_downmix_c_fixed16(s->outptr, s->downmix_coeffs,
 +                              s->out_channels, s->fbw_channels, 256);
 +#else
              s->ac3dsp.downmix(s->outptr, s->downmix_coeffs,
                                s->out_channels, s->fbw_channels, 256);
 +#endif
          }
      } else {
          if (downmix_output) {
 -            s->ac3dsp.downmix(s->xcfptr + 1, s->downmix_coeffs,
 -                              s->out_channels, s->fbw_channels, 256);
 +            s->ac3dsp.AC3_RENAME(downmix)(s->xcfptr + 1, s->downmix_coeffs,
 +                                          s->out_channels, s->fbw_channels, 256);
          }
  
          if (downmix_output && !s->downmixed) {
              s->downmixed = 1;
 -            s->ac3dsp.downmix(s->dlyptr, s->downmix_coeffs, s->out_channels,
 -                              s->fbw_channels, 128);
 +            s->ac3dsp.AC3_RENAME(downmix)(s->dlyptr, s->downmix_coeffs,
 +                                          s->out_channels, s->fbw_channels, 128);
          }
  
          do_imdct(s, s->out_channels);
@@@ -1413,7 -1327,7 +1430,7 @@@ static int ac3_decode_frame(AVCodecCont
      AC3DecodeContext *s = avctx->priv_data;
      int blk, ch, err, ret;
      const uint8_t *channel_map;
 -    const float *output[AC3_MAX_CHANNELS];
 +    const SHORTFLOAT *output[AC3_MAX_CHANNELS];
      enum AVMatrixEncoding matrix_encoding;
      AVDownmixInfo *downmix_info;
  
                              (const uint16_t *) buf, cnt);
      } else
          memcpy(s->input_buffer, buf, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE));
 +
 +    /* if consistent noise generation is enabled, seed the linear feedback generator
 +     * with the contents of the AC-3 frame so that the noise is identical across
 +     * decodes given the same AC-3 frame data, for use with non-linear edititing software. */
 +    if (s->consistent_noise_generation)
 +        av_lfg_init_from_data(&s->dith_state, s->input_buffer, FFMIN(buf_size, AC3_FRAME_BUFFER_SIZE));
 +
      buf = s->input_buffer;
      /* initialize the GetBitContext with the start of valid AC-3 Frame */
 -    init_get_bits(&s->gbc, buf, buf_size * 8);
 +    if ((ret = init_get_bits8(&s->gbc, buf, buf_size)) < 0)
 +        return ret;
  
      /* parse the syncinfo */
      err = parse_frame_header(s);
          if (s->frame_size > buf_size) {
              av_log(avctx, AV_LOG_ERROR, "incomplete frame\n");
              err = AAC_AC3_PARSE_ERROR_FRAME_SIZE;
 -        } else if (avctx->err_recognition & AV_EF_CRCCHECK) {
 +        } else if (avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_CAREFUL)) {
              /* check for crc mismatch */
              if (av_crc(av_crc_get_table(AV_CRC_16_ANSI), 0, &buf[2],
                         s->frame_size - 2)) {
              s->output_mode  = AC3_CHMODE_STEREO;
          }
  
 +        s->loro_center_mix_level   = gain_levels[s->  center_mix_level];
 +        s->loro_surround_mix_level = gain_levels[s->surround_mix_level];
 +        s->ltrt_center_mix_level   = LEVEL_MINUS_3DB;
 +        s->ltrt_surround_mix_level = LEVEL_MINUS_3DB;
          /* set downmixing coefficients if needed */
          if (s->channels != s->out_channels && !((s->output_mode & AC3_OUTPUT_LFEON) &&
                  s->fbw_channels == s->out_channels)) {
  
      /* get output buffer */
      frame->nb_samples = s->num_blocks * AC3_BLOCK_SIZE;
 -    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +    if ((ret = ff_get_buffer(avctx, frame, 0)) < 0)
          return ret;
 -    }
  
      /* decode the audio blocks */
      channel_map = ff_ac3_dec_channel_map[s->output_mode & ~AC3_OUTPUT_LFEON][s->lfe_on];
 +    for (ch = 0; ch < AC3_MAX_CHANNELS; ch++) {
 +        output[ch] = s->output[ch];
 +        s->outptr[ch] = s->output[ch];
 +    }
      for (ch = 0; ch < s->channels; ch++) {
          if (ch < s->out_channels)
 -            s->outptr[channel_map[ch]] = (float *)frame->data[ch];
 -        else
 -            s->outptr[ch] = s->output[ch];
 -        output[ch] = s->output[ch];
 +            s->outptr[channel_map[ch]] = (SHORTFLOAT *)frame->data[ch];
      }
      for (blk = 0; blk < s->num_blocks; blk++) {
          if (!err && decode_audio_block(s, blk)) {
          }
          if (err)
              for (ch = 0; ch < s->out_channels; ch++)
 -                memcpy(s->outptr[channel_map[ch]], output[ch], sizeof(**output) * AC3_BLOCK_SIZE);
 +                memcpy(((SHORTFLOAT*)frame->data[ch]) + AC3_BLOCK_SIZE*blk, output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
          for (ch = 0; ch < s->out_channels; ch++)
              output[ch] = s->outptr[channel_map[ch]];
 -        for (ch = 0; ch < s->out_channels; ch++)
 -            s->outptr[ch] += AC3_BLOCK_SIZE;
 +        for (ch = 0; ch < s->out_channels; ch++) {
 +            if (!ch || channel_map[ch])
 +                s->outptr[channel_map[ch]] += AC3_BLOCK_SIZE;
 +        }
      }
  
 +    av_frame_set_decode_error_flags(frame, err ? FF_DECODE_ERROR_INVALID_BITSTREAM : 0);
 +
      /* keep last block for error concealment in next frame */
      for (ch = 0; ch < s->out_channels; ch++)
 -        memcpy(s->output[ch], output[ch], sizeof(**output) * AC3_BLOCK_SIZE);
 +        memcpy(s->output[ch], output[ch], AC3_BLOCK_SIZE*sizeof(SHORTFLOAT));
  
      /*
       * AVMatrixEncoding
@@@ -1643,10 -1542,59 +1660,10 @@@ 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);
  
      return 0;
  }
  
  #define OFFSET(x) offsetof(AC3DecodeContext, x)
  #define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM)
 -static const AVOption options[] = {
 -    { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 6.0, PAR },
 -    { NULL},
 -};
 -
 -static const AVClass ac3_decoder_class = {
 -    .class_name = "AC3 decoder",
 -    .item_name  = av_default_item_name,
 -    .option     = options,
 -    .version    = LIBAVUTIL_VERSION_INT,
 -};
 -
 -AVCodec ff_ac3_decoder = {
 -    .name           = "ac3",
 -    .long_name      = NULL_IF_CONFIG_SMALL("ATSC A/52A (AC-3)"),
 -    .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,
 -    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
 -                                                      AV_SAMPLE_FMT_NONE },
 -    .priv_class     = &ac3_decoder_class,
 -};
 -
 -#if CONFIG_EAC3_DECODER
 -static const AVClass eac3_decoder_class = {
 -    .class_name = "E-AC3 decoder",
 -    .item_name  = av_default_item_name,
 -    .option     = options,
 -    .version    = LIBAVUTIL_VERSION_INT,
 -};
 -
 -AVCodec ff_eac3_decoder = {
 -    .name           = "eac3",
 -    .long_name      = NULL_IF_CONFIG_SMALL("ATSC A/52B (AC-3, E-AC-3)"),
 -    .type           = AVMEDIA_TYPE_AUDIO,
 -    .id             = AV_CODEC_ID_EAC3,
 -    .priv_data_size = sizeof (AC3DecodeContext),
 -    .init           = ac3_decode_init,
 -    .close          = ac3_decode_end,
 -    .decode         = ac3_decode_frame,
 -    .capabilities   = AV_CODEC_CAP_DR1,
 -    .sample_fmts    = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
 -                                                      AV_SAMPLE_FMT_NONE },
 -    .priv_class     = &eac3_decoder_class,
 -};
 -#endif