[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