[FFmpeg-devel] [PATCH] wmapro decoder

Michael Niedermayer michaelni
Sun Aug 23 16:33:13 CEST 2009


On Fri, Aug 21, 2009 at 07:33:45PM +0200, Sascha Sommer wrote:
> Hi,
> 
> I attached an updated patch. As you might have already noticed, I do not have 
> much time to work on this project so please keep the focus on the important 
> things. I do not mind if Diego or someone else fixes the alignment, coding 
> style, typo and wording problems directly in the SVN sources or if these 
> things are pointed out in a single review but it is very frustrating to 
> resubmit this patch again and again and to synchonize the main and soc svn 
> for things that in the end do not give any real benefit. This is an 
> unacceptable waste of my time. Thanks.



[...]
> > > +        while (missing_samples > 0) {
> >
> > isnt that the same as a simple check on min_channel_len, which at the end
> > should be frame len?
> >
> 
> It is but I don't think the code will become cleaner when min_channel_len is 
> checked.

i think the whole tile code is messy and could be simplified, iam of course
not saying that above change would be a good idea but something should change
to make things simpler ...


> 
> > >
> > > +                if (channels_for_cur_subframe == 1 ||
> > > +                   min_samples == missing_samples)
> >
> > these 2 look redundant
> > also the condition for reading the mask could just be used instead of
> > the temporary var read_channel_mask
> 
> Did the second thing. Please explain why these 2 look redundant.
> 

i dont remember :(


[...]
> > > +                /** add subframes to the individual channels */
> > > +                if (min_channel_len == chan->channel_len) {
> > > +                    --channels_for_cur_subframe;
> > > +                    if (channel_mask & (1<<channels_for_cur_subframe)) {
> >
> > id do a get_bits1() here instead of loading it in a mask and then
> > extracting it
> > (btw you can just do GetBitContext mask_gb= *s->gb)
> 
> Then this would reintroduce the check for the case that the subframe is used 
> for all channels.

init_get_bits from a 0xFFFFFFFF, but its all of course just a suggestion if
it does improve code



[...]
> +/**
> + * @brief main decoder context
> + */
> +typedef struct WMA3DecodeContext {
> +    /* 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];   ///< windows for the different block sizes
> +

> +    /* frame size dependent frame information (set during initialization) */
> +    uint8_t          lossless;                      ///< lossless mode

never set or did i miss it?


> +    uint32_t         decode_flags;                  ///< used compression features
> +    uint8_t          len_prefix;                    ///< frame is prefixed with its length
> +    uint8_t          dynamic_range_compression;     ///< frame contains DRC data
> +    uint8_t          bits_per_sample;               ///< integer audio sample size for the unscaled IMDCT output (used to scale to [-1.0, 1.0])
> +    uint16_t         samples_per_frame;             ///< number of samples to output
> +    uint16_t         log2_frame_size;
> +    int8_t           num_channels;                  ///< number of channels in the stream (same as AVCodecContext.num_channels)
> +    int8_t           lfe_channel;                   ///< lfe channel index
> +    uint8_t          max_num_subframes;

> +    int8_t           num_possible_block_sizes;      ///< number of distinct block sizes that can be found in the file

i think the doxy is poor because it could also apply to 4 = [1,2,16,32]


[...]
> +
> +/**
> + *@brief Decode how the data in the frame is split into subframes.
> + *       Every WMA frame contains the encoded data for a fixed number of
> + *       samples per channel. The data for every channel might be split
> + *       into several subframes. This function will reconstruct the list of
> + *       subframes for every channel.
> + *
> + *       If the subframes are not evenly split, the algorithm estimates the
> + *       channels with the lowest number of total samples.
> + *       Afterwards, for each of these channels a bit is read from the
> + *       bitstream that indicates if the channel contains a subframe with the
> + *       next subframe size that is going to be read from the bitstream or not.
> + *       If a channel contains such a subframe, the subframe size gets added to
> + *       the channel's subframe list.
> + *       The algorithm repeats these steps until the frame is properly divided
> + *       between the individual channels.
> + *
> + *@param s context
> + *@return 0 on success, < 0 in case of an error
> + */
> +static int decode_tilehdr(WMA3DecodeContext *s)
> +{
> +    int c;
> +    uint16_t num_samples[WMAPRO_MAX_CHANNELS];
> +
> +    /* Should never consume more than 3073 bits (256 iterations for the
> +     * while loop when always the minimum amount of 128 samples is substracted
> +     * from missing samples in the 8 channel case).
> +     * 1 + BLOCK_MAX_SIZE * MAX_CHANNELS / BLOCK_MIN_SIZE * (MAX_CHANNELS  + 4)
> +     */
> +
> +    /** reset tiling information */
> +    for (c = 0; c < s->num_channels; c++)
> +        s->channel[c].num_subframes = 0;
> +
> +    memset(num_samples, 0, sizeof(num_samples));
> +
> +    /** handle the easy case with one constant-sized subframe per channel */
> +    if (s->max_num_subframes == 1) {
> +        for (c = 0; c < s->num_channels; c++) {
> +            s->channel[c].num_subframes = 1;
> +            s->channel[c].subframe_len[0] = s->samples_per_frame;
> +        }
> +    } else { /** subframe length and number of subframes is not constant */
> +        int missing_samples = s->num_channels * s->samples_per_frame;
> +        int subframe_len_bits = 0;     /** bits needed for the subframe length */
> +        int subframe_len_zero_bit = 0; /** first bit indicates if length is zero */
> +        int fixed_channel_layout;      /** all channels have the same subframe layout */
> +
> +        fixed_channel_layout = get_bits1(&s->gb);
> +

> +        /** calculate subframe len bits */
> +        if (s->lossless) {
> +            subframe_len_bits = av_log2(s->max_num_subframes - 1) + 1;
> +        } else {
> +            if (s->max_num_subframes == 16)
> +                subframe_len_zero_bit = 1;
> +            subframe_len_bits = av_log2(av_log2(s->max_num_subframes)) + 1;
> +        }

this maybe can be moved to decode_init()


> +
> +        /** loop until the frame data is split between the subframes */
> +        while (missing_samples > 0) {
> +            unsigned int channel_mask = 0;
> +            int min_channel_len;
> +            int channels_for_cur_subframe = 0;
> +            int subframe_len;
> +            /** minimum number of samples that need to be read */
> +            int min_samples = s->min_samples_per_subframe;
> +

> +            if (fixed_channel_layout) {
> +                channels_for_cur_subframe = s->num_channels;
> +                min_channel_len = num_samples[0];
> +            } else {
> +                min_channel_len = s->samples_per_frame;
> +                /** find channels with the smallest overall length */
> +                for (c = 0; c < s->num_channels; c++) {
> +                    if (num_samples[c] <= min_channel_len) {
> +                        if (num_samples[c] < min_channel_len) {
> +                            channels_for_cur_subframe = 0;
> +                            min_channel_len = num_samples[c];
> +                        }
> +                        ++channels_for_cur_subframe;
> +                    }
> +                }
> +            }

is the fixed_channel_layout special case needed?
also cant the initial min_channel_len be INT_MAX ?


> +            min_samples *= channels_for_cur_subframe;
> +
> +            /** For every channel with the minimum length, 1 bit
> +                might be transmitted that informs us if the channel
> +                contains a subframe with the next subframe_len. */
> +            if (fixed_channel_layout || channels_for_cur_subframe == 1 ||
> +                                             min_samples == missing_samples) {
> +                channel_mask = -1;
> +            } else {
> +                channel_mask = get_bits(&s->gb, channels_for_cur_subframe);
> +                if (!channel_mask) {
> +                    av_log(s->avctx, AV_LOG_ERROR,
> +                        "broken frame: zero frames for subframe_len\n");
> +                    return AVERROR_INVALIDDATA;
> +                }
> +            }
> +
> +            /** if we have the choice get next subframe length from the
> +                bitstream */
> +            if (min_samples != missing_samples) {

> +                int log2_subframe_len = 0;
> +                /* 1 bit indicates if the subframe is of maximum length */
> +                if (subframe_len_zero_bit) {
> +                    if (get_bits1(&s->gb)) {
> +                        log2_subframe_len = 1 +
> +                            get_bits(&s->gb, subframe_len_bits-1);
> +                    }
> +                } else
> +                    log2_subframe_len = get_bits(&s->gb, subframe_len_bits);

> +
> +                if (s->lossless) {
> +                    subframe_len =
> +                        s->samples_per_frame / s->max_num_subframes;
> +                    subframe_len *= log2_subframe_len + 1;
> +                } else {
> +                    subframe_len =
> +                        s->samples_per_frame / (1 << log2_subframe_len);
> +                }

one of these multiplies by log2_subframe_len the other divides, is that
intended?

[...]


> @@ -113,11 +627,11 @@
>      int i;
>      int offset = 0;
>      int8_t rotation_offset[WMAPRO_MAX_CHANNELS * WMAPRO_MAX_CHANNELS];
> -    memset(chgroup->decorrelation_matrix,0,
> +    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);
> +        rotation_offset[i] = get_bits(&s->gb, 6);
>  
>      for (i = 0; i < chgroup->num_channels; i++)
>          chgroup->decorrelation_matrix[chgroup->num_channels * i + i] =
> @@ -127,7 +641,7 @@
>          int x;
>          for (x = 0; x < i; x++) {
>              int y;
> -            for (y = 0; y < i + 1 ; y++) {
> +            for (y = 0; y < i + 1; y++) {
>                  float v1 = chgroup->decorrelation_matrix[x * chgroup->num_channels + y];
>                  float v2 = chgroup->decorrelation_matrix[i * chgroup->num_channels + y];
>                  int n = rotation_offset[offset + x];

ok and please just commit such changes



> @@ -153,42 +667,317 @@
>  }
>  
>  /**
> - *@brief Reconstruct the individual channel data.
> + *@brief Decode channel transformation parameters
>   *@param s codec context
> + *@return 0 in case of success, < 0 in case of bitstream errors
>   */
> -static void inverse_channel_transform(WMA3DecodeContext *s)
> +static int decode_channel_transform(WMA3DecodeContext* s)
>  {
>      int i;
> +    /* should never consume more than 1921 bits for the 8 channel case
> +     * 1 + MAX_CHANNELS * ( MAX_CHANNELS + 2 + 3 * MAX_CHANNELS * MAX_CHANNELS
> +     * + MAX_CHANNELS + MAX_BANDS + 1)
> +     */
>  
> -    for (i = 0; i < s->num_chgroups; i++) {
> +    /** in the one channel case channel transforms are pointless */
> +    s->num_chgroups = 0;
> +    if (s->num_channels > 1) {
> +        int remaining_channels = s->channels_for_cur_subframe;
>  
> -        if (s->chgroup[i].transform == 1) {
> -            /** M/S stereo decoding */
> -            int16_t* sfb_offsets = s->cur_sfb_offsets;
> -            float* ch0 = *sfb_offsets + s->channel[0].coeffs;
> -            float* ch1 = *sfb_offsets++ + s->channel[1].coeffs;
> -            const char* tb = s->chgroup[i].transform_band;
> -            const char* tb_end = tb + s->num_bands;
> +        if (get_bits1(&s->gb)) {
> +            av_log_ask_for_sample(s->avctx,
> +                "unsupported channel transform bit\n");
> +            return AVERROR_INVALIDDATA;
> +        }
>  
> -            while (tb < tb_end) {
> -                const float* ch0_end = s->channel[0].coeffs +
> -                                       FFMIN(*sfb_offsets,s->subframe_len);
> -                if (*tb++ == 1) {
> -                    while (ch0 < ch0_end) {
> -                        const float v1 = *ch0;
> -                        const float v2 = *ch1;
> -                        *ch0++ = v1 - v2;
> -                        *ch1++ = v1 + v2;
> +        for (s->num_chgroups = 0; remaining_channels &&
> +            s->num_chgroups < s->channels_for_cur_subframe; s->num_chgroups++) {
> +            WMA3ChannelGroup* chgroup = &s->chgroup[s->num_chgroups];
> +            float** channel_data = chgroup->channel_data;
> +            chgroup->num_channels = 0;
> +            chgroup->transform = 0;
> +
> +            /** decode channel mask */
> +            if (remaining_channels > 2) {
> +                for (i = 0; i < s->channels_for_cur_subframe; i++) {
> +                    int channel_idx = s->channel_indexes_for_cur_subframe[i];
> +                    if (!s->channel[channel_idx].grouped
> +                        && get_bits1(&s->gb)) {
> +                        ++chgroup->num_channels;
> +                        s->channel[channel_idx].grouped = 1;
> +                        *channel_data++ = s->channel[channel_idx].coeffs;
>                      }
> +                }
> +            } else {
> +                chgroup->num_channels = remaining_channels;
> +                for (i = 0; i < s->channels_for_cur_subframe; i++) {
> +                    int channel_idx = s->channel_indexes_for_cur_subframe[i];
> +                    if (!s->channel[channel_idx].grouped)
> +                        *channel_data++ = s->channel[channel_idx].coeffs;
> +                    s->channel[channel_idx].grouped = 1;
> +                }
> +            }
> +
> +            /** decode transform type */
> +            if (chgroup->num_channels == 2) {
> +                if (get_bits1(&s->gb)) {
> +                    if (get_bits1(&s->gb)) {
> +                        av_log_ask_for_sample(s->avctx,
> +                               "unsupported channel transform type\n");
> +                    }
>                  } else {
> -                    while (ch0 < ch0_end) {
> -                        *ch0++ *= 181.0 / 128;
> -                        *ch1++ *= 181.0 / 128;
> +                    chgroup->transform = 1;
> +                    if (s->num_channels == 2) {
> +                        chgroup->decorrelation_matrix[0] =  1.0;
> +                        chgroup->decorrelation_matrix[1] = -1.0;
> +                        chgroup->decorrelation_matrix[2] =  1.0;
> +                        chgroup->decorrelation_matrix[3] =  1.0;
> +                    } else {
> +                        /** 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;
>                      }
>                  }
> -                ++sfb_offsets;
> +            } else if (chgroup->num_channels > 2) {
> +                if (get_bits1(&s->gb)) {
> +                    chgroup->transform = 1;
> +                    if (get_bits1(&s->gb)) {
> +                        decode_decorrelation_matrix(s, chgroup);
> +                    } else {
> +                        /** FIXME: more than 6 coupled channels not supported */
> +                        if (chgroup->num_channels > 6) {
> +                            av_log_ask_for_sample(s->avctx,
> +                                   "coupled channels > 6\n");
> +                        } else {
> +                            memcpy(chgroup->decorrelation_matrix,
> +                              default_decorrelation[chgroup->num_channels],
> +                              sizeof(float) * chgroup->num_channels *
> +                              chgroup->num_channels);
> +                        }
> +                    }
> +                }
>              }
> -        } else if (s->chgroup[i].transform) {
> +
> +            /** decode transform on / off */
> +            if (chgroup->transform) {
> +                if (!get_bits1(&s->gb)) {
> +                    int i;
> +                    /** transform can be enabled for individual bands */
> +                    for (i = 0; i < s->num_bands; i++) {
> +                        chgroup->transform_band[i] = get_bits1(&s->gb);
> +                    }
> +                } else {
> +                    memset(chgroup->transform_band, 1, s->num_bands);
> +                }
> +            }
> +            remaining_channels -= chgroup->num_channels;
> +        }
> +    }
> +    return 0;
> +}

whatever happened here its not revieable


> +
> +/**
> + *@brief Extract the coefficients from the bitstream.
> + *@param s codec context
> + *@param c current channel number
> + *@return 0 on success, < 0 in case of bitstream errors
> + */
> +static int decode_coeffs(WMA3DecodeContext *s, int c)
> +{
> +    int vlctable;
> +    VLC* vlc;
> +    WMA3ChannelCtx* ci = &s->channel[c];
> +    int rl_mode = 0;
> +    int cur_coeff = 0;
> +    int num_zeros = 0;
> +    const uint16_t* run;
> +    const uint16_t* level;
> +
> +    dprintf(s->avctx, "decode coefficients for channel %i\n", c);
> +
> +    vlctable = get_bits1(&s->gb);
> +    vlc = &coef_vlc[vlctable];
> +
> +    if (vlctable) {
> +        run = coef1_run;
> +        level = coef1_level;
> +    } else {
> +        run = coef0_run;
> +        level = coef0_level;
> +    }
> +
> +    /** decode vector coefficients (consumes up to 167 bits per iteration for
> +      4 vector coded large values) */
> +    while (!rl_mode && cur_coeff + 3 < s->subframe_len) {
> +        int vals[4];
> +        int i;
> +        unsigned int idx;
> +
> +        idx = get_vlc2(&s->gb, vec4_vlc.table, VLCBITS, VEC4MAXDEPTH);
> +
> +        if ( idx == HUFF_VEC4_SIZE - 1 ) {
> +            for (i = 0 ; i < 4 ; i += 2) {
> +                idx = get_vlc2(&s->gb, vec2_vlc.table, VLCBITS, VEC2MAXDEPTH);
> +                if ( idx == HUFF_VEC2_SIZE - 1 ) {
> +                    vals[i] = get_vlc2(&s->gb, vec1_vlc.table, VLCBITS, VEC1MAXDEPTH);
> +                    if (vals[i] == HUFF_VEC1_SIZE - 1)
> +                        vals[i] += ff_wma_get_large_val(&s->gb);
> +                    vals[i+1] = get_vlc2(&s->gb, vec1_vlc.table, VLCBITS, VEC1MAXDEPTH);
> +                    if (vals[i+1] == HUFF_VEC1_SIZE - 1)
> +                        vals[i+1] += ff_wma_get_large_val(&s->gb);
> +                } else {
> +                    vals[i]   = symbol_to_vec2[idx] >> 4;
> +                    vals[i+1] = symbol_to_vec2[idx] & 0xF;
> +                }
> +            }
> +        } else {
> +             vals[0] =  symbol_to_vec4[idx] >> 12;
> +             vals[1] = (symbol_to_vec4[idx] >> 8) & 0xF;
> +             vals[2] = (symbol_to_vec4[idx] >> 4) & 0xF;
> +             vals[3] =  symbol_to_vec4[idx]       & 0xF;
> +        }
> +
> +        /** decode sign */
> +        for (i = 0; i < 4; i++) {
> +            if (vals[i]) {
> +                int sign = get_bits1(&s->gb) - 1;
> +                ci->coeffs[cur_coeff] = (vals[i]^sign) - sign;
> +                num_zeros = 0;
> +            } else {
> +                /** switch to run level mode when subframe_len / 128 zeros
> +                   were found in a row */
> +                rl_mode |= (++num_zeros > s->subframe_len>>8);
> +            }
> +            ++cur_coeff;
> +        }
> +    }
> +
> +    /** decode run level coded coefficients */
> +    if (rl_mode) {
> +        if(ff_wma_run_level_decode(s->avctx, &s->gb, vlc,
> +                             level, run, 1, ci->coeffs,
> +                             cur_coeff, s->subframe_len, s->subframe_len,
> +                             s->esc_len, 0))
> +            return AVERROR_INVALIDDATA;
> +    }
> +
> +    return 0;
> +}
> +

ok


> +/**
> + *@brief Extract scale factors from the bitstream.
> + *@param s codec context
> + *@return 0 on success, < 0 in case of bitstream errors
> + */
> +static int decode_scale_factors(WMA3DecodeContext* s)
> +{
> +    int i;
> +
> +    /** should never consume more than 5344 bits
> +     *  MAX_CHANNELS * (1 +  MAX_BANDS * 23)
> +     */
> +
> +    for (i = 0; i < s->channels_for_cur_subframe; i++) {
> +        int c = s->channel_indexes_for_cur_subframe[i];
> +        int* sf;
> +        int* sf_end = s->channel[c].scale_factors + s->num_bands;
> +
> +        /** resample scale factors for the new block size */
> +        if (s->channel[c].reuse_sf) {
> +            const int blocks_per_frame = s->samples_per_frame/s->subframe_len;
> +            const int res_blocks_per_frame = s->samples_per_frame /
> +                                          s->channel[c].scale_factor_block_len;

> +            const int idx0 = av_log2(blocks_per_frame);
> +            const int idx1 = av_log2(res_blocks_per_frame);

i assume these are exact 2^x values in which case maybe storing them as
log2 values might be simpler?


> +            const int8_t* sf_offsets = s->sf_offsets[idx0][idx1];
> +            int b;
> +            for (b = 0; b < s->num_bands; b++)
> +                s->channel[c].scale_factors[b] =
> +                                   s->channel[c].saved_scale_factors[*sf_offsets++];
> +        }
> +

> +        if (s->channel[c].cur_subframe > 0) {
> +            s->channel[c].transmit_sf = get_bits1(&s->gb);
> +        } else
> +            s->channel[c].transmit_sf = 1;
> +
> +        if (s->channel[c].transmit_sf) {

can transmit_sf be a local var here? theres no other use in this patch


> +
> +            if (!s->channel[c].reuse_sf) {
> +                int val;
> +                /** decode DPCM coded scale factors */
> +                s->channel[c].scale_factor_step = get_bits(&s->gb, 2) + 1;
> +                val = 45 / s->channel[c].scale_factor_step;
> +                for (sf = s->channel[c].scale_factors; sf < sf_end; sf++) {
> +                    val += get_vlc2(&s->gb, sf_vlc.table, SCALEVLCBITS, SCALEMAXDEPTH) - 60;
> +                    *sf = val;
> +                }
> +            } else {
> +                int i;
> +                /** run level decode differences to the resampled factors */
> +                for (i = 0; i < s->num_bands; i++) {
> +                    int idx;
> +                    int skip;
> +                    int val;
> +                    int sign;
> +
> +                    idx = get_vlc2(&s->gb, sf_rl_vlc.table, VLCBITS, SCALERLMAXDEPTH);
> +
> +                    if ( !idx ) {
> +                        uint32_t code = get_bits(&s->gb, 14);
> +                        val  =  code >> 6;
> +                        sign = (code & 1) - 1;
> +                        skip = (code & 0x3f) >> 1;
> +                    } else if (idx == 1) {
> +                        break;
> +                    } else {
> +                        skip = scale_rl_run[idx];
> +                        val  = scale_rl_level[idx];
> +                        sign = get_bits1(&s->gb)-1;
> +                    }
> +
> +                    i += skip;
> +                    if (i >= s->num_bands) {
> +                        av_log(s->avctx,AV_LOG_ERROR,
> +                               "invalid scale factor coding\n");
> +                        return AVERROR_INVALIDDATA;
> +                    }
> +                    s->channel[c].scale_factors[i] += (val ^ sign) - sign;
> +                }
> +            }
> +

> +            /** save transmitted scale factors so that they can be reused for
> +                the next subframe */
> +            memcpy(s->channel[c].saved_scale_factors,
> +                   s->channel[c].scale_factors,
> +                   sizeof(int) * s->num_bands);

sizeof(*s->channel[c].saved_scale_factors)


> +            s->channel[c].scale_factor_block_len = s->subframe_len;
> +            s->channel[c].reuse_sf               = 1;
> +        }
> +
> +        /** calculate new scale factor maximum */
> +        s->channel[c].max_scale_factor = s->channel[c].scale_factors[0];
> +        for (sf = s->channel[c].scale_factors + 1; sf < sf_end; sf++) {

> +            if (s->channel[c].max_scale_factor < *sf)
> +                s->channel[c].max_scale_factor = *sf;

FFMAX


[...]
> @@ -199,8 +988,8 @@
>              /** multichannel decorrelation */
>              for (sfb = s->cur_sfb_offsets ;
>                  sfb < s->cur_sfb_offsets + s->num_bands;sfb++) {
> +                int y;
>                  if (*tb++ == 1) {
> -                    int y;
>                      /** multiply values with the decorrelation_matrix */
>                      for (y = sfb[0]; y < FFMIN(sfb[1], s->subframe_len); y++) {
>                          const float* mat = s->chgroup[i].decorrelation_matrix;
> @@ -208,7 +997,7 @@
>                          float* data_ptr = data;
>                          float** ch;
>  
> -                        for (ch = ch_data;ch < ch_end; ch++)
> +                        for (ch = ch_data; ch < ch_end; ch++)
>                             *data_ptr++ = (*ch)[y];
>  
>                          for (ch = ch_data; ch < ch_end; ch++) {
> @@ -220,9 +1009,593 @@
>                              (*ch)[y] = sum;
>                          }
>                      }
> +                } else if (s->num_channels == 2) {
> +                    for (y = sfb[0]; y < FFMIN(sfb[1], s->subframe_len); y++) {
> +                        ch_data[0][y] *= 181.0 / 128;
> +                        ch_data[1][y] *= 181.0 / 128;
> +                    }
>                  }
>              }
>          }
>      }
>  }

ok

[...]
> +        memset(s->channel[c].coeffs, 0, sizeof(float) * subframe_len);

sizeof(*s->channel[c].coeffs)

[...]
> +/**
> + *@brief Decode one WMA frame.
> + *@param s codec context
> + *@return 0 if the trailer bit indicates that this is the last frame,
> + *        1 if there are additional frames
> + */
> +static int decode_frame(WMA3DecodeContext *s)
> +{
> +    GetBitContext* gb = &s->gb;
> +    int more_frames = 0;
> +    int len = 0;
> +    int i;
> +
> +    /** check for potential output buffer overflow */
> +    if (s->samples + s->num_channels * s->samples_per_frame > s->samples_end) {

can overflow
s->samples_end - s->samples < ...
should be better


> +        av_log(s->avctx,AV_LOG_ERROR,
> +               "not enough space for the output samples\n");
> +        s->packet_loss = 1;
> +        return 0;
> +    }
> +
> +    /** get frame length */
> +    if (s->len_prefix)
> +        len = get_bits(gb, s->log2_frame_size);
> +
> +    dprintf(s->avctx, "decoding frame with length %x\n", len);
> +
> +    /** decode tile information */
> +    if (decode_tilehdr(s)) {
> +        s->packet_loss = 1;
> +        return 0;
> +    }
> +
> +    /** read postproc transform */
> +    if (s->num_channels > 1 && get_bits1(gb)) {
> +        av_log_ask_for_sample(s->avctx, "Unsupported postproc transform found\n");
> +        s->packet_loss = 1;
> +        return 0;
> +    }
> +
> +    /** read drc info */
> +    if (s->dynamic_range_compression) {
> +        s->drc_gain = get_bits(gb, 8);
> +        dprintf(s->avctx, "drc_gain %i\n", s->drc_gain);
> +    }
> +
> +    /** no idea what these are for, might be the number of samples
> +        that need to be skipped at the beginning or end of a stream */
> +    if (get_bits1(gb)) {
> +        int skip;
> +
> +        /** usually true for the first frame */
> +        if (get_bits1(gb)) {
> +            skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
> +            dprintf(s->avctx, "start skip: %i\n", skip);
> +        }
> +
> +        /** sometimes true for the last frame */
> +        if (get_bits1(gb)) {
> +            skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
> +            dprintf(s->avctx, "end skip: %i\n", skip);
> +        }
> +
> +    }
> +
> +    dprintf(s->avctx, "BITSTREAM: frame header length was %i\n",
> +           get_bits_count(gb) - s->frame_offset);
> +
> +    /** reset subframe states */
> +    s->parsed_all_subframes = 0;
> +    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;
> +    }
> +

> +    /** decode all subframes */
> +    while (!s->parsed_all_subframes) {
> +        if (decode_subframe(s) < 0) {
> +            s->packet_loss = 1;
> +            return 0;
> +        }
> +    }

are all the previous frames to a failed frames used or droped?
i think droping all might not be wise but maybe the last few should
be droped (depends on which works best)


> +
> +    /** interleave samples and write them to the output buffer */
> +    for (i = 0; i < s->num_channels; i++) {
> +        float* ptr;
> +        int incr = s->num_channels;
> +        float* iptr = s->channel[i].out;
> +        int x;
> +
> +        ptr = s->samples + i;
> +
> +        for (x = 0; x < s->samples_per_frame; x++) {
> +            *ptr = av_clipf(*iptr++, -1.0, 32767.0 / 32768.0);
> +            ptr += incr;
> +        }
> +

> +        /** reuse second half of the IMDCT output for the next frame */
> +        memmove(&s->channel[i].out[0],
> +                &s->channel[i].out[s->samples_per_frame],
> +                s->samples_per_frame * sizeof(float));

doesnt look like it needs a move besides are you sure that cannot be avoided?

[...]
> +/**
> + *@brief Fill the bit reservoir with a (partial) frame.
> + *@param s codec context
> + *@param gb bitstream reader context
> + *@param len length of the partial frame
> + *@param append decides wether to reset the buffer or not
> + */
> +static void save_bits(WMA3DecodeContext *s, GetBitContext* gb, int len,
> +                          int append)
> +{
> +    int buflen;
> +    int bit_offset;
> +    int pos;
> +
> +    if (!append) {
> +        s->frame_offset = get_bits_count(gb) & 7;
> +        s->num_saved_bits = s->frame_offset;
> +    }
> +
> +    buflen = (s->num_saved_bits + len + 8) >> 3;
> +
> +    if (len <= 0 || buflen > MAX_FRAMESIZE) {
> +         av_log_ask_for_sample(s->avctx, "input buffer too small\n");
> +         s->packet_loss = 1;
> +         return;
> +    }
> +
> +    if (!append) {
> +        s->num_saved_bits += len;
> +        memcpy(s->frame_data, gb->buffer + (get_bits_count(gb) >> 3),
> +              (s->num_saved_bits  + 8)>> 3);
> +        skip_bits_long(gb, len);
> +    } else {
> +        bit_offset = s->num_saved_bits & 7;
> +        pos = (s->num_saved_bits - bit_offset) >> 3;
> +
> +        s->num_saved_bits += len;
> +
> +        /** byte align prev_frame buffer */
> +        if (bit_offset) {
> +            int missing = 8 - bit_offset;
> +            missing = FFMIN(len, missing);
> +            s->frame_data[pos++] |=
> +                get_bits(gb, missing) << (8 - bit_offset - missing);
> +            len -= missing;
> +        }
> +
> +        /** copy full bytes */
> +        while (len > 7) {
> +            s->frame_data[pos++] = get_bits(gb, 8);
> +            len -= 8;
> +        }
> +
> +        /** copy remaining bits */
> +        if (len > 0)
> +            s->frame_data[pos++] = get_bits(gb, len) << (8 - len);
> +
> +    }
> +
> +    init_get_bits(&s->gb, s->frame_data, s->num_saved_bits);
> +    skip_bits(&s->gb, s->frame_offset);

ff_copy_bits()
also you could keep a PutBitContext instead of dealing with remaining %8
bits
and maybe some frames can be decoded without copying them

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Complexity theory is the science of finding the exact solution to an
approximation. Benchmarking OTOH is finding an approximation of the exact
-------------- 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/20090823/1fd4f93c/attachment.pgp>



More information about the ffmpeg-devel mailing list