Merge commit 'edd9ea3ffba1d5873dead1c57c74b1e3cc912167'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 4 Feb 2015 12:18:45 +0000 (13:18 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 4 Feb 2015 12:18:51 +0000 (13:18 +0100)
* commit 'edd9ea3ffba1d5873dead1c57c74b1e3cc912167':
  aacdec: Refactor aac_er_decode_frame.

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
libavcodec/aacdec.c

diff --combined libavcodec/aacdec.c
@@@ -8,20 -8,20 +8,20 @@@
   * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz>
   * Copyright (c) 2010      Janne Grunau <janne-libav@jannau.net>
   *
 - * 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
   */
  
@@@ -74,7 -74,6 +74,7 @@@
   * N                    SinuSoidal Coding (Transient, Sinusoid, Noise)
   * Y                    Parametric Stereo
   * N                    Direct Stream Transfer
 + * Y                    Enhanced AAC Low Delay (ER AAC ELD)
   *
   * Note: - HE AAC v1 comprises LC AAC with Spectral Band Replication.
   *       - HE AAC v2 comprises LC AAC with Spectral Band Replication and
@@@ -82,7 -81,6 +82,7 @@@
   */
  
  #include "libavutil/float_dsp.h"
 +#include "libavutil/opt.h"
  #include "avcodec.h"
  #include "internal.h"
  #include "get_bits.h"
  #include "aacadtsdec.h"
  #include "libavutil/intfloat.h"
  
 -#include <assert.h>
  #include <errno.h>
  #include <math.h>
  #include <stdint.h>
  
  #if ARCH_ARM
  #   include "arm/aac.h"
 +#elif ARCH_MIPS
 +#   include "mips/aacdec_mips.h"
  #endif
  
  static VLC vlc_scalefactors;
  static VLC vlc_spectral[11];
  
 -static const char overread_err[] = "Input buffer exhausted before END element found\n";
 +static int output_configure(AACContext *ac,
 +                            uint8_t layout_map[MAX_ELEM_ID*4][3], int tags,
 +                            enum OCStatus oc_type, int get_new_frame);
 +
 +#define overread_err "Input buffer exhausted before END element found\n"
  
  static int count_channels(uint8_t (*layout)[3], int tags)
  {
  /**
   * Check for the channel element in the current channel position configuration.
   * If it exists, make sure the appropriate element is allocated and map the
 - * channel order to match the internal Libav channel layout.
 + * channel order to match the internal FFmpeg channel layout.
   *
   * @param   che_pos current channel position configuration
   * @param   type channel element type
@@@ -150,8 -143,6 +150,8 @@@ static av_cold int che_configure(AACCon
                                   enum ChannelPosition che_pos,
                                   int type, int id, int *channels)
  {
 +    if (*channels >= MAX_CHANNELS)
 +        return AVERROR_INVALIDDATA;
      if (che_pos) {
          if (!ac->che[type][id]) {
              if (!(ac->che[type][id] = av_mallocz(sizeof(ChannelElement))))
              ff_aac_sbr_ctx_init(ac, &ac->che[type][id]->sbr);
          }
          if (type != TYPE_CCE) {
 -            if (*channels >= MAX_CHANNELS - 2)
 +            if (*channels >= MAX_CHANNELS - (type == TYPE_CPE || (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1))) {
 +                av_log(ac->avctx, AV_LOG_ERROR, "Too many channels\n");
                  return AVERROR_INVALIDDATA;
 +            }
              ac->output_element[(*channels)++] = &ac->che[type][id]->ch[0];
              if (type == TYPE_CPE ||
                  (type == TYPE_SCE && ac->oc[1].m4ac.ps == 1)) {
@@@ -195,12 -184,11 +195,12 @@@ static int frame_configure_elements(AVC
  
      /* get output buffer */
      av_frame_unref(ac->frame);
 +    if (!avctx->channels)
 +        return 1;
 +
      ac->frame->nb_samples = 2048;
 -    if ((ret = ff_get_buffer(avctx, ac->frame, 0)) < 0) {
 -        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 +    if ((ret = ff_get_buffer(avctx, ac->frame, 0)) < 0)
          return ret;
 -    }
  
      /* map output channel pointers to AVFrame data */
      for (ch = 0; ch < avctx->channels; ch++) {
@@@ -439,8 -427,6 +439,8 @@@ static void pop_output_configuration(AA
          ac->oc[1] = ac->oc[0];
          ac->avctx->channels = ac->oc[1].channels;
          ac->avctx->channel_layout = ac->oc[1].channel_layout;
 +        output_configure(ac, ac->oc[1].layout_map, ac->oc[1].layout_map_tags,
 +                         ac->oc[1].status, 0);
      }
  }
  
@@@ -486,8 -472,7 +486,8 @@@ static int output_configure(AACContext 
      }
  
      memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0]));
 -    avctx->channel_layout = ac->oc[1].channel_layout = layout;
 +    if (layout) avctx->channel_layout = layout;
 +                            ac->oc[1].channel_layout = layout;
      avctx->channels       = ac->oc[1].channels       = channels;
      ac->oc[1].status = oc_type;
  
      return 0;
  }
  
 +static void flush(AVCodecContext *avctx)
 +{
 +    AACContext *ac= avctx->priv_data;
 +    int type, i, j;
 +
 +    for (type = 3; type >= 0; type--) {
 +        for (i = 0; i < MAX_ELEM_ID; i++) {
 +            ChannelElement *che = ac->che[type][i];
 +            if (che) {
 +                for (j = 0; j <= 1; j++) {
 +                    memset(che->ch[j].saved, 0, sizeof(che->ch[j].saved));
 +                }
 +            }
 +        }
 +    }
 +}
 +
  /**
   * Set up channel positions based on a default channel configuration
   * as specified in table 1.17.
@@@ -536,25 -504,6 +536,25 @@@ static int set_default_channel_config(A
      *tags = tags_per_config[channel_config];
      memcpy(layout_map, aac_channel_layout_map[channel_config - 1],
             *tags * sizeof(*layout_map));
 +
 +    /*
 +     * AAC specification has 7.1(wide) as a default layout for 8-channel streams.
 +     * However, at least Nero AAC encoder encodes 7.1 streams using the default
 +     * channel config 7, mapping the side channels of the original audio stream
 +     * to the second AAC_CHANNEL_FRONT pair in the AAC stream. Similarly, e.g. FAAD
 +     * decodes the second AAC_CHANNEL_FRONT pair as side channels, therefore decoding
 +     * the incorrect streams as if they were correct (and as the encoder intended).
 +     *
 +     * As actual intended 7.1(wide) streams are very rare, default to assuming a
 +     * 7.1 layout was intended.
 +     */
 +    if (channel_config == 7 && avctx->strict_std_compliance < FF_COMPLIANCE_STRICT) {
 +        av_log(avctx, AV_LOG_INFO, "Assuming an incorrectly encoded 7.1 channel layout"
 +               " instead of a spec-compliant 7.1(wide) layout, use -strict %d to decode"
 +               " according to the specification instead.\n", FF_COMPLIANCE_STRICT);
 +        layout_map[2][2] = AAC_CHANNEL_SIDE;
 +    }
 +
      return 0;
  }
  
