X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Faac.c;h=0fbab7736735f689a4f432425ba117c76a12df0b;hb=dd0cd3d2730b93958a34dea7c7890e71d2d72bf6;hp=235cce53941a9b93840af109d49b36b9e17a622a;hpb=b418a6ca7e34c7788ab172f9e8a7b39cfac2fda2;p=ffmpeg diff --git a/libavcodec/aac.c b/libavcodec/aac.c index 235cce53941..0fbab773673 100644 --- a/libavcodec/aac.c +++ b/libavcodec/aac.c @@ -93,6 +93,10 @@ #include #include +#if ARCH_ARM +# include "arm/aac.h" +#endif + union float754 { float f; uint32_t i; @@ -101,10 +105,10 @@ union float754 { static VLC vlc_scalefactors; static VLC vlc_spectral[11]; +static uint32_t cbrt_tab[1<<13]; static ChannelElement *get_che(AACContext *ac, int type, int elem_id) { - static const int8_t tags_per_config[16] = { 0, 1, 1, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0 }; if (ac->tag_che_map[type][elem_id]) { return ac->tag_che_map[type][elem_id]; } @@ -153,6 +157,37 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id) } } +/** + * 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 FFmpeg channel layout. + * + * @param che_pos current channel position configuration + * @param type channel element type + * @param id channel element id + * @param channels count of the number of channels in the configuration + * + * @return Returns error status. 0 - OK, !0 - error + */ +static int che_configure(AACContext *ac, + enum ChannelPosition che_pos[4][MAX_ELEM_ID], + int type, int id, + int *channels) +{ + if (che_pos[type][id]) { + if (!ac->che[type][id] && !(ac->che[type][id] = av_mallocz(sizeof(ChannelElement)))) + return AVERROR(ENOMEM); + if (type != TYPE_CCE) { + ac->output_data[(*channels)++] = ac->che[type][id]->ch[0].ret; + if (type == TYPE_CPE) { + ac->output_data[(*channels)++] = ac->che[type][id]->ch[1].ret; + } + } + } else + av_freep(&ac->che[type][id]); + return 0; +} + /** * Configure output channel order based on the current program configuration element. * @@ -164,49 +199,52 @@ static ChannelElement *get_che(AACContext *ac, int type, int elem_id) static int output_configure(AACContext *ac, enum ChannelPosition che_pos[4][MAX_ELEM_ID], enum ChannelPosition new_che_pos[4][MAX_ELEM_ID], - int channel_config) + int channel_config, enum OCStatus oc_type) { AVCodecContext *avctx = ac->avccontext; - int i, type, channels = 0; + int i, type, channels = 0, ret; memcpy(che_pos, new_che_pos, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0])); - /* Allocate or free elements depending on if they are in the - * current program configuration. - * - * Set up default 1:1 output mapping. - * - * For a 5.1 stream the output order will be: - * [ Center ] [ Front Left ] [ Front Right ] [ LFE ] [ Surround Left ] [ Surround Right ] - */ - - for (i = 0; i < MAX_ELEM_ID; i++) { - for (type = 0; type < 4; type++) { - if (che_pos[type][i]) { - if (!ac->che[type][i] && !(ac->che[type][i] = av_mallocz(sizeof(ChannelElement)))) - return AVERROR(ENOMEM); - if (type != TYPE_CCE) { - ac->output_data[channels++] = ac->che[type][i]->ch[0].ret; - if (type == TYPE_CPE) { - ac->output_data[channels++] = ac->che[type][i]->ch[1].ret; - } - } - } else - av_freep(&ac->che[type][i]); + if (channel_config) { + for (i = 0; i < tags_per_config[channel_config]; i++) { + if ((ret = che_configure(ac, che_pos, + aac_channel_layout_map[channel_config - 1][i][0], + aac_channel_layout_map[channel_config - 1][i][1], + &channels))) + return ret; } - } - if (channel_config) { memset(ac->tag_che_map, 0, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0])); ac->tags_mapped = 0; + + avctx->channel_layout = aac_channel_layout[channel_config - 1]; } else { + /* Allocate or free elements depending on if they are in the + * current program configuration. + * + * Set up default 1:1 output mapping. + * + * For a 5.1 stream the output order will be: + * [ Center ] [ Front Left ] [ Front Right ] [ LFE ] [ Surround Left ] [ Surround Right ] + */ + + for (i = 0; i < MAX_ELEM_ID; i++) { + for (type = 0; type < 4; type++) { + if ((ret = che_configure(ac, che_pos, type, i, &channels))) + return ret; + } + } + memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0])); ac->tags_mapped = 4 * MAX_ELEM_ID; + + avctx->channel_layout = 0; } avctx->channels = channels; - ac->output_configured = 1; + ac->output_configured = oc_type; return 0; } @@ -357,7 +395,7 @@ static int decode_ga_specific_config(AACContext *ac, GetBitContext *gb, if ((ret = set_default_channel_config(ac, new_che_pos, channel_config))) return ret; } - if ((ret = output_configure(ac, ac->che_pos, new_che_pos, channel_config))) + if ((ret = output_configure(ac, ac->che_pos, new_che_pos, channel_config, OC_GLOBAL_HDR))) return ret; if (extension_flag) { @@ -474,17 +512,17 @@ static av_cold int aac_decode_init(AVCodecContext *avccontext) avccontext->sample_fmt = SAMPLE_FMT_S16; avccontext->frame_size = 1024; - AAC_INIT_VLC_STATIC( 0, 144); - AAC_INIT_VLC_STATIC( 1, 114); - AAC_INIT_VLC_STATIC( 2, 188); - AAC_INIT_VLC_STATIC( 3, 180); - AAC_INIT_VLC_STATIC( 4, 172); - AAC_INIT_VLC_STATIC( 5, 140); - AAC_INIT_VLC_STATIC( 6, 168); - AAC_INIT_VLC_STATIC( 7, 114); - AAC_INIT_VLC_STATIC( 8, 262); - AAC_INIT_VLC_STATIC( 9, 248); - AAC_INIT_VLC_STATIC(10, 384); + AAC_INIT_VLC_STATIC( 0, 304); + AAC_INIT_VLC_STATIC( 1, 270); + AAC_INIT_VLC_STATIC( 2, 550); + AAC_INIT_VLC_STATIC( 3, 300); + AAC_INIT_VLC_STATIC( 4, 328); + AAC_INIT_VLC_STATIC( 5, 294); + AAC_INIT_VLC_STATIC( 6, 306); + AAC_INIT_VLC_STATIC( 7, 268); + AAC_INIT_VLC_STATIC( 8, 510); + AAC_INIT_VLC_STATIC( 9, 366); + AAC_INIT_VLC_STATIC(10, 462); dsputil_init(&ac->dsp, avccontext); @@ -494,7 +532,7 @@ static av_cold int aac_decode_init(AVCodecContext *avccontext) // 32768 - Required to scale values to the correct range for the bias method // for float to int16 conversion. - if (ac->dsp.float_to_int16 == ff_float_to_int16_c) { + if (ac->dsp.float_to_int16_interleave == ff_float_to_int16_interleave_c) { ac->add_bias = 385.0f; ac->sf_scale = 1. / (-1024. * 32768.); ac->sf_offset = 0; @@ -519,8 +557,16 @@ static av_cold int aac_decode_init(AVCodecContext *avccontext) // window initialization ff_kbd_window_init(ff_aac_kbd_long_1024, 4.0, 1024); ff_kbd_window_init(ff_aac_kbd_short_128, 6.0, 128); - ff_sine_window_init(ff_sine_1024, 1024); - ff_sine_window_init(ff_sine_128, 128); + ff_init_ff_sine_windows(10); + ff_init_ff_sine_windows( 7); + + if (!cbrt_tab[(1<<13) - 1]) { + for (i = 0; i < 1<<13; i++) { + union float754 f; + f.f = cbrtf(i) * i; + cbrt_tab[i] = f.i; + } + } return 0; } @@ -645,7 +691,7 @@ static int decode_band_types(AACContext *ac, enum BandType band_type[120], for (g = 0; g < ics->num_window_groups; g++) { int k = 0; while (k < ics->max_sfb) { - uint8_t sect_len = k; + uint8_t sect_end = k; int sect_len_incr; int sect_band_type = get_bits(gb, 4); if (sect_band_type == 12) { @@ -653,17 +699,17 @@ static int decode_band_types(AACContext *ac, enum BandType band_type[120], return -1; } while ((sect_len_incr = get_bits(gb, bits)) == (1 << bits) - 1) - sect_len += sect_len_incr; - sect_len += sect_len_incr; - if (sect_len > ics->max_sfb) { + sect_end += sect_len_incr; + sect_end += sect_len_incr; + if (sect_end > ics->max_sfb) { av_log(ac->avccontext, AV_LOG_ERROR, "Number of bands (%d) exceeds limit (%d).\n", - sect_len, ics->max_sfb); + sect_end, ics->max_sfb); return -1; } - for (; k < sect_len; k++) { + for (; k < sect_end; k++) { band_type [idx] = sect_band_type; - band_type_run_end[idx++] = sect_len; + band_type_run_end[idx++] = sect_end; } } } @@ -820,6 +866,74 @@ static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb, } } +#ifndef VMUL2 +static inline float *VMUL2(float *dst, const float *v, unsigned idx, + const float *scale) +{ + float s = *scale; + *dst++ = v[idx & 15] * s; + *dst++ = v[idx>>4 & 15] * s; + return dst; +} +#endif + +#ifndef VMUL4 +static inline float *VMUL4(float *dst, const float *v, unsigned idx, + const float *scale) +{ + float s = *scale; + *dst++ = v[idx & 3] * s; + *dst++ = v[idx>>2 & 3] * s; + *dst++ = v[idx>>4 & 3] * s; + *dst++ = v[idx>>6 & 3] * s; + return dst; +} +#endif + +#ifndef VMUL2S +static inline float *VMUL2S(float *dst, const float *v, unsigned idx, + unsigned sign, const float *scale) +{ + union float754 s0, s1; + + s0.f = s1.f = *scale; + s0.i ^= sign >> 1 << 31; + s1.i ^= sign << 31; + + *dst++ = v[idx & 15] * s0.f; + *dst++ = v[idx>>4 & 15] * s1.f; + + return dst; +} +#endif + +#ifndef VMUL4S +static inline float *VMUL4S(float *dst, const float *v, unsigned idx, + unsigned sign, const float *scale) +{ + unsigned nz = idx >> 12; + union float754 s = { .f = *scale }; + union float754 t; + + t.i = s.i ^ (sign & 1<<31); + *dst++ = v[idx & 3] * t.f; + + sign <<= nz & 1; nz >>= 1; + t.i = s.i ^ (sign & 1<<31); + *dst++ = v[idx>>2 & 3] * t.f; + + sign <<= nz & 1; nz >>= 1; + t.i = s.i ^ (sign & 1<<31); + *dst++ = v[idx>>4 & 3] * t.f; + + sign <<= nz & 1; nz >>= 1; + t.i = s.i ^ (sign & 1<<31); + *dst++ = v[idx>>6 & 3] * t.f; + + return dst; +} +#endif + /** * Decode spectral data; reference: table 4.50. * Dequantize and scale spectral data; reference: 4.6.3.3. @@ -833,7 +947,7 @@ static void decode_mid_side_stereo(ChannelElement *cpe, GetBitContext *gb, * @return Returns error status. 0 - OK, !0 - error */ static int decode_spectrum_and_dequant(AACContext *ac, float coef[1024], - GetBitContext *gb, float sf[120], + GetBitContext *gb, const float sf[120], int pulse_present, const Pulse *pulse, const IndividualChannelStream *ics, enum BandType band_type[120]) @@ -842,100 +956,228 @@ static int decode_spectrum_and_dequant(AACContext *ac, float coef[1024], const int c = 1024 / ics->num_windows; const uint16_t *offsets = ics->swb_offset; float *coef_base = coef; - static const float sign_lookup[] = { 1.0f, -1.0f }; + int err_idx; for (g = 0; g < ics->num_windows; g++) memset(coef + g * 128 + offsets[ics->max_sfb], 0, sizeof(float) * (c - offsets[ics->max_sfb])); for (g = 0; g < ics->num_window_groups; g++) { + unsigned g_len = ics->group_len[g]; + for (i = 0; i < ics->max_sfb; i++, idx++) { - const int cur_band_type = band_type[idx]; - const int dim = cur_band_type >= FIRST_PAIR_BT ? 2 : 4; - const int is_cb_unsigned = IS_CODEBOOK_UNSIGNED(cur_band_type); + const unsigned cbt_m1 = band_type[idx] - 1; + float *cfo = coef + offsets[i]; + int off_len = offsets[i + 1] - offsets[i]; int group; - if (cur_band_type == ZERO_BT || cur_band_type == INTENSITY_BT2 || cur_band_type == INTENSITY_BT) { - for (group = 0; group < ics->group_len[g]; group++) { - memset(coef + group * 128 + offsets[i], 0, (offsets[i + 1] - offsets[i]) * sizeof(float)); + + if (cbt_m1 >= INTENSITY_BT2 - 1) { + for (group = 0; group < g_len; group++, cfo+=128) { + memset(cfo, 0, off_len * sizeof(float)); } - } else if (cur_band_type == NOISE_BT) { - for (group = 0; group < ics->group_len[g]; group++) { + } else if (cbt_m1 == NOISE_BT - 1) { + for (group = 0; group < g_len; group++, cfo+=128) { float scale; float band_energy; - float *cf = coef + group * 128 + offsets[i]; - int len = offsets[i+1] - offsets[i]; - for (k = 0; k < len; k++) { + for (k = 0; k < off_len; k++) { ac->random_state = lcg_random(ac->random_state); - cf[k] = ac->random_state; + cfo[k] = ac->random_state; } - band_energy = ac->dsp.scalarproduct_float(cf, cf, len); + band_energy = ac->dsp.scalarproduct_float(cfo, cfo, off_len); scale = sf[idx] / sqrtf(band_energy); - ac->dsp.vector_fmul_scalar(cf, cf, scale, len); + ac->dsp.vector_fmul_scalar(cfo, cfo, scale, off_len); } } else { - for (group = 0; group < ics->group_len[g]; group++) { - const float *vq[96]; - const float **vqp = vq; - float *cf = coef + (group << 7) + offsets[i]; - int len = offsets[i + 1] - offsets[i]; - - for (k = offsets[i]; k < offsets[i + 1]; k += dim) { - const int index = get_vlc2(gb, vlc_spectral[cur_band_type - 1].table, 6, 3); - const int coef_tmp_idx = (group << 7) + k; - const float *vq_ptr; - int j; - if (index >= ff_aac_spectral_sizes[cur_band_type - 1]) { - av_log(ac->avccontext, AV_LOG_ERROR, - "Read beyond end of ff_aac_codebook_vectors[%d][]. index %d >= %d\n", - cur_band_type - 1, index, ff_aac_spectral_sizes[cur_band_type - 1]); - return -1; - } - vq_ptr = &ff_aac_codebook_vectors[cur_band_type - 1][index * dim]; - *vqp++ = vq_ptr; - if (is_cb_unsigned) { - if (vq_ptr[0]) - coef[coef_tmp_idx ] = sign_lookup[get_bits1(gb)]; - if (vq_ptr[1]) - coef[coef_tmp_idx + 1] = sign_lookup[get_bits1(gb)]; - if (dim == 4) { - if (vq_ptr[2]) - coef[coef_tmp_idx + 2] = sign_lookup[get_bits1(gb)]; - if (vq_ptr[3]) - coef[coef_tmp_idx + 3] = sign_lookup[get_bits1(gb)]; + const float *vq = ff_aac_codebook_vector_vals[cbt_m1]; + const uint16_t *cb_vector_idx = ff_aac_codebook_vector_idx[cbt_m1]; + VLC_TYPE (*vlc_tab)[2] = vlc_spectral[cbt_m1].table; + const int cb_size = ff_aac_spectral_sizes[cbt_m1]; + OPEN_READER(re, gb); + + switch (cbt_m1 >> 1) { + case 0: + for (group = 0; group < g_len; group++, cfo+=128) { + float *cf = cfo; + int len = off_len; + + do { + int code; + unsigned cb_idx; + + UPDATE_CACHE(re, gb); + GET_VLC(code, re, gb, vlc_tab, 8, 2); + + if (code >= cb_size) { + err_idx = code; + goto err_cb_overflow; } - if (cur_band_type == ESC_BT) { - for (j = 0; j < 2; j++) { - if (vq_ptr[j] == 64.0f) { - int n = 4; - /* The total length of escape_sequence must be < 22 bits according - to the specification (i.e. max is 11111111110xxxxxxxxxx). */ - while (get_bits1(gb) && n < 15) n++; - if (n == 15) { - av_log(ac->avccontext, AV_LOG_ERROR, "error in spectral data, ESC overflow\n"); - return -1; - } - n = (1 << n) + get_bits(gb, n); - coef[coef_tmp_idx + j] *= cbrtf(n) * n; - } else - coef[coef_tmp_idx + j] *= vq_ptr[j]; - } + + cb_idx = cb_vector_idx[code]; + cf = VMUL4(cf, vq, cb_idx, sf + idx); + } while (len -= 4); + } + break; + + case 1: + for (group = 0; group < g_len; group++, cfo+=128) { + float *cf = cfo; + int len = off_len; + + do { + int code; + unsigned nnz; + unsigned cb_idx; + uint32_t bits; + + UPDATE_CACHE(re, gb); + GET_VLC(code, re, gb, vlc_tab, 8, 2); + + if (code >= cb_size) { + err_idx = code; + goto err_cb_overflow; } - } + +#if MIN_CACHE_BITS < 20 + UPDATE_CACHE(re, gb); +#endif + cb_idx = cb_vector_idx[code]; + nnz = cb_idx >> 8 & 15; + bits = SHOW_UBITS(re, gb, nnz) << (32-nnz); + LAST_SKIP_BITS(re, gb, nnz); + cf = VMUL4S(cf, vq, cb_idx, bits, sf + idx); + } while (len -= 4); } + break; + + case 2: + for (group = 0; group < g_len; group++, cfo+=128) { + float *cf = cfo; + int len = off_len; - if (is_cb_unsigned && cur_band_type != ESC_BT) { - ac->dsp.vector_fmul_sv_scalar[dim>>2]( - cf, cf, vq, sf[idx], len); - } else if (cur_band_type == ESC_BT) { - ac->dsp.vector_fmul_scalar(cf, cf, sf[idx], len); - } else { /* !is_cb_unsigned */ - ac->dsp.sv_fmul_scalar[dim>>2](cf, vq, sf[idx], len); + do { + int code; + unsigned cb_idx; + + UPDATE_CACHE(re, gb); + GET_VLC(code, re, gb, vlc_tab, 8, 2); + + if (code >= cb_size) { + err_idx = code; + goto err_cb_overflow; + } + + cb_idx = cb_vector_idx[code]; + cf = VMUL2(cf, vq, cb_idx, sf + idx); + } while (len -= 2); + } + break; + + case 3: + case 4: + for (group = 0; group < g_len; group++, cfo+=128) { + float *cf = cfo; + int len = off_len; + + do { + int code; + unsigned nnz; + unsigned cb_idx; + unsigned sign; + + UPDATE_CACHE(re, gb); + GET_VLC(code, re, gb, vlc_tab, 8, 2); + + if (code >= cb_size) { + err_idx = code; + goto err_cb_overflow; + } + + cb_idx = cb_vector_idx[code]; + nnz = cb_idx >> 8 & 15; + sign = SHOW_UBITS(re, gb, nnz) << (cb_idx >> 12); + LAST_SKIP_BITS(re, gb, nnz); + cf = VMUL2S(cf, vq, cb_idx, sign, sf + idx); + } while (len -= 2); + } + break; + + default: + for (group = 0; group < g_len; group++, cfo+=128) { + float *cf = cfo; + uint32_t *icf = (uint32_t *) cf; + int len = off_len; + + do { + int code; + unsigned nzt, nnz; + unsigned cb_idx; + uint32_t bits; + int j; + + UPDATE_CACHE(re, gb); + GET_VLC(code, re, gb, vlc_tab, 8, 2); + + if (!code) { + *icf++ = 0; + *icf++ = 0; + continue; + } + + if (code >= cb_size) { + err_idx = code; + goto err_cb_overflow; + } + + cb_idx = cb_vector_idx[code]; + nnz = cb_idx >> 12; + nzt = cb_idx >> 8; + bits = SHOW_UBITS(re, gb, nnz) << (32-nnz); + LAST_SKIP_BITS(re, gb, nnz); + + for (j = 0; j < 2; j++) { + if (nzt & 1< 8) { + av_log(ac->avccontext, AV_LOG_ERROR, "error in spectral data, ESC overflow\n"); + return -1; + } + +#if MIN_CACHE_BITS < 21 + LAST_SKIP_BITS(re, gb, b + 1); + UPDATE_CACHE(re, gb); +#else + SKIP_BITS(re, gb, b + 1); +#endif + b += 4; + n = (1 << b) + SHOW_UBITS(re, gb, b); + LAST_SKIP_BITS(re, gb, b); + *icf++ = cbrt_tab[n] | (bits & 1<<31); + bits <<= 1; + } else { + unsigned v = ((const uint32_t*)vq)[cb_idx & 15]; + *icf++ = (bits & 1<<31) | v; + bits <<= !!v; + } + cb_idx >>= 4; + } + } while (len -= 2); + + ac->dsp.vector_fmul_scalar(cfo, cfo, sf[idx], off_len); } } + + CLOSE_READER(re, gb); } } - coef += ics->group_len[g] << 7; + coef += g_len << 7; } if (pulse_present) { @@ -955,6 +1197,12 @@ static int decode_spectrum_and_dequant(AACContext *ac, float coef[1024], } } return 0; + +err_cb_overflow: + av_log(ac->avccontext, AV_LOG_ERROR, + "Read beyond end of ff_aac_codebook_vectors[%d][]. index %d >= %d\n", + band_type[idx], err_idx, ff_aac_spectral_sizes[band_type[idx]]); + return -1; } static av_always_inline float flt16_round(float pf) @@ -1643,18 +1891,24 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb) size = ff_aac_parse_header(gb, &hdr_info); if (size > 0) { - if (!ac->output_configured && hdr_info.chan_config) { + if (ac->output_configured != OC_LOCKED && hdr_info.chan_config) { enum ChannelPosition new_che_pos[4][MAX_ELEM_ID]; memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0])); ac->m4ac.chan_config = hdr_info.chan_config; if (set_default_channel_config(ac, new_che_pos, hdr_info.chan_config)) return -7; - if (output_configure(ac, ac->che_pos, new_che_pos, 1)) + if (output_configure(ac, ac->che_pos, new_che_pos, hdr_info.chan_config, OC_TRIAL_FRAME)) return -7; + } else if (ac->output_configured != OC_LOCKED) { + ac->output_configured = OC_NONE; } + if (ac->output_configured != OC_LOCKED) + ac->m4ac.sbr = -1; ac->m4ac.sample_rate = hdr_info.sample_rate; ac->m4ac.sampling_index = hdr_info.sampling_index; ac->m4ac.object_type = hdr_info.object_type; + if (!ac->avccontext->sample_rate) + ac->avccontext->sample_rate = hdr_info.sample_rate; if (hdr_info.num_aac_frames == 1) { if (!hdr_info.crc_absent) skip_bits(gb, 16); @@ -1727,11 +1981,11 @@ static int aac_decode_frame(AVCodecContext *avccontext, void *data, memset(new_che_pos, 0, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0])); if ((err = decode_pce(ac, new_che_pos, &gb))) break; - if (ac->output_configured) + if (ac->output_configured > OC_TRIAL_PCE) av_log(avccontext, AV_LOG_ERROR, "Not evaluating a further program_config_element as this construct is dubious at best.\n"); else - err = output_configure(ac, ac->che_pos, new_che_pos, 0); + err = output_configure(ac, ac->che_pos, new_che_pos, 0, OC_TRIAL_PCE); break; } @@ -1771,6 +2025,9 @@ static int aac_decode_frame(AVCodecContext *avccontext, void *data, ac->dsp.float_to_int16_interleave(data, (const float **)ac->output_data, 1024, avccontext->channels); + if (ac->output_configured) + ac->output_configured = OC_LOCKED; + return buf_size; } @@ -1802,4 +2059,5 @@ AVCodec aac_decoder = { .sample_fmts = (const enum SampleFormat[]) { SAMPLE_FMT_S16,SAMPLE_FMT_NONE }, + .channel_layouts = aac_channel_layout, };