[FFmpeg-devel] [PATCH] wmapro decoder

Sascha Sommer saschasommer
Sun Jun 21 14:18:42 CEST 2009


Hi Vitor,

thanks for your comments.

> > The code still outputs shorts. Float produced clicks all around the
> > place. I'm not sure yet if the problem is in my code or in ffmpeg.
>
> It looks like it works for me, see attached.

So your code does not produce clicks at second 16-18 for you with the sample 
file you mentioned below? It does for me when I'm using ffmpeg to produce a 
16-bit wav file and play that back with MPlayer.
Also the scaling can be done in the imdct.

>
> > Float output can also be added after the code has been added to svn imho.
> >
> > New patch attached.
> >
> >
> > +/**
> > + * @brief main decoder context
> > + */
>
> The @brief here makes the plain C code harder to read without improving
> a lot doxy output, so it is better to remove it (happens a lot elsewhere).
>

Do others agree?
I don't think it makes the code any harder to read.

> > +    /** generic decoder variables */
> > +    AVCodecContext*  avctx;                         ///< codec context
> > for av_log +    DSPContext       dsp;                           ///<
> > accelerated dsp functions +    uint8_t          frame_data[MAX_FRAMESIZE
> > +
> > +                      FF_INPUT_BUFFER_PADDING_SIZE];///< compressed
> > frame data +    MDCTContext      mdct_ctx[WMAPRO_BLOCK_SIZES];  ///< MDCT
> > context per block size +    DECLARE_ALIGNED_16(float,
> > tmp[WMAPRO_BLOCK_MAX_SIZE]); ///< imdct output buffer +    float*        
> >   windows[WMAPRO_BLOCK_SIZES];   ///< window per block size +    int     
> >         coef_max[2];                   ///< max length of vlc codes
>
> The "/** generic decoder variables */" will be misinterpreted by doxygen
> as been only referent to "AVCodecContext*  avctx;". There is a doxygen
> syntax for grouping.
>

Yes and the grouping syntax leads to the same problem. Looks like a doxygen 
problem. Any other ideas?

> > +    s->num_sfb = av_mallocz(sizeof(int8_t)*s->num_possible_block_sizes);
> > +    s->sfb_offsets = av_mallocz(MAX_BANDS *
> > +                                sizeof(int16_t) *
> > s->num_possible_block_sizes); +    s->subwoofer_cutoffs =
> > av_mallocz(sizeof(int16_t) *
> > +                                      s->num_possible_block_sizes);
> > +    s->sf_offsets = av_mallocz(MAX_BANDS * s->num_possible_block_sizes *
> > +                               s->num_possible_block_sizes *
> > sizeof(int16_t));
>
> There is no necessity of clearing s->num_sfb, it will be filled up in
> the next few lines (is clearing the others needed?), so you can use
> plain av_malloc().
>

I prefer to use av_mallocz on places where speed does not matter.

> > +/**
> > + *@brief Calculate a decorrelation matrix from the bitstream parameters.
> > + *@param s codec context
> > + *@param chgroup channel group for which the matrix needs to be
> > calculated + */
> > +static void decode_decorrelation_matrix(WMA3DecodeContext* s,
> > +                                            WMA3ChannelGroup* chgroup)
> > +{
> > +    int i;
> > +    int offset = 0;
> > +    char rotation_offset[WMAPRO_MAX_CHANNELS * WMAPRO_MAX_CHANNELS];
> > +    memset(chgroup->decorrelation_matrix,0,
> > +           sizeof(float) *s->num_channels * s->num_channels);
> > +
> > +    for (i=0;i<chgroup->num_channels  * (chgroup->num_channels - 1) >>
> > 1;i++) +        rotation_offset[i] = get_bits(&s->gb,6);
> > +
> > +    for (i=0;i<chgroup->num_channels;i++) {
> > +        if (get_bits1(&s->gb)) {
> > +            chgroup->decorrelation_matrix[chgroup->num_channels * i +
> > i]=  1.0; +        } else
> > +            chgroup->decorrelation_matrix[chgroup->num_channels * i +
> > i]= -1.0;
>
> chgroup->decorrelation_matrix[chgroup->num_channels * i + i] =
>                                        -1 + get_bits1(&s->gb)<<1;
>

That is slower.

> or
>
> chgroup->decorrelation_matrix[chgroup->num_channels * i + i] =
>
>                                     get_bits1(&s->gb) ? 1.0, -1.0;
>

Thanks. That seems to be slightly faster.

> > +                    if (s->num_channels == 2) {
> > +                        chgroup->transform = 1;
> > +                    } else {
> > +                        chgroup->transform = 2;
> > +                        /** cos(pi/4) */
> > +                        chgroup->decorrelation_matrix[0] = 0.70703125;
> > +                        chgroup->decorrelation_matrix[1] = -0.70703125;
> > +                        chgroup->decorrelation_matrix[2] = 0.70703125;
> > +                        chgroup->decorrelation_matrix[3] = 0.70703125;
>
> Already mentioned...
>

Yes. These values were used to produce binary identical output in the past. So 
I will keep using those value.

> > +
> > +    if (len <= 0 || buflen > MAX_FRAMESIZE) {
> > +         ff_log_ask_for_sample(s->avctx, "input buffer to small\n");
>
> s/to small/too small/
>

Fixed in the soc repository.

> Note also that the sample at
> http://samples.mplayerhq.hu/A-codecs/WMA9/wmapro/New%20Stories%20(Highway%2
>0Blues)-2.wma trigger this error.
>

Hm. Seems to be the same problem that I fixed in revision 4492 in the soc 
repository.

> > +    for (i=0;i<s->num_channels;i++) {
> > +        s->channel[i].decoded_samples = 0;
> > +        s->channel[i].cur_subframe = 0;
> > +        s->channel[i].reuse_sf = 0;
> > +    }
>
> memset(...)
>

Can't be used because some data like prev_block_len and the out buffer is not 
supposed to be resetted between the packets. They will be used for windowing.
 
Regards

Sascha




More information about the ffmpeg-devel mailing list