[FFmpeg-devel] [PATCH] AAC Decoder round 3

Robert Swain robert.swain
Mon Jul 7 03:50:36 CEST 2008


2008/7/6 Michael Niedermayer <michaelni at gmx.at>:
> On Tue, Jul 01, 2008 at 12:37:11PM +0100, Robert Swain wrote:
> [...]
>> +/**
>> + * Free a channel element.
>> + */
>> +static void che_freep(ChannelElement **s) {
>> +    if(!*s)
>> +        return;
>> +    av_freep(s);
>> +}
>
> am i too tired or is the if-return useless and this a senseless wraper
> function?

I'll remove it for the next submission but it's needed for SSR/LTP in
SoC so I won't remove it there.

> [...]
>> +/**
>> + * Decode section_data payload; reference: table 4.46.
>> + */
>> +static int decode_section_data(AACContext * ac, GetBitContext * gb, IndividualChannelStream * ics, int cb[][64], int cb_run_end[][64]) {
>> +    int g;
>> +    for (g = 0; g < ics->num_window_groups; g++) {
>> +        int bits = (ics->window_sequence == EIGHT_SHORT_SEQUENCE) ? 3 : 5;
>> +        int k = 0;
>> +        while (k < ics->max_sfb) {
>> +            int sect_len = k;
>> +            int sect_len_incr;
>> +            int sect_cb = get_bits(gb, 4);
>> +            if (sect_cb == 12) {
>> +                av_log(ac->avccontext, AV_LOG_ERROR, "invalid codebook\n");
>> +                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) {
>
> change the check to unsigned or check for < 0 please, it doesnt seeem to
> do any harm but <0 is not correct

Made sect_len and max_sfb uint8_t as they should be.

> [...]
>> +/**
>> + * Decode scale_factor_data; reference: table 4.47.
>> + */
>> +static int decode_scale_factor_data(AACContext * ac, GetBitContext * gb, float mix_gain, unsigned int global_gain, IndividualChannelStream * ics, const int cb[][64], const int cb_run_end[][64], float sf[][64]) {
>> +    const int sf_offset = ac->sf_offset + (ics->window_sequence == EIGHT_SHORT_SEQUENCE ? 12 : 0);
>> +    int g, i;
>> +    int offset[3] = { global_gain, global_gain - 90, 100 };
>> +    int noise_flag = 1;
>> +    static const char *sf_str[3] = { "Global gain", "Noise gain", "Intensity stereo position" };
>> +    ics->intensity_present = 0;
>> +    for (g = 0; g < ics->num_window_groups; g++) {
>> +        for (i = 0; i < ics->max_sfb;) {
>> +            if (cb[g][i] == ZERO_HCB) {
>> +                int run_end = cb_run_end[g][i];
>> +                for(; i < run_end; i++)
>> +                    sf[g][i] = 0.;
>> +                continue;
>
> useless continue and this could use a memset(0)

I didn't use memset because the runs are usually small (<10) and I
thought using memset in such cases may be slower than just assigning
the values. I can change it to memset if you wish though.

> [...]
>> +static void coupling_tool(AACContext * ac, int independent, int domain) {
>
> This as well as other functions could benefit from some documentation
> what does it do, what is "independent" what "domain" ?

independent == 0 : dependent channel coupling
independent == 1 : independent channel coupling

The dependence of the channel coupling has implications on the data
that is shared between the coupled channels and how the data is
processed.

domain == 0 : apply coupling before TNS decoding
domain == 1 : apply coupling after TNS decoding

This variable is called cc_domain in the spec.

If you're not happy with the names, please make suggestions based on
the descriptions. I have added the documentation of these particular
ones and I'm looking at other non-obvious function names and adding
doxygen comments.

>> +    int i;
>> +    for (i = 0; i < MAX_TAGID; i++) {
>> +        ChannelElement * cc = ac->che[ID_CCE][i];
>> +        if (cc) {
>> +            if (cc->coup.ind_sw && independent) {
>> +                transform_coupling_tool(ac, cc, coupling_independent_trans);
>> +            } else if (!cc->coup.ind_sw && !independent && (cc->coup.domain == domain)) {
>> +                transform_coupling_tool(ac, cc, coupling_dependent_trans);
>> +            }
>> +        }
>> +    }
>> +}
>> +
>
>> +static void transform_sce_tool(AACContext * ac, void (*sce_trans)(AACContext * ac, SingleChannelElement * sce)) {
>
> iam still not happy with _tool() functions. Functions should be named
> so that the names describes what the function does.

They're called tools in the spec. Looking up blah_tool shouldn't be
too difficult, but I agree it would be better if one didn't have to
look up the meaning of a function name. I'll see what I can do about
this tomorrow.

> [...]
>> +static void spec_to_sample(AACContext * ac) {
>
> what is "spec to sample" ? the name does not say anythig to me

A function that converts spectral data to time domain sample data?
I'll annotate it as I will do for other functions.

> [...]
>
>> +    i = 1024 * avccontext->channels * sizeof(uint16_t);
>> +    if(*data_size < i)
>> +        return -1;
>
> i wonder if this shouldnt be checked earlier (closer to where the number of
> channels is set)

data_size is only known in aac_decode_frame() and avctx->channels is
known at the end of output_configure() which is called at the end of
program_config_element() and program_config_element_default().

The latter is called during aac_decode_init() and imposes the default
channel mapping. A stream doesn't have to have a program config
element to reconfigure the channel mappings from the default (which is
the whole point of having default mappings I guess).

We have to be certain of the number of channels before we can do this check.

The spec says that a program config element must come before all other
syntactic elements in the while() loop in aac_decode_frame(). So, I
can add a flag var which can be toggled after the first syntactic
element has been decoded and check data_size then or I can add the
check just after the while() loop or maybe you have another
suggestion?

Regards,
Rob




More information about the ffmpeg-devel mailing list