@@@ -572,8 -521,6 +572,8 @@@ static ChannelElement *get_che(AACConte
          int layout_map_tags;
          push_output_configuration(ac);
  
 +        av_log(ac->avctx, AV_LOG_DEBUG, "mono with CPE\n");
 +
          if (set_default_channel_config(ac->avctx, layout_map,
                                         &layout_map_tags, 2) < 0)
              return NULL;
          int layout_map_tags;
          push_output_configuration(ac);
  
 +        av_log(ac->avctx, AV_LOG_DEBUG, "stereo with SCE\n");
 +
          if (set_default_channel_config(ac->avctx, layout_map,
                                         &layout_map_tags, 1) < 0)
              return NULL;
           * If we seem to have encountered such a stream, transfer
           * the LFE[0] element to the SCE[1]'s mapping */
          if (ac->tags_mapped == tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
 +            if (!ac->warned_remapping_once && (type != TYPE_LFE || elem_id != 0)) {
 +                av_log(ac->avctx, AV_LOG_WARNING,
 +                   "This stream seems to incorrectly report its last channel as %s[%d], mapping to LFE[0]\n",
 +                   type == TYPE_SCE ? "SCE" : "LFE", elem_id);
 +                ac->warned_remapping_once++;
 +            }
              ac->tags_mapped++;
              return ac->tag_che_map[type][elem_id] = ac->che[TYPE_LFE][0];
          }
              return ac->tag_che_map[TYPE_CPE][elem_id] = ac->che[TYPE_CPE][1];
          }
      case 4:
 +        /* Some streams incorrectly code 4.0 audio as
 +         * SCE[0] CPE[0] LFE[0]
 +         * instead of
 +         * SCE[0] CPE[0] SCE[1].
 +         * If we seem to have encountered such a stream, transfer
 +         * the SCE[1] element to the LFE[0]'s mapping */
 +        if (ac->tags_mapped == tags_per_config[ac->oc[1].m4ac.chan_config] - 1 && (type == TYPE_LFE || type == TYPE_SCE)) {
 +            if (!ac->warned_remapping_once && (type != TYPE_SCE || elem_id != 1)) {
 +                av_log(ac->avctx, AV_LOG_WARNING,
 +                   "This stream seems to incorrectly report its last channel as %s[%d], mapping to SCE[1]\n",
 +                   type == TYPE_SCE ? "SCE" : "LFE", elem_id);
 +                ac->warned_remapping_once++;
 +            }
 +            ac->tags_mapped++;
 +            return ac->tag_che_map[type][elem_id] = ac->che[TYPE_SCE][1];
 +        }
          if (ac->tags_mapped == 2 &&
              ac->oc[1].m4ac.chan_config == 4 &&
              type == TYPE_SCE) {
@@@ -703,7 -626,7 +703,7 @@@ static void decode_channel_map(uint8_t 
              break;
          default:
              // AAC_CHANNEL_OFF has no channel map
 -            return;
 +            av_assert0(0);
          }
          layout_map[0][0] = syn_ele;
          layout_map[0][1] = get_bits(gb, 4);
@@@ -749,10 -672,6 +749,10 @@@ static int decode_pce(AVCodecContext *a
      if (get_bits1(gb))
          skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround
  
 +    if (get_bits_left(gb) < 4 * (num_front + num_side + num_back + num_lfe + num_assoc_data + num_cc)) {
 +        av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err);
 +        return -1;
 +    }
      decode_channel_map(layout_map       , AAC_CHANNEL_FRONT, gb, num_front);
      tags = num_front;
      decode_channel_map(layout_map + tags, AAC_CHANNEL_SIDE,  gb, num_side);
      /* comment field, first byte is length */
      comment_len = get_bits(gb, 8) * 8;
      if (get_bits_left(gb) < comment_len) {
 -        av_log(avctx, AV_LOG_ERROR, overread_err);
 +        av_log(avctx, AV_LOG_ERROR, "decode_pce: " overread_err);
          return AVERROR_INVALIDDATA;
      }
      skip_bits_long(gb, comment_len);
@@@ -946,9 -865,9 +946,9 @@@ static int decode_audio_specific_config
      GetBitContext gb;
      int i, ret;
  
 -    av_dlog(avctx, "extradata size %d\n", avctx->extradata_size);
 -    for (i = 0; i < avctx->extradata_size; i++)
 -        av_dlog(avctx, "%02x ", avctx->extradata[i]);
 +    av_dlog(avctx, "audio specific config size %d\n", bit_size >> 3);
 +    for (i = 0; i < bit_size >> 3; i++)
 +        av_dlog(avctx, "%02x ", data[i]);
      av_dlog(avctx, "\n");
  
      if ((ret = init_get_bits(&gb, data, bit_size)) < 0)
   *
   * @return  Returns a 32-bit pseudorandom integer
   */
 -static av_always_inline int lcg_random(int previous_val)
 +static av_always_inline int lcg_random(unsigned previous_val)
  {
      union { unsigned u; int s; } v = { previous_val * 1664525u + 1013904223 };
      return v.s;
@@@ -1066,8 -985,6 +1066,8 @@@ static void reset_predictor_group(Predi
                                      sizeof(ff_aac_spectral_codes[num][0]), \
          size);
  
 +static void aacdec_init(AACContext *ac);
 +
  static av_cold int aac_decode_init(AVCodecContext *avctx)
  {
      AACContext *ac = avctx->priv_data;
      ac->avctx = avctx;
      ac->oc[1].m4ac.sample_rate = avctx->sample_rate;
  
 +    aacdec_init(ac);
 +
      avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
  
      if (avctx->extradata_size > 0) {
          }
      }
  
 +    if (avctx->channels > MAX_CHANNELS) {
 +        av_log(avctx, AV_LOG_ERROR, "Too many channels\n");
 +        return AVERROR_INVALIDDATA;
 +    }
 +
      AAC_INIT_VLC_STATIC( 0, 304);
      AAC_INIT_VLC_STATIC( 1, 270);
      AAC_INIT_VLC_STATIC( 2, 550);
      ff_aac_sbr_init();
  
      ff_fmt_convert_init(&ac->fmt_conv, avctx);
 -    avpriv_float_dsp_init(&ac->fdsp, avctx->flags & CODEC_FLAG_BITEXACT);
 +    ac->fdsp = avpriv_float_dsp_alloc(avctx->flags & CODEC_FLAG_BITEXACT);
 +    if (!ac->fdsp) {
 +        return AVERROR(ENOMEM);
 +    }
  
      ac->random_state = 0x1f2e3d4c;
  
@@@ -1184,7 -1091,7 +1184,7 @@@ static int skip_data_stream_element(AAC
          align_get_bits(gb);
  
      if (get_bits_left(gb) < 8 * count) {
 -        av_log(ac->avctx, AV_LOG_ERROR, overread_err);
 +        av_log(ac->avctx, AV_LOG_ERROR, "skip_data_stream_element: "overread_err);
          return AVERROR_INVALIDDATA;
      }
      skip_bits_long(gb, 8 * count);
@@@ -1290,13 -1197,13 +1290,13 @@@ static int decode_ics_info(AACContext *
          if (ics->predictor_present) {
              if (aot == AOT_AAC_MAIN) {
                  if (decode_prediction(ac, ics, gb)) {
 -                    return AVERROR_INVALIDDATA;
 +                    goto fail;
                  }
              } else if (aot == AOT_AAC_LC ||
                         aot == AOT_ER_AAC_LC) {
                  av_log(ac->avctx, AV_LOG_ERROR,
                         "Prediction is not allowed in AAC-LC.\n");
 -                return AVERROR_INVALIDDATA;
 +                goto fail;
              } else {
                  if (aot == AOT_ER_AAC_LD) {
                      av_log(ac->avctx, AV_LOG_ERROR,
                 "Number of scalefactor bands in group (%d) "
                 "exceeds limit (%d).\n",
                 ics->max_sfb, ics->num_swb);
 -        return AVERROR_INVALIDDATA;
 +        goto fail;
      }
  
      return 0;
 +fail:
 +    ics->max_sfb = 0;
 +    return AVERROR_INVALIDDATA;
  }
  
  /**
@@@ -1351,7 -1255,7 +1351,7 @@@ static int decode_band_types(AACContex
                  sect_len_incr = get_bits(gb, bits);
                  sect_end += sect_len_incr;
                  if (get_bits_left(gb) < 0) {
 -                    av_log(ac->avctx, AV_LOG_ERROR, overread_err);
 +                    av_log(ac->avctx, AV_LOG_ERROR, "decode_band_types: "overread_err);
                      return AVERROR_INVALIDDATA;
                  }
                  if (sect_end > ics->max_sfb) {
@@@ -1453,12 -1357,12 +1453,12 @@@ static int decode_pulses(Pulse *pulse, 
          return -1;
      pulse->pos[0]    = swb_offset[pulse_swb];
      pulse->pos[0]   += get_bits(gb, 5);
 -    if (pulse->pos[0] > 1023)
 +    if (pulse->pos[0] >= swb_offset[num_swb])
          return -1;
      pulse->amp[0]    = get_bits(gb, 4);
      for (i = 1; i < pulse->num_pulse; i++) {
          pulse->pos[i] = get_bits(gb, 5) + pulse->pos[i - 1];
 -        if (pulse->pos[i] > 1023)
 +        if (pulse->pos[i] >= swb_offset[num_swb])
              return -1;
          pulse->amp[i] = get_bits(gb, 4);
      }
@@@ -1644,9 -1548,9 +1644,9 @@@ static int decode_spectrum_and_dequant(
                          cfo[k] = ac->random_state;
                      }
  
 -                    band_energy = ac->fdsp.scalarproduct_float(cfo, cfo, off_len);
 +                    band_energy = ac->fdsp->scalarproduct_float(cfo, cfo, off_len);
                      scale = sf[idx] / sqrtf(band_energy);
 -                    ac->fdsp.vector_fmul_scalar(cfo, cfo, scale, off_len);
 +                    ac->fdsp->vector_fmul_scalar(cfo, cfo, scale, off_len);
                  }
              } else {
                  const float *vq = ff_aac_codebook_vector_vals[cbt_m1];
                              }
                          } while (len -= 2);
  
 -                        ac->fdsp.vector_fmul_scalar(cfo, cfo, sf[idx], off_len);
 +                        ac->fdsp->vector_fmul_scalar(cfo, cfo, sf[idx], off_len);
                      }
                  }
  
@@@ -1972,7 -1876,7 +1972,7 @@@ static int decode_ics(AACContext *ac, S
              avpriv_request_sample(ac->avctx, "SSR");
              return AVERROR_PATCHWELCOME;
          }
 -        // I see no textual basis in the spec for this occuring after SSR gain
 +        // I see no textual basis in the spec for this occurring after SSR gain
          // control, but this is what both reference and real implmentations do
          if (tns->present && er_syntax)
              if (decode_tns(ac, tns, gb, ics) < 0)
@@@ -2005,7 -1909,7 +2005,7 @@@ static void apply_mid_side_stereo(AACCo
                  cpe->ch[0].band_type[idx] < NOISE_BT &&
                  cpe->ch[1].band_type[idx] < NOISE_BT) {
                  for (group = 0; group < ics->group_len[g]; group++) {
 -                    ac->fdsp.butterflies_float(ch0 + group * 128 + offsets[i],
 +                    ac->fdsp->butterflies_float(ch0 + group * 128 + offsets[i],
                                                 ch1 + group * 128 + offsets[i],
                                                 offsets[i+1] - offsets[i]);
                  }
@@@ -2044,7 -1948,7 +2044,7 @@@ static void apply_intensity_stereo(AACC
                          c *= 1 - 2 * cpe->ms_mask[idx];
                      scale = c * sce1->sf[idx];
                      for (group = 0; group < ics->group_len[g]; group++)
 -                        ac->fdsp.vector_fmul_scalar(coef1 + group * 128 + offsets[i],
 +                        ac->fdsp->vector_fmul_scalar(coef1 + group * 128 + offsets[i],
                                                      coef0 + group * 128 + offsets[i],
                                                      scale,
                                                      offsets[i + 1] - offsets[i]);
@@@ -2256,32 -2160,6 +2256,32 @@@ static int decode_dynamic_range(Dynamic
      return n;
  }
  
 +static int decode_fill(AACContext *ac, GetBitContext *gb, int len) {
 +    uint8_t buf[256];
 +    int i, major, minor;
 +
 +    if (len < 13+7*8)
 +        goto unknown;
 +
 +    get_bits(gb, 13); len -= 13;
 +
 +    for(i=0; i+1<sizeof(buf) && len>=8; i++, len-=8)
 +        buf[i] = get_bits(gb, 8);
 +
 +    buf[i] = 0;
 +    if (ac->avctx->debug & FF_DEBUG_PICT_INFO)
 +        av_log(ac->avctx, AV_LOG_DEBUG, "FILL:%s\n", buf);
 +
 +    if (sscanf(buf, "libfaac %d.%d", &major, &minor) == 2){
 +        ac->avctx->internal->skip_samples = 1024;
 +    }
 +
 +unknown:
 +    skip_bits_long(gb, len);
 +
 +    return 0;
 +}
 +
  /**
   * Decode extension data (incomplete); reference: table 4.51.
   *
@@@ -2294,12 -2172,7 +2294,12 @@@ static int decode_extension_payload(AAC
  {
      int crc_flag = 0;
      int res = cnt;
 -    switch (get_bits(gb, 4)) { // extension type
 +    int type = get_bits(gb, 4);
 +
 +    if (ac->avctx->debug & FF_DEBUG_STARTCODE)
 +        av_log(ac->avctx, AV_LOG_DEBUG, "extension type: %d len:%d\n", type, cnt);
 +
 +    switch (type) { // extension type
      case EXT_SBR_DATA_CRC:
          crc_flag++;
      case EXT_SBR_DATA:
          res = decode_dynamic_range(&ac->che_drc, gb);
          break;
      case EXT_FILL:
 +        decode_fill(ac, gb, 8 * cnt - 4);
 +        break;
      case EXT_FILL_DATA:
      case EXT_DATA_ELEMENT:
      default:
@@@ -2354,7 -2225,7 +2354,7 @@@ static void apply_tns(float coef[1024]
      int w, filt, m, i;
      int bottom, top, order, start, end, size, inc;
      float lpc[TNS_MAX_ORDER];
 -    float tmp[TNS_MAX_ORDER + 1];
 +    float tmp[TNS_MAX_ORDER+1];
  
      for (w = 0; w < ics->num_windows; w++) {
          bottom = ics->num_swb;
@@@ -2412,15 -2283,15 +2412,15 @@@ static void windowing_and_mdct_ltp(AACC
      const float *swindow_prev = ics->use_kb_window[1] ? ff_aac_kbd_short_128 : ff_sine_128;
  
      if (ics->window_sequence[0] != LONG_STOP_SEQUENCE) {
 -        ac->fdsp.vector_fmul(in, in, lwindow_prev, 1024);
 +        ac->fdsp->vector_fmul(in, in, lwindow_prev, 1024);
      } else {
          memset(in, 0, 448 * sizeof(float));
 -        ac->fdsp.vector_fmul(in + 448, in + 448, swindow_prev, 128);
 +        ac->fdsp->vector_fmul(in + 448, in + 448, swindow_prev, 128);
      }
      if (ics->window_sequence[0] != LONG_START_SEQUENCE) {
 -        ac->fdsp.vector_fmul_reverse(in + 1024, in + 1024, lwindow, 1024);
 +        ac->fdsp->vector_fmul_reverse(in + 1024, in + 1024, lwindow, 1024);
      } else {
 -        ac->fdsp.vector_fmul_reverse(in + 1024 + 448, in + 1024 + 448, swindow, 128);
 +        ac->fdsp->vector_fmul_reverse(in + 1024 + 448, in + 1024 + 448, swindow, 128);
          memset(in + 1024 + 576, 0, 448 * sizeof(float));
      }
      ac->mdct_ltp.mdct_calc(&ac->mdct_ltp, out, in);
@@@ -2446,10 -2317,10 +2446,10 @@@ static void apply_ltp(AACContext *ac, S
              predTime[i] = sce->ltp_state[i + 2048 - ltp->lag] * ltp->coef;
          memset(&predTime[i], 0, (2048 - i) * sizeof(float));
  
 -        windowing_and_mdct_ltp(ac, predFreq, predTime, &sce->ics);
 +        ac->windowing_and_mdct_ltp(ac, predFreq, predTime, &sce->ics);
  
          if (sce->tns.present)
 -            apply_tns(predFreq, &sce->tns, &sce->ics, 0);
 +            ac->apply_tns(predFreq, &sce->tns, &sce->ics, 0);
  
          for (sfb = 0; sfb < FFMIN(sce->ics.max_sfb, MAX_LTP_LONG_SFB); sfb++)
              if (ltp->used[sfb])
@@@ -2473,17 -2344,17 +2473,17 @@@ static void update_ltp(AACContext *ac, 
      if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
          memcpy(saved_ltp,       saved, 512 * sizeof(float));
          memset(saved_ltp + 576, 0,     448 * sizeof(float));
 -        ac->fdsp.vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960,     &swindow[64],      64);
 +        ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960,     &swindow[64],      64);
          for (i = 0; i < 64; i++)
              saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * swindow[63 - i];
      } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
          memcpy(saved_ltp,       ac->buf_mdct + 512, 448 * sizeof(float));
          memset(saved_ltp + 576, 0,                  448 * sizeof(float));
 -        ac->fdsp.vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960,     &swindow[64],      64);
 +        ac->fdsp->vector_fmul_reverse(saved_ltp + 448, ac->buf_mdct + 960,     &swindow[64],      64);
          for (i = 0; i < 64; i++)
              saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * swindow[63 - i];
      } else { // LONG_STOP or ONLY_LONG
 -        ac->fdsp.vector_fmul_reverse(saved_ltp,       ac->buf_mdct + 512,     &lwindow[512],     512);
 +        ac->fdsp->vector_fmul_reverse(saved_ltp,       ac->buf_mdct + 512,     &lwindow[512],     512);
          for (i = 0; i < 512; i++)
              saved_ltp[i + 512] = ac->buf_mdct[1023 - i] * lwindow[511 - i];
      }
@@@ -2524,19 -2395,19 +2524,19 @@@ static void imdct_and_windowing(AACCont
       */
      if ((ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE) &&
              (ics->window_sequence[0] == ONLY_LONG_SEQUENCE || ics->window_sequence[0] == LONG_START_SEQUENCE)) {
 -        ac->fdsp.vector_fmul_window(    out,               saved,            buf,         lwindow_prev, 512);
 +        ac->fdsp->vector_fmul_window(    out,               saved,            buf,         lwindow_prev, 512);
      } else {
          memcpy(                         out,               saved,            448 * sizeof(float));
  
          if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
 -            ac->fdsp.vector_fmul_window(out + 448 + 0*128, saved + 448,      buf + 0*128, swindow_prev, 64);
 -            ac->fdsp.vector_fmul_window(out + 448 + 1*128, buf + 0*128 + 64, buf + 1*128, swindow,      64);
 -            ac->fdsp.vector_fmul_window(out + 448 + 2*128, buf + 1*128 + 64, buf + 2*128, swindow,      64);
 -            ac->fdsp.vector_fmul_window(out + 448 + 3*128, buf + 2*128 + 64, buf + 3*128, swindow,      64);
 -            ac->fdsp.vector_fmul_window(temp,              buf + 3*128 + 64, buf + 4*128, swindow,      64);
 +            ac->fdsp->vector_fmul_window(out + 448 + 0*128, saved + 448,      buf + 0*128, swindow_prev, 64);
 +            ac->fdsp->vector_fmul_window(out + 448 + 1*128, buf + 0*128 + 64, buf + 1*128, swindow,      64);
 +            ac->fdsp->vector_fmul_window(out + 448 + 2*128, buf + 1*128 + 64, buf + 2*128, swindow,      64);
 +            ac->fdsp->vector_fmul_window(out + 448 + 3*128, buf + 2*128 + 64, buf + 3*128, swindow,      64);
 +            ac->fdsp->vector_fmul_window(temp,              buf + 3*128 + 64, buf + 4*128, swindow,      64);
              memcpy(                     out + 448 + 4*128, temp, 64 * sizeof(float));
          } else {
 -            ac->fdsp.vector_fmul_window(out + 448,         saved + 448,      buf,         swindow_prev, 64);
 +            ac->fdsp->vector_fmul_window(out + 448,         saved + 448,      buf,         swindow_prev, 64);
              memcpy(                     out + 576,         buf + 64,         448 * sizeof(float));
          }
      }
      // buffer update
      if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
          memcpy(                     saved,       temp + 64,         64 * sizeof(float));
 -        ac->fdsp.vector_fmul_window(saved + 64,  buf + 4*128 + 64, buf + 5*128, swindow, 64);
 -        ac->fdsp.vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 64);
 -        ac->fdsp.vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 64);
 +        ac->fdsp->vector_fmul_window(saved + 64,  buf + 4*128 + 64, buf + 5*128, swindow, 64);
 +        ac->fdsp->vector_fmul_window(saved + 192, buf + 5*128 + 64, buf + 6*128, swindow, 64);
 +        ac->fdsp->vector_fmul_window(saved + 320, buf + 6*128 + 64, buf + 7*128, swindow, 64);
          memcpy(                     saved + 448, buf + 7*128 + 64,  64 * sizeof(float));
      } else if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
          memcpy(                     saved,       buf + 512,        448 * sizeof(float));
@@@ -2571,10 -2442,10 +2571,10 @@@ static void imdct_and_windowing_ld(AACC
      if (ics->use_kb_window[1]) {
          // AAC LD uses a low overlap sine window instead of a KBD window
          memcpy(out, saved, 192 * sizeof(float));
 -        ac->fdsp.vector_fmul_window(out + 192, saved + 192, buf, ff_sine_128, 64);
 +        ac->fdsp->vector_fmul_window(out + 192, saved + 192, buf, ff_sine_128, 64);
          memcpy(                     out + 320, buf + 64, 192 * sizeof(float));
      } else {
 -        ac->fdsp.vector_fmul_window(out, saved, buf, ff_sine_512, 256);
 +        ac->fdsp->vector_fmul_window(out, saved, buf, ff_sine_512, 256);
      }
  
      // buffer update
@@@ -2596,7 -2467,7 +2596,7 @@@ static void imdct_and_windowing_eld(AAC
      // Inverse transform, mapped to the conventional IMDCT by
      // Chivukula, R.K.; Reznik, Y.A.; Devarajan, V.,
      // "Efficient algorithms for MPEG-4 AAC-ELD, AAC-LD and AAC-LC filterbanks,"
 -    // Audio, Language and Image Processing, 2008. ICALIP 2008. International Conference on
 +    // International Conference on Audio, Language and Image Processing, ICALIP 2008.
      // URL: http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=4590245&isnumber=4589950
      for (i = 0; i < n2; i+=2) {
          float temp;
@@@ -2742,36 -2613,36 +2742,36 @@@ static void spectral_to_sample(AACConte
          imdct_and_window = imdct_and_windowing_eld;
          break;
      default:
 -        imdct_and_window = imdct_and_windowing;
 +        imdct_and_window = ac->imdct_and_windowing;
      }
      for (type = 3; type >= 0; type--) {
          for (i = 0; i < MAX_ELEM_ID; i++) {
              ChannelElement *che = ac->che[type][i];
 -            if (che) {
 +            if (che && che->present) {
                  if (type <= TYPE_CPE)
                      apply_channel_coupling(ac, che, type, i, BEFORE_TNS, apply_dependent_coupling);
                  if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP) {
                      if (che->ch[0].ics.predictor_present) {
                          if (che->ch[0].ics.ltp.present)
 -                            apply_ltp(ac, &che->ch[0]);
 +                            ac->apply_ltp(ac, &che->ch[0]);
                          if (che->ch[1].ics.ltp.present && type == TYPE_CPE)
 -                            apply_ltp(ac, &che->ch[1]);
 +                            ac->apply_ltp(ac, &che->ch[1]);
                      }
                  }
                  if (che->ch[0].tns.present)
 -                    apply_tns(che->ch[0].coeffs, &che->ch[0].tns, &che->ch[0].ics, 1);
 +                    ac->apply_tns(che->ch[0].coeffs, &che->ch[0].tns, &che->ch[0].ics, 1);
                  if (che->ch[1].tns.present)
 -                    apply_tns(che->ch[1].coeffs, &che->ch[1].tns, &che->ch[1].ics, 1);
 +                    ac->apply_tns(che->ch[1].coeffs, &che->ch[1].tns, &che->ch[1].ics, 1);
                  if (type <= TYPE_CPE)
                      apply_channel_coupling(ac, che, type, i, BETWEEN_TNS_AND_IMDCT, apply_dependent_coupling);
                  if (type != TYPE_CCE || che->coup.coupling_point == AFTER_IMDCT) {
                      imdct_and_window(ac, &che->ch[0]);
                      if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
 -                        update_ltp(ac, &che->ch[0]);
 +                        ac->update_ltp(ac, &che->ch[0]);
                      if (type == TYPE_CPE) {
                          imdct_and_window(ac, &che->ch[1]);
                          if (ac->oc[1].m4ac.object_type == AOT_AAC_LTP)
 -                            update_ltp(ac, &che->ch[1]);
 +                            ac->update_ltp(ac, &che->ch[1]);
                      }
                      if (ac->oc[1].m4ac.sbr > 0) {
                          ff_sbr_apply(ac, &che->sbr, type, che->ch[0].ret, che->ch[1].ret);
                  }
                  if (type <= TYPE_CCE)
                      apply_channel_coupling(ac, che, type, i, AFTER_IMDCT, apply_independent_coupling);
 +                che->present = 0;
 +            } else if (che) {
 +                av_log(ac->avctx, AV_LOG_VERBOSE, "ChannelElement %d.%d missing \n", type, i);
              }
          }
      }
@@@ -2796,12 -2664,10 +2796,12 @@@ static int parse_adts_frame_header(AACC
  
      size = avpriv_aac_parse_header(gb, &hdr_info);
      if (size > 0) {
 -        if (hdr_info.num_aac_frames != 1) {
 +        if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) {
 +            // This is 2 for "VLB " audio in NSV files.
 +            // See samples/nsv/vlb_audio.
              avpriv_report_missing_feature(ac->avctx,
                                            "More than one AAC RDB per ADTS frame");
 -            return AVERROR_PATCHWELCOME;
 +            ac->warned_num_aac_frames = 1;
          }
          push_output_configuration(ac);
          if (hdr_info.chan_config) {
                  return ret;
          } else {
              ac->oc[1].m4ac.chan_config = 0;
 +            /**
 +             * dual mono frames in Japanese DTV can have chan_config 0
 +             * WITHOUT specifying PCE.
 +             *  thus, set dual mono as default.
 +             */
 +            if (ac->dmono_mode && ac->oc[0].status == OC_NONE) {
 +                layout_map_tags = 2;
 +                layout_map[0][0] = layout_map[1][0] = TYPE_SCE;
 +                layout_map[0][2] = layout_map[1][2] = AAC_CHANNEL_FRONT;
 +                layout_map[0][1] = 0;
 +                layout_map[1][1] = 1;
 +                if (output_configure(ac, layout_map, layout_map_tags,
 +                                     OC_TRIAL_FRAME, 0))
 +                    return -7;
 +            }
          }
          ac->oc[1].m4ac.sample_rate     = hdr_info.sample_rate;
          ac->oc[1].m4ac.sampling_index  = hdr_info.sampling_index;
@@@ -2852,11 -2703,12 +2852,12 @@@ static int aac_decode_er_frame(AVCodecC
                                 int *got_frame_ptr, GetBitContext *gb)
  {
      AACContext *ac = avctx->priv_data;
+     const MPEG4AudioConfig *const m4ac = &ac->oc[1].m4ac;
      ChannelElement *che;
      int err, i;
      int samples = 1024;
-     int chan_config = ac->oc[1].m4ac.chan_config;
-     int aot = ac->oc[1].m4ac.object_type;
+     int chan_config = m4ac->chan_config;
+     int aot = m4ac->object_type;
  
      if (aot == AOT_ER_AAC_LD || aot == AOT_ER_AAC_ELD)
          samples >>= 1;
  
      // The FF_PROFILE_AAC_* defines are all object_type - 1
      // This may lead to an undefined profile being signaled
-     ac->avctx->profile = ac->oc[1].m4ac.object_type - 1;
+     ac->avctx->profile = aot - 1;
  
      ac->tags_mapped = 0;
  
      if (chan_config < 0 || chan_config >= 8) {
          avpriv_request_sample(avctx, "Unknown ER channel configuration %d",
-                               ac->oc[1].m4ac.chan_config);
+                               chan_config);
          return AVERROR_INVALIDDATA;
      }
      for (i = 0; i < tags_per_config[chan_config]; i++) {
                     elem_type, elem_id);
              return AVERROR_INVALIDDATA;
          }
 +        che->present = 1;
          if (aot != AOT_ER_AAC_ELD)
              skip_bits(gb, 4);
          switch (elem_type) {
  }
  
  static int aac_decode_frame_int(AVCodecContext *avctx, void *data,
 -                                int *got_frame_ptr, GetBitContext *gb)
 +                                int *got_frame_ptr, GetBitContext *gb, AVPacket *avpkt)
  {
      AACContext *ac = avctx->priv_data;
      ChannelElement *che = NULL, *che_prev = NULL;
      enum RawDataBlockType elem_type, elem_type_prev = TYPE_END;
      int err, elem_id;
      int samples = 0, multiplier, audio_found = 0, pce_found = 0;
 +    int is_dmono, sce_count = 0;
  
      ac->frame = data;
  
      while ((elem_type = get_bits(gb, 3)) != TYPE_END) {
          elem_id = get_bits(gb, 4);
  
 +        if (avctx->debug & FF_DEBUG_STARTCODE)
 +            av_log(avctx, AV_LOG_DEBUG, "Elem type:%x id:%x\n", elem_type, elem_id);
 +
          if (elem_type < TYPE_DSE) {
              if (!(che=get_che(ac, elem_type, elem_id))) {
                  av_log(ac->avctx, AV_LOG_ERROR, "channel element %d.%d is not allocated\n",
                  goto fail;
              }
              samples = 1024;
 +            che->present = 1;
          }
  
          switch (elem_type) {
          case TYPE_SCE:
              err = decode_ics(ac, &che->ch[0], gb, 0, 0);
              audio_found = 1;
 +            sce_count++;
              break;
  
          case TYPE_CPE:
              if (pce_found) {
                  av_log(avctx, AV_LOG_ERROR,
                         "Not evaluating a further program_config_element as this construct is dubious at best.\n");
 -                pop_output_configuration(ac);
              } else {
                  err = output_configure(ac, layout_map, tags, OC_TRIAL_PCE, 1);
 +                if (!err)
 +                    ac->oc[1].m4ac.chan_config = 0;
                  pce_found = 1;
              }
              break;
              if (elem_id == 15)
                  elem_id += get_bits(gb, 8) - 1;
              if (get_bits_left(gb) < 8 * elem_id) {
 -                    av_log(avctx, AV_LOG_ERROR, overread_err);
 +                    av_log(avctx, AV_LOG_ERROR, "TYPE_FIL: "overread_err);
                      err = AVERROR_INVALIDDATA;
                      goto fail;
              }
          ac->oc[1].status = OC_LOCKED;
      }
  
 +    if (multiplier) {
 +        int side_size;
 +        const uint8_t *side = av_packet_get_side_data(avpkt, AV_PKT_DATA_SKIP_SAMPLES, &side_size);
 +        if (side && side_size>=4)
 +            AV_WL32(side, 2*AV_RL32(side));
 +    }
 +
 +    *got_frame_ptr = !!samples;
      if (samples) {
          ac->frame->nb_samples = samples;
          ac->frame->sample_rate = avctx->sample_rate;
 -    }
 +    } else
 +        av_frame_unref(ac->frame);
      *got_frame_ptr = !!samples;
  
 +    /* for dual-mono audio (SCE + SCE) */
 +    is_dmono = ac->dmono_mode && sce_count == 2 &&
 +               ac->oc[1].channel_layout == (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT);
 +    if (is_dmono) {
 +        if (ac->dmono_mode == 1)
 +            ((AVFrame *)data)->data[1] =((AVFrame *)data)->data[0];
 +        else if (ac->dmono_mode == 2)
 +            ((AVFrame *)data)->data[0] =((AVFrame *)data)->data[1];
 +    }
 +
      return 0;
  fail:
      pop_output_configuration(ac);
@@@ -3098,12 -2923,8 +3099,12 @@@ static int aac_decode_frame(AVCodecCont
      const uint8_t *new_extradata = av_packet_get_side_data(avpkt,
                                         AV_PKT_DATA_NEW_EXTRADATA,
                                         &new_extradata_size);
 +    int jp_dualmono_size;
 +    const uint8_t *jp_dualmono   = av_packet_get_side_data(avpkt,
 +                                       AV_PKT_DATA_JP_DUALMONO,
 +                                       &jp_dualmono_size);
  
 -    if (new_extradata) {
 +    if (new_extradata && 0) {
          av_free(avctx->extradata);
          avctx->extradata = av_mallocz(new_extradata_size +
                                        FF_INPUT_BUFFER_PADDING_SIZE);
          }
      }
  
 +    ac->dmono_mode = 0;
 +    if (jp_dualmono && jp_dualmono_size > 0)
 +        ac->dmono_mode =  1 + *jp_dualmono;
 +    if (ac->force_dmono_mode >= 0)
 +        ac->dmono_mode = ac->force_dmono_mode;
 +
 +    if (INT_MAX / 8 <= buf_size)
 +        return AVERROR_INVALIDDATA;
 +
      if ((err = init_get_bits(&gb, buf, buf_size * 8)) < 0)
          return err;
  
          err = aac_decode_er_frame(avctx, data, got_frame_ptr, &gb);
          break;
      default:
 -        err = aac_decode_frame_int(avctx, data, got_frame_ptr, &gb);
 +        err = aac_decode_frame_int(avctx, data, got_frame_ptr, &gb, avpkt);
      }
      if (err < 0)
          return err;
@@@ -3170,7 -2982,6 +3171,7 @@@ static av_cold int aac_decode_close(AVC
      ff_mdct_end(&ac->mdct_small);
      ff_mdct_end(&ac->mdct_ld);
      ff_mdct_end(&ac->mdct_ltp);
 +    av_freep(&ac->fdsp);
      return 0;
  }
  
  
  struct LATMContext {
      AACContext aac_ctx;     ///< containing AACContext
 -    int initialized;        ///< initilized after a valid extradata was seen
 +    int initialized;        ///< initialized after a valid extradata was seen
  
      // parser data
      int audio_mux_version_A; ///< LATM syntax version
@@@ -3228,11 -3039,7 +3229,11 @@@ static int latm_decode_audio_specific_c
          ac->oc[1].m4ac.sample_rate != m4ac.sample_rate ||
          ac->oc[1].m4ac.chan_config != m4ac.chan_config) {
  
 -        av_log(avctx, AV_LOG_INFO, "audio config changed\n");
 +        if(latmctx->initialized) {
 +            av_log(avctx, AV_LOG_INFO, "audio config changed\n");
 +        } else {
 +            av_log(avctx, AV_LOG_DEBUG, "initializing latmctx\n");
 +        }
          latmctx->initialized = 0;
  
          esize = (bits_consumed+7) / 8;
@@@ -3275,9 -3082,9 +3276,9 @@@ static int read_stream_mux_config(struc
              return AVERROR_PATCHWELCOME;
          }
  
 -        // for each program (which there is only on in DVB)
 +        // for each program (which there is only one in DVB)
  
 -        // for each layer (which there is only on in DVB)
 +        // for each layer (which there is only one in DVB)
          if (get_bits(gb, 3)) {                   // numLayer
              avpriv_request_sample(latmctx->aac_ctx.avctx, "Multiple layers");
              return AVERROR_PATCHWELCOME;
@@@ -3390,7 -3197,7 +3391,7 @@@ static int latm_decode_frame(AVCodecCon
      int                 muxlength, err;
      GetBitContext       gb;
  
 -    if ((err = init_get_bits(&gb, avpkt->data, avpkt->size * 8)) < 0)
 +    if ((err = init_get_bits8(&gb, avpkt->data, avpkt->size)) < 0)
          return err;
  
      // check for LOAS sync word
          return AVERROR_INVALIDDATA;
  
      muxlength = get_bits(&gb, 13) + 3;
 -    // not enough data, the parser should have sorted this
 +    // not enough data, the parser should have sorted this out
      if (muxlength > avpkt->size)
          return AVERROR_INVALIDDATA;
  
          return AVERROR_INVALIDDATA;
      }
  
 -    if ((err = aac_decode_frame_int(avctx, out, got_frame_ptr, &gb)) < 0)
 +    if ((err = aac_decode_frame_int(avctx, out, got_frame_ptr, &gb, avpkt)) < 0)
          return err;
  
      return muxlength;
@@@ -3445,52 -3252,6 +3446,52 @@@ static av_cold int latm_decode_init(AVC
      return ret;
  }
  
 +static void aacdec_init(AACContext *c)
 +{
 +    c->imdct_and_windowing                      = imdct_and_windowing;
 +    c->apply_ltp                                = apply_ltp;
 +    c->apply_tns                                = apply_tns;
 +    c->windowing_and_mdct_ltp                   = windowing_and_mdct_ltp;
 +    c->update_ltp                               = update_ltp;
 +
 +    if(ARCH_MIPS)
 +        ff_aacdec_init_mips(c);
 +}
 +/**
 + * AVOptions for Japanese DTV specific extensions (ADTS only)
 + */
 +#define AACDEC_FLAGS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM
 +static const AVOption options[] = {
 +    {"dual_mono_mode", "Select the channel to decode for dual mono",
 +     offsetof(AACContext, force_dmono_mode), AV_OPT_TYPE_INT, {.i64=-1}, -1, 2,
 +     AACDEC_FLAGS, "dual_mono_mode"},
 +
 +    {"auto", "autoselection",            0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
 +    {"main", "Select Main/Left channel", 0, AV_OPT_TYPE_CONST, {.i64= 1}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
 +    {"sub" , "Select Sub/Right channel", 0, AV_OPT_TYPE_CONST, {.i64= 2}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
 +    {"both", "Select both channels",     0, AV_OPT_TYPE_CONST, {.i64= 0}, INT_MIN, INT_MAX, AACDEC_FLAGS, "dual_mono_mode"},
 +
 +    {NULL},
 +};
 +
 +static const AVClass aac_decoder_class = {
 +    .class_name = "AAC decoder",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +static const AVProfile profiles[] = {
 +    { FF_PROFILE_AAC_MAIN,  "Main"     },
 +    { FF_PROFILE_AAC_LOW,   "LC"       },
 +    { FF_PROFILE_AAC_SSR,   "SSR"      },
 +    { FF_PROFILE_AAC_LTP,   "LTP"      },
 +    { FF_PROFILE_AAC_HE,    "HE-AAC"   },
 +    { FF_PROFILE_AAC_HE_V2, "HE-AACv2" },
 +    { FF_PROFILE_AAC_LD,    "LD"       },
 +    { FF_PROFILE_AAC_ELD,   "ELD"      },
 +    { FF_PROFILE_UNKNOWN },
 +};
  
  AVCodec ff_aac_decoder = {
      .name            = "aac",
      },
      .capabilities    = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1,
      .channel_layouts = aac_channel_layout,
 +    .flush = flush,
 +    .priv_class      = &aac_decoder_class,
 +    .profiles        = profiles,
  };
  
  /*
@@@ -3530,6 -3288,4 +3531,6 @@@ AVCodec ff_aac_latm_decoder = 
      },
      .capabilities    = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1,
      .channel_layouts = aac_channel_layout,
 +    .flush = flush,
 +    .profiles        = profiles,
  };