[FFmpeg-devel] AAC decoder round 7
Michael Niedermayer
michaelni
Mon Aug 11 15:23:49 CEST 2008
On Mon, Aug 11, 2008 at 12:50:09PM +0100, Robert Swain wrote:
> $subj
>
> Regards,
> Rob
[...]
> Index: libavcodec/aactab.c
> ===================================================================
> --- libavcodec/aactab.c (revision 14694)
> +++ libavcodec/aactab.c (working copy)
> @@ -32,6 +32,11 @@
>
> #include <stdint.h>
>
> +DECLARE_ALIGNED(16, float, ff_aac_kbd_long_1024[1024]);
> +DECLARE_ALIGNED(16, float, ff_aac_kbd_short_128[128]);
> +DECLARE_ALIGNED(16, float, ff_aac_sine_long_1024[1024]);
> +DECLARE_ALIGNED(16, float, ff_aac_sine_short_128[128]);
i think these can be shared with at least wma
i dont remember what vorbis used?
[...]
> /**
> + * Configure output channel order based on the current program configuration element.
> + *
> + * @param che_pos current channel position configuration
> + * @param new_che_pos New channel position configuration - we only do something if it differs from the current one.
> + *
> + * @return Returns error status. 0 - OK, !0 - error
> + */
> +static int output_configure(AACContext *ac, enum ChannelPosition che_pos[4][MAX_ELEM_ID],
> + enum ChannelPosition new_che_pos[4][MAX_ELEM_ID]) {
> + AVCodecContext *avctx = ac->avccontext;
> + int i, type, channels = 0;
> +
> + if(!memcmp(che_pos, new_che_pos, 4 * MAX_ELEM_ID * sizeof(new_che_pos[0][0])))
> + return 0; /* no change */
> +
> + 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:
> + * [ Front Left ] [ Front Right ] [ Center ] [ 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]);
> + }
> + }
> +
> + avctx->channels = channels;
> + return 0;
> +}
> +
> +/**
> * Decode an array of 4 bit element IDs, optionally interleaved with a stereo/mono switching bit.
> *
> * @param cpe_map Stereo (Channel Pair Element) map, NULL if stereo bit is not present.
> @@ -209,6 +267,17 @@
> return 0;
> }
>
> +/**
> + * Decode GA "General Audio" specific configuration; reference: table 4.1.
> + *
> + * @return Returns error status. 0 - OK, !0 - error
> + */
> +static int decode_ga_specific_config(AACContext * ac, GetBitContext * gb, int channel_config) {
> + enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
> + int extension_flag, ret;
> +
> + if(get_bits1(gb)) { // frameLengthFlag
> + av_log_missing_feature(ac->avccontext, "960/120 MDCT window is", 1);
> return -1;
> }
>
> @@ -289,6 +358,17 @@
> return 0;
> }
>
> +/**
> + * linear congruential pseudorandom number generator
> + *
> + * @param previous_val pointer to the current state of the generator
> + *
> + * @return Returns a 32-bit pseudorandom integer
> + */
> +static av_always_inline int lcg_random(int previous_val) {
> + return previous_val * 1664525 + 1013904223;
> +}
> +
> static av_cold int aac_decode_init(AVCodecContext * avccontext) {
> AACContext * ac = avccontext->priv_data;
> int i;
ok
[...]
> @@ -380,7 +465,42 @@
> ics->use_kb_window[0] = get_bits1(gb);
> ics->num_window_groups = 1;
> ics->group_len[0] = 1;
> + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
> + int i;
> + ics->max_sfb = get_bits(gb, 4);
> + for (i = 0; i < 7; i++) {
> + if (get_bits1(gb)) {
> + ics->group_len[ics->num_window_groups-1]++;
> + } else {
> + ics->num_window_groups++;
> + ics->group_len[ics->num_window_groups-1] = 1;
> + }
> + }
> + ics->swb_offset = swb_offset_128[ac->m4ac.sampling_index];
> + ics->num_swb = ff_aac_num_swb_128[ac->m4ac.sampling_index];
> + ics->num_windows = 8;
> + ics->tns_max_bands = tns_max_bands_128[ac->m4ac.sampling_index];
> + } else {
> + ics->max_sfb = get_bits(gb, 6);
> + ics->swb_offset = swb_offset_1024[ac->m4ac.sampling_index];
> + ics->num_swb = ff_aac_num_swb_1024[ac->m4ac.sampling_index];
> + ics->num_windows = 1;
> + ics->tns_max_bands = tns_max_bands_1024[ac->m4ac.sampling_index];
vertical align
> + if (get_bits1(gb)) {
> + av_log_missing_feature(ac->avccontext, "Predictor bit set but LTP is", 1);
> + memset(ics, 0, sizeof(IndividualChannelStream));
> + return -1;
> + }
> + }
>
> + if(ics->max_sfb > ics->num_swb) {
> + av_log(ac->avccontext, AV_LOG_ERROR,
> + "Number of scalefactor bands in group (%d) exceeds limit (%d).\n",
> + ics->max_sfb, ics->num_swb);
> + memset(ics, 0, sizeof(IndividualChannelStream));
> + return -1;
> + }
> +
> return 0;
> }
>
ok
[...]
> @@ -520,8 +682,88 @@
> */
> static void decode_mid_side_stereo(ChannelElement * cpe, GetBitContext * gb,
> int ms_present) {
> + int idx;
> + if (ms_present == 1) {
> + for (idx = 0; idx < cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb; idx++)
> + cpe->ms_mask[idx] = get_bits1(gb);
> + } else if (ms_present == 2) {
> + memset(cpe->ms_mask, 1, cpe->ch[0].ics.num_window_groups * cpe->ch[0].ics.max_sfb * sizeof(cpe->ms_mask[0]));
> + }
> +}
>
ok
> /**
> + * Decode spectral data; reference: table 4.50.
> + *
> + * @param band_type array of the used band type
> + * @param icoef array of quantized spectral data
> + *
> + * @return Returns error status. 0 - OK, !0 - error
> + */
> +static int decode_spectrum(AACContext * ac, int icoef[1024], GetBitContext * gb,
> + const IndividualChannelStream * ics, enum BandType band_type[120]) {
> + int i, k, g, idx = 0;
> + const uint16_t * offsets = ics->swb_offset;
> +
> + for (g = 0; g < ics->num_window_groups; 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);
> + int group;
> + if (cur_band_type == ZERO_BT) {
> + for (group = 0; group < ics->group_len[g]; group++) {
> + memset(icoef + group * 128 + offsets[i], 0, (offsets[i+1] - offsets[i])*sizeof(int));
> + }
> + }else if (cur_band_type != NOISE_BT && cur_band_type != INTENSITY_BT2 && cur_band_type != INTENSITY_BT) {
> + for (group = 0; group < ics->group_len[g]; group++) {
> + 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_idx = (group << 7) + k;
> + const int8_t *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];
> + if (is_cb_unsigned) {
> + for (j = 0; j < dim; j++)
> + if (vq_ptr[j])
> + icoef[coef_idx + j] = 1 - 2*get_bits1(gb);
> + }else {
> + for (j = 0; j < dim; j++)
> + icoef[coef_idx + j] = 1;
> + }
> + if (cur_band_type == ESC_BT) {
> + for (j = 0; j < 2; j++) {
> + if (vq_ptr[j] == 16) {
> + 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;
> + }
> + icoef[coef_idx + j] *= (1<<n) + get_bits(gb, n);
> + }else
> + icoef[coef_idx + j] *= vq_ptr[j];
> + }
> + }else
> + for (j = 0; j < dim; j++)
> + icoef[coef_idx + j] *= vq_ptr[j];
> + }
> + }
> + }
> + }
> + icoef += ics->group_len[g]<<7;
> + }
> + return 0;
> +}
> +
> +/**
> * Add pulses with particular amplitudes to the quantized spectral data; reference: 4.6.3.3.
> *
> * @param pulse pointer to pulse data struct
> @@ -538,6 +780,46 @@
> }
>
> /**
> + * Dequantize and scale spectral data; reference: 4.6.3.3.
> + *
> + * @param icoef array of quantized spectral data
> + * @param band_type array of the used band type
> + * @param sf array of scalefactors or intensity stereo positions
> + * @param coef array of dequantized, scaled spectral data
> + */
> +static void dequant(AACContext * ac, float coef[1024], const int icoef[1024], float sf[120],
> + const IndividualChannelStream * ics, enum BandType band_type[120]) {
> + const uint16_t * offsets = ics->swb_offset;
> + const int c = 1024/ics->num_windows;
> + int g, i, group, k, idx = 0;
> +
> + 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++) {
> + for (i = 0; i < ics->max_sfb; i++, idx++) {
> + if (band_type[idx] == NOISE_BT) {
> + const float scale = sf[idx] / ((offsets[i+1] - offsets[i]) * PNS_MEAN_ENERGY);
> + for (group = 0; group < ics->group_len[g]; group++) {
> + for (k = offsets[i]; k < offsets[i+1]; k++) {
> + ac->random_state = lcg_random(ac->random_state);
> + coef[group*128+k] = ac->random_state * scale;
> + }
> + }
> + } else if (band_type[idx] != INTENSITY_BT && band_type[idx] != INTENSITY_BT2) {
> + for (group = 0; group < ics->group_len[g]; group++) {
> + for (k = offsets[i]; k < offsets[i+1]; k++) {
> + coef[group*128+k] = ivquant(icoef[group*128+k]) * sf[idx];
> + }
> + }
> + }
> + }
> + coef += ics->group_len[g]*128;
> + icoef += ics->group_len[g]*128;
> + }
> +}
> +
> +/**
dequant and decode_spectrum() can be merged, especially the VQ tables can
already include ivquant().
and yes i know that this means add_pulses will be more tricky
> * Decode an individual_channel_stream payload; reference: table 4.44.
> *
> * @param common_window Channels have independent [0], or shared [1], Individual Channel Stream information.
> @@ -597,6 +879,71 @@
> }
>
> /**
> + * Mid/Side stereo decoding; reference: 4.6.8.1.3.
> + */
> +static void apply_mid_side_stereo(ChannelElement * cpe) {
> + const IndividualChannelStream * ics = &cpe->ch[0].ics;
> + float *ch0 = cpe->ch[0].coeffs;
> + float *ch1 = cpe->ch[1].coeffs;
> + int g, i, k, group, idx = 0;
> + const uint16_t * offsets = ics->swb_offset;
> + for (g = 0; g < ics->num_window_groups; g++) {
> + for (i = 0; i < ics->max_sfb; i++, idx++) {
> + if (cpe->ms_mask[idx] &&
> + 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++) {
> + for (k = offsets[i]; k < offsets[i+1]; k++) {
> + float tmp = ch0[group*128 + k] - ch1[group*128 + k];
> + ch0[group*128 + k] += ch1[group*128 + k];
> + ch1[group*128 + k] = tmp;
> + }
> + }
> + }
> + }
> + ch0 += ics->group_len[g]*128;
> + ch1 += ics->group_len[g]*128;
> + }
please try the following, iam curious if its faster (START/STOP_TIMER),
it does more if() but accesses elements in sequential order
for (g = 0; g < ics->num_window_groups; g++) {
for (group = 0; group < ics->group_len[g]; group++) {
for (i = 0; i < ics->max_sfb; i++, idx++) {
if (cpe->ms_mask[idx] &&
cpe->ch[0].band_type[idx] < NOISE_BT && cpe->ch[1].band_type[idx] < NOISE_BT) {
for (k = offsets[i]; k < offsets[i+1]; k++) {
float tmp = ch0[k] - ch1[k];
ch0[k] += ch1[k];
ch1[k] = tmp;
}
}
}
idx -= ics->max_sfb;
ch0 += 128;
ch1 += 128;
}
idx += ics->max_sfb;
}
[...]
> @@ -636,6 +983,83 @@
> }
>
> /**
> + * Decode coupling_channel_element; reference: table 4.8.
> + *
> + * @param elem_id Identifies the instance of a syntax element.
> + *
> + * @return Returns error status. 0 - OK, !0 - error
> + */
> +static int decode_cce(AACContext * ac, GetBitContext * gb, int elem_id) {
> + int num_gain = 0;
> + int c, g, sfb, ret, idx = 0;
> + int sign;
> + float scale;
> + SingleChannelElement * sce;
> + ChannelCoupling * coup;
> +
> + sce = &ac->che[TYPE_CCE][elem_id]->ch[0];
> +
> + coup = &ac->che[TYPE_CCE][elem_id]->coup;
instead if elem_id ac->che[TYPE_CCE][elem_id] could be passed as argument
> +
> + coup->coupling_point = 2*get_bits1(gb);
> + coup->num_coupled = get_bits(gb, 3);
> + for (c = 0; c <= coup->num_coupled; c++) {
> + num_gain++;
> + coup->type[c] = get_bits1(gb) ? TYPE_CPE : TYPE_SCE;
> + coup->id_select[c] = get_bits(gb, 4);
> + if (coup->type[c] == TYPE_CPE) {
> + coup->ch_select[c] = get_bits(gb, 2);
> + if (coup->ch_select[c] == 3)
> + num_gain++;
> + } else
> + coup->ch_select[c] = 1;
> + }
> + coup->coupling_point += get_bits1(gb);
> +
> + if (coup->coupling_point == 2) {
> + av_log(ac->avccontext, AV_LOG_ERROR,
> + "Independently switched CCE with 'invalid' domain signalled.\n");
> + memset(coup, 0, sizeof(ChannelCoupling));
> + return -1;
> + }
> +
> + sign = get_bits(gb, 1);
> + scale = pow(2., pow(2., get_bits(gb, 2) - 3));
> +
> + if ((ret = decode_ics(ac, sce, gb, 0, 0)))
> + return ret;
> +
> + for (c = 0; c < num_gain; c++) {
> + int cge = 1;
> + int gain = 0;
> + float gain_cache = 1.;
> + if (c) {
> + cge = coup->coupling_point == AFTER_IMDCT ? 1 : get_bits1(gb);
> + gain = cge ? get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60: 0;
> + gain_cache = pow(scale, gain);
> + }
> + for (g = 0; g < sce->ics.num_window_groups; g++)
> + for (sfb = 0; sfb < sce->ics.max_sfb; sfb++, idx++)
> + if (sce->band_type[idx] != ZERO_BT) {
> + if (!cge) {
> + int t = get_vlc2(gb, vlc_scalefactors.table, 7, 3) - 60;
> + if (t) {
> + int s = 1;
> + if (sign) {
> + s -= 2 * (t & 0x1);
> + t >>= 1;
> + }
> + gain += t;
> + gain_cache = pow(scale, gain) * s;
> + }
> + }
> + coup->gain[c][idx] = gain_cache;
> + }
> + }
> + return 0;
> +}
> +
> +/**
> * Decode Spectral Band Replication extension data; reference: table 4.55.
> *
> * @param crc flag indicating the presence of CRC checksum
ok
> @@ -651,6 +1075,23 @@
> }
>
> /**
> + * Parse whether channels are to be excluded from Dynamic Range Compression; reference: table 4.53.
> + *
> + * @return Returns number of bytes consumed.
> + */
> +static int decode_drc_channel_exclusions(DynamicRangeControl *che_drc, GetBitContext * gb) {
> + int i;
> + int num_excl_chan = 0;
> +
> + do {
> + for (i = 0; i < 7; i++)
> + che_drc->exclude_mask[num_excl_chan++] = get_bits1(gb);
> + } while (num_excl_chan < MAX_CHANNELS - 7 && get_bits1(gb));
> +
> + return num_excl_chan / 7;
> +}
> +
> +/**
> * Decode dynamic range information; reference: table 4.52.
> *
> * @param cnt length of TYPE_FIL syntactic element in bytes
ok
[...]
> static void imdct_and_windowing(AACContext * ac, SingleChannelElement * sce) {
> @@ -746,6 +1252,55 @@
> float * buf = ac->buf_mdct;
> int i;
>
> + if (ics->window_sequence[0] == EIGHT_SHORT_SEQUENCE) {
> + if (ics->window_sequence[1] == ONLY_LONG_SEQUENCE || ics->window_sequence[1] == LONG_STOP_SEQUENCE)
> + av_log(ac->avccontext, AV_LOG_WARNING,
> + "Transition from an ONLY_LONG or LONG_STOP to an EIGHT_SHORT sequence detected. "
> + "If you heard an audible artifact, please submit the sample to the FFmpeg developers.\n");
> + for (i = 0; i < 2048; i += 256) {
> + ff_imdct_calc(&ac->mdct_small, buf + i, in + i/2, out);
> + ac->dsp.vector_fmul_reverse(ac->revers + i/2, buf + i + 128, swindow, 128);
> + }
> + for (i = 0; i < 448; i++) out[i] = saved[i] + ac->add_bias;
> +
> + ac->dsp.vector_fmul_add_add(out + 448 + 0*128, buf + 0*128, swindow_prev, saved + 448 , ac->add_bias, 128, 1);
> + ac->dsp.vector_fmul_add_add(out + 448 + 1*128, buf + 2*128, swindow, ac->revers + 0*128, ac->add_bias, 128, 1);
> + ac->dsp.vector_fmul_add_add(out + 448 + 2*128, buf + 4*128, swindow, ac->revers + 1*128, ac->add_bias, 128, 1);
> + ac->dsp.vector_fmul_add_add(out + 448 + 3*128, buf + 6*128, swindow, ac->revers + 2*128, ac->add_bias, 128, 1);
> + ac->dsp.vector_fmul_add_add(out + 448 + 4*128, buf + 8*128, swindow, ac->revers + 3*128, ac->add_bias, 64, 1);
> +
> +#if 0
> + vector_fmul_add_add_add(&ac->dsp, out + 448 + 1*128, buf + 2*128, swindow, saved + 448 + 1*128, ac->revers + 0*128, ac->add_bias, 128);
> + vector_fmul_add_add_add(&ac->dsp, out + 448 + 2*128, buf + 4*128, swindow, saved + 448 + 2*128, ac->revers + 1*128, ac->add_bias, 128);
> + vector_fmul_add_add_add(&ac->dsp, out + 448 + 3*128, buf + 6*128, swindow, saved + 448 + 3*128, ac->revers + 2*128, ac->add_bias, 128);
> + vector_fmul_add_add_add(&ac->dsp, out + 448 + 4*128, buf + 8*128, swindow, saved + 448 + 4*128, ac->revers + 3*128, ac->add_bias, 64);
> +#endif
> +
> + ac->dsp.vector_fmul_add_add(saved, buf + 1024 + 64, swindow + 64, ac->revers + 3*128+64, 0, 64, 1);
> + ac->dsp.vector_fmul_add_add(saved + 64, buf + 1024 + 2*128, swindow, ac->revers + 4*128, 0, 128, 1);
> + ac->dsp.vector_fmul_add_add(saved + 192, buf + 1024 + 4*128, swindow, ac->revers + 5*128, 0, 128, 1);
> + ac->dsp.vector_fmul_add_add(saved + 320, buf + 1024 + 6*128, swindow, ac->revers + 6*128, 0, 128, 1);
> + memcpy( saved + 448, ac->revers + 7*128, 128 * sizeof(float));
> + memset( saved + 576, 0, 448 * sizeof(float));
> + } else {
> + ff_imdct_calc(&ac->mdct, buf, in, out); // Out can be abused, for now, as a temp buffer.
> + if (ics->window_sequence[0] == LONG_STOP_SEQUENCE) {
> + for (i = 0; i < 448; i++) out[i] = saved[i] + ac->add_bias;
> + ac->dsp.vector_fmul_add_add(out + 448, buf + 448, swindow_prev, saved + 448, ac->add_bias, 128, 1);
> + for (i = 576; i < 1024; i++) out[i] = buf[i] + saved[i] + ac->add_bias;
> + } else {
> + ac->dsp.vector_fmul_add_add(out, buf, lwindow_prev, saved, ac->add_bias, 1024, 1);
> + }
> + if (ics->window_sequence[0] == LONG_START_SEQUENCE) {
> + memcpy(saved, buf + 1024, 448 * sizeof(float));
> + ac->dsp.vector_fmul_reverse(saved + 448, buf + 1024 + 448, swindow, 128);
> + memset(saved + 576, 0, 448 * sizeof(float));
> + } else {
> + ac->dsp.vector_fmul_reverse(saved, buf + 1024, lwindow, 1024);
> + }
> + }
> +}
> +
> /**
> * Apply dependent channel coupling (applied before IMDCT).
> *
ok
[...]
> +
> +/**
> + * Convert spectral data to float samples, applying all supported tools as appropriate.
> + */
> +static void spectral_to_sample(AACContext * ac) {
> + int i, type;
> + for (i = 0; i < MAX_ELEM_ID; i++) {
> + for(type = 0; type < 4; type++) {
> + ChannelElement *che = ac->che[type][i];
> + if(che) {
> + if(type == TYPE_CCE && che->coup.coupling_point == BEFORE_TNS)
> + apply_channel_coupling(ac, che, apply_dependent_coupling);
> + if(che->ch[0].tns.present)
> + 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);
> + if(type == TYPE_CCE && che->coup.coupling_point == BETWEEN_TNS_AND_IMDCT)
> + apply_channel_coupling(ac, che, apply_dependent_coupling);
> + imdct_and_windowing(ac, &che->ch[0]);
> + if(type == TYPE_CPE)
> + imdct_and_windowing(ac, &che->ch[1]);
> + if(type == TYPE_CCE && che->coup.coupling_point == AFTER_IMDCT)
> + apply_channel_coupling(ac, che, apply_independent_coupling);
the 3 TYPE_CCE checks are unneeded when coupling_point matches neiter of the 3
and maybe its possible to put the whole in a for(ch=0; ch<2; ch++) loop
this would need some chnages to apply_channel_coupling() though
iam not sure if this would end up cleaner or not, probably depends mostly on
apply_channel_coupling() being clean when its just doing one channel ...
> + }
> + }
> + }
> +}
> +
> +static int aac_decode_frame(AVCodecContext * avccontext, void * data, int * data_size, const uint8_t * buf, int buf_size) {
> + AACContext * ac = avccontext->priv_data;
> + GetBitContext gb;
> + enum RawDataBlockType elem_type;
> + int err, elem_id, data_size_tmp;
> +
> + init_get_bits(&gb, buf, buf_size*8);
> +
> + // parse
> + while ((elem_type = get_bits(&gb, 3)) != TYPE_END) {
> + elem_id = get_bits(&gb, 4);
> + err = -1;
> +
> + if(elem_type == TYPE_SCE && elem_id == 1 &&
> + !ac->che[TYPE_SCE][elem_id] && ac->che[TYPE_LFE][0]) {
> + /* Some streams incorrectly code 5.1 audio as SCE[0] CPE[0] CPE[1] SCE[1]
> + instead of SCE[0] CPE[0] CPE[0] LFE[0]. If we seem to have
> + encountered such a stream, transfer the LFE[0] element to SCE[1] */
> + ac->che[TYPE_SCE][elem_id] = ac->che[TYPE_LFE][0];
> + ac->che[TYPE_LFE][0] = NULL;
> + }
> + if(elem_type && elem_type < TYPE_DSE && !ac->che[elem_type][elem_id])
> + return -1;
> +
> + switch (elem_type) {
> +
> + case TYPE_SCE:
> + err = decode_ics(ac, &ac->che[TYPE_SCE][elem_id]->ch[0], &gb, 0, 0);
> + break;
> +
> + case TYPE_CPE:
> + err = decode_cpe(ac, &gb, elem_id);
> + break;
> +
> + case TYPE_CCE:
> + err = decode_cce(ac, &gb, elem_id);
> + break;
> +
> + case TYPE_LFE:
> + err = decode_ics(ac, &ac->che[TYPE_LFE][elem_id]->ch[0], &gb, 0, 0);
> + break;
> +
> + case TYPE_DSE:
> + skip_data_stream_element(&gb);
> + err = 0;
> + break;
> +
> + case TYPE_PCE:
> + {
> + enum ChannelPosition new_che_pos[4][MAX_ELEM_ID];
> + 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;
> + err = output_configure(ac, ac->che_pos, new_che_pos);
> + break;
> + }
> +
> + case TYPE_FIL:
> + if (elem_id == 15)
> + elem_id += get_bits(&gb, 8) - 1;
> + while (elem_id > 0)
> + elem_id -= decode_extension_payload(ac, &gb, elem_id);
> + err = 0; /* FIXME */
> + break;
> +
> + default:
> + err = -1; /* should not happen, but keeps compiler happy */
> + break;
> + }
> +
> + if(err)
> + return err;
> + }
> +
> + spectral_to_sample(ac);
> +
> if (!ac->is_saved) {
> ac->is_saved = 1;
> *data_size = 0;
ok
> Index: libavcodec/aac.h
> ===================================================================
> --- libavcodec/aac.h (revision 14694)
> +++ libavcodec/aac.h (working copy)
> @@ -45,6 +45,8 @@
> #define MAX_CHANNELS 64
> #define MAX_ELEM_ID 16
>
> +#define TNS_MAX_ORDER 20
> +#define PNS_MEAN_ENERGY 3719550720.0f // sqrt(3.0) * 1<<31
> #define IVQUANT_SIZE 1024
>
> enum AudioObjectType {
> @@ -135,8 +137,33 @@
> /**
> * Individual Channel Stream
> */
> +typedef struct {
> + int intensity_present;
Is this really needed? It does not seem so.
> + uint8_t max_sfb; ///< number of scalefactor bands per group
> + enum WindowSequence window_sequence[2];
> + uint8_t use_kb_window[2]; ///< If set, use Kaiser-Bessel window, otherwise use a sinus window.
> + int num_window_groups;
> + uint8_t group_len[8];
> + const uint16_t *swb_offset; ///< table of offsets to the lowest spectral coefficient of a scalefactor band, sfb, for a particular window
> + int num_swb; ///< number of scalefactor window bands
> + int num_windows;
> + int tns_max_bands;
> +} IndividualChannelStream;
>
[...]
> @@ -163,8 +190,43 @@
> * coupling parameters
> */
> typedef struct {
> + enum CouplingPoint coupling_point; ///< The point during decoding at which coupling is applied.
> + int num_coupled; ///< number of target elements
> + enum RawDataBlockType type[8]; ///< Type of channel element to be coupled - SCE or CPE.
> + int id_select[8]; ///< element id
> + int ch_select[8]; /**< [0] shared list of gains; [1] list of gains for left channel;
> + * [2] list of gains for right channel; [3] lists of gains for both channels
> + */
> + float gain[16][120];
> +} ChannelCoupling;
>
> /**
> + * Single Channel Element - used for both SCE and LFE elements.
> + */
> +typedef struct {
> + IndividualChannelStream ics;
> + TemporalNoiseShaping tns;
> + enum BandType band_type[120]; ///< band types
> + int band_type_run_end[120]; ///< band type run end points
> + float sf[120]; ///< scalefactors
> + DECLARE_ALIGNED_16(float, coeffs[1024]); ///< coefficients for IMDCT
> + DECLARE_ALIGNED_16(float, saved[1024]); ///< overlap
> + DECLARE_ALIGNED_16(float, ret[1024]); ///< PCM output
> +} SingleChannelElement;
> +
> +/**
> + * channel element - generic struct for SCE/CPE/CCE/LFE
> + */
> +typedef struct {
> + // CPE specific
> + uint8_t ms_mask[120]; ///< Set if mid/side stereo is used for each scalefactor window band
> + // shared
> + SingleChannelElement ch[2];
> + // CCE specific
> + ChannelCoupling coup;
> +} ChannelElement;
> +
> +/**
> * main AAC context
> */
> typedef struct {
ok
[...]
--
Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB
If a bugfix only changes things apparently unrelated to the bug with no
further explanation, that is a good sign that the bugfix is wrong.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080811/5eb85db4/attachment.pgp>
More information about the ffmpeg-devel
mailing list