[FFmpeg-devel] [PATCH 2/4] Add functions which are specific to E-AC-3 decoding.

Justin Ruggles justinruggles
Sun Jul 20 04:48:03 CEST 2008


Michael Niedermayer wrote:
> On Sat, Jul 19, 2008 at 07:50:26PM -0400, justin.ruggles at gmail.com wrote:
> [...]
 >>  ///@}
>>  
>>  ///@defgroup channel channel
>> @@ -172,4 +172,12 @@ typedef struct {
>>  ///@}
>>  } AC3DecodeContext;
>>  
>> +void ff_eac3_get_transform_coeffs_aht_ch(AC3DecodeContext *s, int ch);
>> +
>> +void ff_eac3_idct_transform_coeffs_ch(AC3DecodeContext *s, int ch, int blk);
>> +
>> +int ff_eac3_parse_header(AC3DecodeContext *s);
>> +
>> +void ff_eac3_tables_init(void);
> 
> As this adds functions seperate from their use. It would be nice to know why
> they are needed? (as i cannot check without looking at seperate patches what
> and where they are used an why they are non static ...)
> 
> Besides, idependant of that i think they should have some doxy comments

So I guess this is the same thing as below with splitting commits.  One
large commit plus one cosmetic commit would show the use of these.

And I'll add doxy comments.

> [...]
>> +static int gaq_ungroup_tab[32][3];
> 
> is the function to init this smaller than the table?
> is int needed or can a smaller data type be used?

int is not needed. I can't believe I missed that one. :)
As for the code size vs. table size, that I don't know.  With uint8_t,
the table size is 96 bytes.  If I move the table to ac3dec_data.c and
hardcode it, I can reuse it in the mantissa decoding, so I'm guessing it
would be smaller.

> 
>> +
>> +/** lrint(M_SQRT2*cos(2*M_PI/12)*(1<<23)) */
>> +#define COEFF_0 10273905
>> +
>> +/** lrint(M_SQRT2*cos(0*M_PI/12)*(1<<23)) = lrint(M_SQRT2*(1<<23)) */
>> +#define COEFF_1 11863283
>> +
>> +/** lrint(M_SQRT2*cos(5*M_PI/12)*(1<<23)) */
>> +#define COEFF_2  3070444
>> +
>> +/**
>> + * Calculate 6-point IDCT of the pre-mantissas.
>> + * All calculations are 24-bit fixed-point.
>> + */
>> +static void idct6(int pre_mant[6])
>> +{
>> +    int tmp;
> 
>> +    int even[3], odd[3];
> 
> I wouldnt use arrays for intermediate variables, i doubt the compiler
> is very good at putting their elements in registers

I tried both ways and it didn't affect speed on my machine.  I don't
have multiple machines to test with though.  I'll post some test results
of various changes so others can compare.

> 
> LL constants to avoid the casts
> 
> /** lrint(M_SQRT2*cos(2*M_PI/12)*(1<<23)) */
> #define COEFF_0 10273905LL
> 
> /** lrint(M_SQRT2*cos(0*M_PI/12)*(1<<23)) = lrint(M_SQRT2*(1<<23)) */
> #define COEFF_1 11863283LL
> 
> /** lrint(M_SQRT2*cos(5*M_PI/12)*(1<<23)) */
> #define COEFF_2  3070444LL

ok.

> 
> slightly reordered to avoid a few useless assignments
> 
> even[2] = (pre_mant[2] * COEFF_0) >> 23;
> tmp     = (pre_mant[4] * COEFF_1) >> 24;
> even[1] = pre_mant[0] - 2*tmp;
> tmp    += pre_mant[0];
> even[0] = tmp + even[2];
> even[2] = tmp - even[2];
> 
> 
> odd[1] =   pre_mant[1] - pre_mant[3] - pre_mant[5];
> tmp    = ((pre_mant[1]               + pre_mant[5]) * COEFF_2) >> 23;
> odd[0] = tmp + pre_mant[1] + pre_mant[3];
> odd[2] = tmp + pre_mant[5] - pre_mant[3];

I'll test it out.  When I tried rearranging things to simplify the code,
it affected the speed significantly.

> [...]
>> +        // TODO: modify AC3 demuxer to allow user to select which substream to decode
> 
> Iam not sure how to support substreams but that is likey not the ideal solution
> decoding all substreams and reencoding and storing them as seperates streams
> must be possible ...

It didn't sound quite right to me either.  I can't think of any other
good way within the current framework.  Would it be ok to just add a
comment that we're skipping additional substreams instead of a TODO?  I
havn't found any samples for this anyway...

> 
> [...]
>> +    s->block_switch_syntax = get_bits1(gbc);
>> +    if (!s->block_switch_syntax)
>> +        memset(s->block_switch, 0, sizeof(s->block_switch));
> 
> this flag does not seem used anywhere except here thus does not need to
> be in the context
> 
> 
>> +
>> +    s->dither_flag_syntax = get_bits1(gbc);
>> +    if (!s->dither_flag_syntax) {
> 
> same
> 
> 
>> +        s->dither_all = 1;
>> +        for(ch = 1; ch <= s->fbw_channels; ch++)
>> +            s->dither_flag[ch] = 1;
>> +    }
>> +    s->dither_flag[CPL_CH] = s->dither_flag[s->lfe_ch] = 0;
>> +
> 
>> +    s->bit_allocation_syntax = get_bits1(gbc);
>> +    if (!s->bit_allocation_syntax) {
> 
> and this as well
> 
> either this is very poorly written or VERY bad split in 2 patches.
> its hard to review code that is incomplete or unused.

All those *_syntax variables are used in the decoder from within
ac3dec.c.  If I combine the 2 patches, it will be pretty large, but if
that's preferable then I can do it.

Thanks,
Justin




More information about the ffmpeg-devel mailing list