[FFmpeg-devel] [PATCH] wmapro decoder

Michael Niedermayer michaelni
Tue Jul 14 03:44:32 CEST 2009


On Sat, Jul 04, 2009 at 05:10:52PM +0200, Sascha Sommer wrote:
[...]
> +/**
> + * @file  libavcodec/wmaprodec.c
> + * @brief wmapro decoder implementation
> + * Wmapro is an MDCT based codec comparable to wma standard or AAC.
> + * The decoding therefore consist of the following steps:
> + * - bitstream decoding
> + * - reconstruction of per channel data
> + * - rescaling and inverse quantization
> + * - IMDCT
> + * - windowing and overlapp-add
> + *

> + * The compressed wmapro bitstream is split into individual packets.
> + * Every such packet contains one or more wma frames.
> + * The compressed frames may have a variable length and frames may
> + * cross packet boundaries.
> + * Common to all wmapro frames is the number of samples that are stored in
> + * a frame.
> + * The number of samples and a few other decode flags are stored
> + * as extradata that has to be passed to the decoder.
> + *
> + * The wmapro frames themselves are again split into a variable number of
> + * subframes. Every subframe contains the data for 2^N time domain samples
> + * where N varies between 7 and 12.
> + *
> + * The frame layouts for the individual channels of a wma frame does not need
> + * to be the same.

maybe you want to draw some simple ascii art to show these things ...


[...]
> +/**
> + * @brief decoder context for a single channel
> + */
> +typedef struct {
> +    int16_t  prev_block_len;                          ///< length of the previous block
> +    uint8_t  transmit_coefs;
> +    uint8_t  num_subframes;
> +    uint16_t subframe_len[MAX_SUBFRAMES];             ///< subframe length in samples

> +    uint16_t subframe_offset[MAX_SUBFRAMES];          ///< subframe position

a little unclear, position in the stream vs. frame


> +    uint8_t  cur_subframe;                            ///< subframe index

same and it applies to more fields as well i think


> +    uint16_t channel_len;                             ///< channel length in samples
> +    uint16_t decoded_samples;                         ///< already processed samples
> +    uint8_t  grouped;                                 ///< channel is part of a group
> +    int      quant_step;                              ///< quantization step
> +    int8_t   transmit_sf;                             ///< transmit scale factors
> +    int8_t   reuse_sf;                                ///< share scale factors between subframes
> +    int8_t   scale_factor_step;                       ///< scaling step

> +    int      max_scale_factor;                        ///< maximum scale factor
> +    int      scale_factors[MAX_BANDS];                ///< scale factor values

doxy seem redundant, they just repeat the var names ...


> +    int      resampled_scale_factors[MAX_BANDS];      ///< scale factors from a previous block
> +    int16_t  scale_factor_block_len;                  ///< scale factor reference block length
> +    float*   coeffs;                                  ///< pointer to the decode buffer
> +    DECLARE_ALIGNED_16(float, out[2*WMAPRO_BLOCK_MAX_SIZE]); ///< output buffer
> +} WMA3ChannelCtx;
> +
> +/**
> + * @brief channel group for channel transformations
> + */
> +typedef struct {
> +    uint8_t num_channels;                                     ///< number of channels in the group
> +    int8_t  transform;                                        ///< controls the type of the transform
> +    int8_t  transform_band[MAX_BANDS];                        ///< controls if the transform is enabled for a certain band

> +    float   decorrelation_matrix[WMAPRO_MAX_CHANNELS*WMAPRO_MAX_CHANNELS];

is it simpler if its [WMAPRO_MAX_CHANNELS][WMAPRO_MAX_CHANNELS] ?


[...]

> +/**
> + *@brief helper function to print the most important members of the context
> + *@param s context
> + */
> +static void av_cold dump_context(WMA3DecodeContext *s)
> +{

> +#define PRINT(a,b) av_log(s->avctx,AV_LOG_DEBUG," %s = %d\n", a, b);
> +#define PRINT_HEX(a,b) av_log(s->avctx,AV_LOG_DEBUG," %s = %x\n", a, b);

vertical align


> +
> +    PRINT("ed sample bit depth",s->bits_per_sample);
> +    PRINT_HEX("ed decode flags",s->decode_flags);
> +    PRINT("samples per frame",s->samples_per_frame);
> +    PRINT("log2 frame size",s->log2_frame_size);
> +    PRINT("max num subframes",s->max_num_subframes);
> +    PRINT("len prefix",s->len_prefix);
> +    PRINT("num channels",s->num_channels);
> +    PRINT("lossless",s->lossless);
> +}
> +

> +/**
> + *@brief Uninitialize the decoder and free all resources.
> + *@param avctx codec context
> + *@return 0 on success, < 0 otherwise
> + */
> +static av_cold int decode_end(AVCodecContext *avctx)
> +{
> +    WMA3DecodeContext *s = avctx->priv_data;
> +    int i;
> +
> +    av_freep(&s->num_sfb);
> +    av_freep(&s->sfb_offsets);
> +    av_freep(&s->subwoofer_cutoffs);
> +    av_freep(&s->sf_offsets);
> +
> +    for (i=0 ; i<WMAPRO_BLOCK_SIZES ; i++)
> +        ff_mdct_end(&s->mdct_ctx[i]);
> +
> +    return 0;
> +}

function ok, can be commited if you like


> +
> +/**
> + *@brief Initialize the decoder.
> + *@param avctx codec context
> + *@return 0 on success, -1 otherwise
> + */
> +static av_cold int decode_init(AVCodecContext *avctx)
> +{
> +    WMA3DecodeContext *s = avctx->priv_data;
> +    uint8_t *edata_ptr = avctx->extradata;
> +    int16_t* sfb_offsets;
> +    unsigned int channel_mask;
> +    int i;
> +    int log2_num_subframes;
> +
> +    s->avctx = avctx;
> +    dsputil_init(&s->dsp, avctx);
> +
> +    avctx->sample_fmt = SAMPLE_FMT_FLT;
> +
> +    if (avctx->extradata_size >= 18) {

> +        s->decode_flags     = AV_RL16(edata_ptr+14);
> +        channel_mask    = AV_RL32(edata_ptr+2);
> +        s->bits_per_sample = AV_RL16(edata_ptr);

vertical align


> +#ifdef DEBUG
> +        /** dump the extradata */
> +        for (i=0 ; i<avctx->extradata_size ; i++)
> +            av_log(avctx, AV_LOG_DEBUG, "[%x] ",avctx->extradata[i]);
> +        av_log(avctx, AV_LOG_DEBUG, "\n");
> +#endif
> +
> +    } else {
> +        av_log_ask_for_sample(avctx, "Unknown extradata size\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    /** generic init */
> +    s->log2_frame_size = av_log2(avctx->block_align) + 4;
> +
> +    /** frame info */
> +    s->skip_frame = 1; /** skip first frame */
> +    s->packet_loss = 1;

> +    s->len_prefix = (s->decode_flags & 0x40) >> 6;

the >> is uneeded


> +
> +    if (!s->len_prefix) {
> +         av_log_ask_for_sample(avctx, "no length prefix\n");
> +         return AVERROR_INVALIDDATA;
> +    }
> +
> +    /** get frame len */
> +    s->samples_per_frame = 1 << ff_wma_get_frame_len_bits(avctx->sample_rate,
> +                                                          3, s->decode_flags);
> +
> +    /** init previous block len */
> +    for (i=0;i<avctx->channels;i++)
> +        s->channel[i].prev_block_len = s->samples_per_frame;
> +
> +    /** subframe info */
> +    log2_num_subframes = ((s->decode_flags & 0x38) >> 3);
> +    s->max_num_subframes = 1 << log2_num_subframes;
> +    s->num_possible_block_sizes = log2_num_subframes + 1;
> +    s->min_samples_per_subframe = s->samples_per_frame / s->max_num_subframes;
> +    s->dynamic_range_compression = (s->decode_flags & 0x80);

these assignments also could be aligned so that = is at the same pos, i
think this would be more readable ....


> +
> +    if (s->max_num_subframes > MAX_SUBFRAMES) {
> +        av_log(avctx, AV_LOG_ERROR, "invalid number of subframes %i\n",
> +                      s->max_num_subframes);
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    s->num_channels = avctx->channels;
> +
> +    /** extract lfe channel position */
> +    s->lfe_channel = -1;
> +
> +    if (channel_mask & 8) {
> +        unsigned int mask;
> +        for (mask=1;mask < 16;mask <<= 1) {
> +            if (channel_mask & mask)
> +                ++s->lfe_channel;
> +        }
> +    }
> +
> +    if (s->num_channels < 0 || s->num_channels > WMAPRO_MAX_CHANNELS) {
> +        av_log_ask_for_sample(avctx, "invalid number of channels\n");
> +        return AVERROR_NOTSUPP;
> +    }
> +
> +    INIT_VLC_STATIC(&sf_vlc, SCALEVLCBITS, HUFF_SCALE_SIZE,
> +                 scale_huffbits, 1, 1,
> +                 scale_huffcodes, 2, 2, 616);
> +
> +    INIT_VLC_STATIC(&sf_rl_vlc, VLCBITS, HUFF_SCALE_RL_SIZE,
> +                 scale_rl_huffbits, 1, 1,
> +                 scale_rl_huffcodes, 4, 4, 1406);
> +
> +    INIT_VLC_STATIC(&coef_vlc[0], VLCBITS, HUFF_COEF0_SIZE,
> +                 coef0_huffbits, 1, 1,
> +                 coef0_huffcodes, 4, 4, 2108);
> +
> +    INIT_VLC_STATIC(&coef_vlc[1], VLCBITS, HUFF_COEF1_SIZE,
> +                 coef1_huffbits, 1, 1,
> +                 coef1_huffcodes, 4, 4, 3912);
> +
> +    INIT_VLC_STATIC(&vec4_vlc, VLCBITS, HUFF_VEC4_SIZE,
> +                 vec4_huffbits, 1, 1,
> +                 vec4_huffcodes, 2, 2, 604);
> +
> +    INIT_VLC_STATIC(&vec2_vlc, VLCBITS, HUFF_VEC2_SIZE,
> +                 vec2_huffbits, 1, 1,
> +                 vec2_huffcodes, 2, 2, 562);
> +
> +    INIT_VLC_STATIC(&vec1_vlc, VLCBITS, HUFF_VEC1_SIZE,
> +                 vec1_huffbits, 1, 1,
> +                 vec1_huffcodes, 2, 2, 562);
> +
> +    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));
> +
> +    if (!s->num_sfb ||
> +       !s->sfb_offsets || !s->subwoofer_cutoffs || !s->sf_offsets) {
> +        av_log(avctx, AV_LOG_ERROR,
> +                      "failed to allocate scale factor offset tables\n");
> +        decode_end(avctx);
> +        return AVERROR_NOMEM;
> +    }
> +
> +    /** calculate number of scale factor bands and their offsets
> +        for every possible block size */
> +    sfb_offsets = s->sfb_offsets;
> +
> +    for (i=0;i<s->num_possible_block_sizes;i++) {
> +        int subframe_len = s->samples_per_frame >> i;
> +        int x;
> +        int band = 1;
> +
> +        sfb_offsets[0] = 0;
> +
> +        for (x=0;x < MAX_BANDS-1 && sfb_offsets[band-1] < subframe_len;x++) {
> +            int offset = (subframe_len * 2 * critical_freq[x])
> +                          / s->avctx->sample_rate + 2;
> +            offset &= ~3;
> +            if ( offset > sfb_offsets[band - 1] )
> +                sfb_offsets[band++] = offset;
> +        }
> +        sfb_offsets[band - 1] = subframe_len;
> +        s->num_sfb[i] = band - 1;
> +        sfb_offsets += MAX_BANDS;
> +    }

looking at the MAX_BANDS i was wonderin if the thing might be better as a
2d array?


> +
> +
> +    /** Scale factors can be shared between blocks of different size
> +        as every block has a different scale factor band layout.
> +        The matrix sf_offsets is needed to find the correct scale factor.
> +     */
> +
> +    for (i=0;i<s->num_possible_block_sizes;i++) {
> +        int b;

> +        for (b=0;b< s->num_sfb[i];b++) {

the whitespace seems inconsistent around < here


> +            int x;
> +            int offset = ((s->sfb_offsets[MAX_BANDS * i + b]
> +                         + s->sfb_offsets[MAX_BANDS * i + b + 1] - 1)<<i) >> 1;
> +            for (x=0;x<s->num_possible_block_sizes;x++) {
> +                int v = 0;
> +                while (s->sfb_offsets[MAX_BANDS * x + v +1] << x < offset)
> +                    ++v;
> +                s->sf_offsets[  i * s->num_possible_block_sizes * MAX_BANDS
> +                              + x * MAX_BANDS + b] = v;
> +            }
> +        }
> +    }
> +
> +    /** init MDCT, FIXME: only init needed sizes */
> +    for (i = 0; i < WMAPRO_BLOCK_SIZES; i++)
> +        ff_mdct_init(&s->mdct_ctx[i], BLOCK_MIN_BITS+1+i, 1,
> +                     1.0 / (1 <<(BLOCK_MIN_BITS + i - 1))
> +                     / (1 << (s->bits_per_sample - 1)));
> +
> +    /** init MDCT windows: simple sinus window */
> +    for (i=0 ; i<WMAPRO_BLOCK_SIZES ; i++) {
> +        const int n = 1 << (WMAPRO_BLOCK_MAX_BITS - i);
> +        const int win_idx = WMAPRO_BLOCK_MAX_BITS - i - 7;
> +        ff_sine_window_init(ff_sine_windows[win_idx], n);
> +        s->windows[WMAPRO_BLOCK_SIZES-i-1] = ff_sine_windows[win_idx];
> +    }
> +
> +    /** calculate subwoofer cutoff values */
> +    for (i=0;i< s->num_possible_block_sizes;i++) {
> +        int block_size = s->samples_per_frame >> i;
> +        int cutoff = (440*block_size + 3 * (s->avctx->sample_rate >> 1) - 1)
> +                     / s->avctx->sample_rate;
> +        s->subwoofer_cutoffs[i] = av_clip(cutoff,4,block_size);
> +    }
> +
> +    /** calculate sine values for the decorrelation matrix */
> +    for (i=0;i<33;i++)
> +        sin64[i] = sin(i*M_PI / 64.0);
> +

> +    dump_context(s);

this should be under some FF_DEBUG_ if() like in the video decoders
otherwise it can become pretty hard to read the result as there are
too many av_logs being printed ...



> +    avctx->channel_layout = channel_mask;
> +    return 0;
> +}
> +
> +/**
> + *@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 frame with the

frame or subframe ?


> + *       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;
> +
> +    /* 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;
> +        s->channel[c].channel_len = 0;
> +    }
> +
> +    /** 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 = 3;
> +        } else
> +            subframe_len_bits = av_log2(av_log2(s->max_num_subframes)) + 1;

the special casing of subframe_len_bits seems unneeded


[...]
> +/**
> + *@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;
> +    int8_t 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++)
> +        chgroup->decorrelation_matrix[chgroup->num_channels * i + i] =
> +                                                get_bits1(&s->gb) ? 1.0 : -1.0;
> +
> +    for (i=1;i<chgroup->num_channels;i++) {
> +        int x;
> +        for (x=0;x<i;x++) {
> +            int 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];
> +                float sinv;
> +                float cosv;
> +
> +                if (n<32) {
> +                    sinv = sin64[n];
> +                    cosv = sin64[32-n];
> +                } else {
> +                    sinv = sin64[64-n];
> +                    cosv = -sin64[n-32];
> +                }
> +
> +                chgroup->decorrelation_matrix[y + x * chgroup->num_channels] =
> +                                               (v1 * sinv) - (v2 * cosv);
> +                chgroup->decorrelation_matrix[y + i * chgroup->num_channels] =
> +                                               (v1 * cosv) + (v2 * sinv);
> +            }
> +        }
> +        offset += i;
> +    }
> +}

i wonder if decorrelation_matrix should be a 2d array besides this, this
function is ok


[...]
> +            /** 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 {

> +                    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;
> +                    }

why the special handling of 2 vs. >2 channels here?


[...]
> +/**
> + *@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) & 0xF;

does this really need the & F ?


> +                    vals[i+1] = symbol_to_vec2[idx] & 0xF;
> +                }
> +            }
> +        } else {

> +             vals[0] = (symbol_to_vec4[idx] >> 8) >> 4;

can be simplified


[...]
> +/**
> + *@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);
> +            const int16_t* sf_offsets =
> +                               &s->sf_offsets[s->num_possible_block_sizes *
> +                               MAX_BANDS  * idx0 + MAX_BANDS * idx1];
> +            int b;
> +            for (b=0;b<s->num_bands;b++)
> +                s->channel[c].resampled_scale_factors[b] =
> +                                   s->channel[c].scale_factors[*sf_offsets++];
> +
> +            s->channel[c].max_scale_factor =
> +                                   s->channel[c].resampled_scale_factors[0];
> +            sf = s->channel[c].resampled_scale_factors + 1;
> +            while (sf < s->channel[c].resampled_scale_factors + s->num_bands) {
> +                if (*sf > s->channel[c].max_scale_factor)
> +                    s->channel[c].max_scale_factor = *sf;
> +                ++sf;
> +            }
> +        }
> +
> +        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) {
> +
> +            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 */
> +
> +                memcpy(s->channel[c].scale_factors,
> +                       s->channel[c].resampled_scale_factors,
> +                       sizeof(int) * s->num_bands);
> +
> +                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;

any reason why that are not 3 get_bits() ?


> +                    } 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;
> +                    } else
> +                        s->channel[c].scale_factors[i] += (val ^ sign) - sign;
> +                }
> +            }
> +
> +            s->channel[c].reuse_sf = 1;

> +            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;
> +            }

seems duplicated



> +            s->channel[c].scale_factor_block_len = s->subframe_len;
> +        }
> +    }
> +    return 0;
> +}
> +

> +/**
> + *@brief Reconstruct the individual channel data.
> + *@param s codec context
> + */
> +static void inverse_channel_transform(WMA3DecodeContext *s)
> +{
> +    int i;
> +
> +    for (i=0;i<s->num_chgroups;i++) {
> +
> +        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;
> +
> +            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;
> +                    }
> +                } else {
> +                    while (ch0 < ch0_end) {
> +                        *ch0++ *= 181.0 / 128;
> +                        *ch1++ *= 181.0 / 128;
> +                    }
> +                }
> +                ++sfb_offsets;
> +            }
> +        } else if (s->chgroup[i].transform) {
> +            float data[WMAPRO_MAX_CHANNELS];
> +            const int num_channels = s->chgroup[i].num_channels;
> +            float** ch_data = s->chgroup[i].channel_data;
> +            float** ch_end = ch_data + num_channels;
> +            const int8_t* tb = s->chgroup[i].transform_band;
> +            int16_t* sfb;
> +
> +            /** multichannel decorrelation */
> +            for (sfb = s->cur_sfb_offsets ;
> +                sfb < s->cur_sfb_offsets + s->num_bands;sfb++) {
> +                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;
> +                        const float* data_end= data + num_channels;
> +                        float* data_ptr= data;
> +                        float** ch;
> +
> +                        for (ch = ch_data;ch < ch_end; ch++)
> +                           *data_ptr++ = (*ch)[y];
> +
> +                        for (ch = ch_data; ch < ch_end; ch++) {
> +                            float sum = 0;
> +                            data_ptr = data;
> +                            while (data_ptr < data_end)
> +                                sum += *data_ptr++ * *mat++;
> +
> +                            (*ch)[y] = sum;
> +                        }
> +                    }
> +                }
> +            }
> +        }
> +    }
> +}

function ok


> +
> +/**
> + *@brief Apply sine window and reconstruct the output buffer.
> + *@param s codec context
> + */
> +static void window(WMA3DecodeContext *s)

the function name is not good

[...]
> +/**
> + *@brief Decode a single subframe (block).
> + *@param s codec context
> + *@return 0 on success, < 0 when decoding failed
> + */
> +static int decode_subframe(WMA3DecodeContext *s)
> +{
> +    int offset = s->samples_per_frame;
> +    int subframe_len = s->samples_per_frame;
> +    int i;
> +    int total_samples = s->samples_per_frame * s->num_channels;
> +    int transmit_coeffs = 0;
> +
> +    s->subframe_offset = get_bits_count(&s->gb);
> +
> +    /** reset channel context and find the next block offset and size
> +        == the next block of the channel with the smallest number of
> +        decoded samples
> +    */
> +    for (i=0;i<s->num_channels;i++) {
> +        s->channel[i].grouped = 0;
> +        if (offset > s->channel[i].decoded_samples) {
> +            offset = s->channel[i].decoded_samples;
> +            subframe_len =
> +                s->channel[i].subframe_len[s->channel[i].cur_subframe];
> +        }
> +    }
> +
> +    dprintf(s->avctx,
> +           "processing subframe with offset %i len %i\n",offset,subframe_len);
> +
> +    /** get a list of all channels that contain the estimated block */
> +    s->channels_for_cur_subframe = 0;
> +    for (i=0;i<s->num_channels;i++) {
> +        const int cur_subframe = s->channel[i].cur_subframe;
> +        /** substract already processed samples */
> +        total_samples -= s->channel[i].decoded_samples;
> +
> +        /** and count if there are multiple subframes that match our profile */
> +        if (offset == s->channel[i].decoded_samples &&
> +           subframe_len == s->channel[i].subframe_len[cur_subframe]) {
> +            total_samples -= s->channel[i].subframe_len[cur_subframe];
> +            s->channel[i].decoded_samples +=
> +                s->channel[i].subframe_len[cur_subframe];
> +            s->channel_indexes_for_cur_subframe[s->channels_for_cur_subframe] = i;
> +            ++s->channels_for_cur_subframe;
> +        }
> +    }
> +
> +    /** check if the frame will be complete after processing the
> +        estimated block */
> +    if (!total_samples)
> +        s->parsed_all_subframes = 1;
> +
> +
> +    dprintf(s->avctx, "subframe is part of %i channels\n",
> +           s->channels_for_cur_subframe);
> +

> +    /** calculate number of scale factor bands and their offsets */
> +    if (subframe_len == s->samples_per_frame) {
> +        s->num_bands = s->num_sfb[0];
> +        s->cur_sfb_offsets = s->sfb_offsets;
> +        s->cur_subwoofer_cutoff = s->subwoofer_cutoffs[0];
> +    } else {
> +        int frame_offset = av_log2(s->samples_per_frame/subframe_len);
> +        s->num_bands = s->num_sfb[frame_offset];
> +        s->cur_sfb_offsets = &s->sfb_offsets[MAX_BANDS * frame_offset];
> +        s->cur_subwoofer_cutoff = s->subwoofer_cutoffs[frame_offset];
> +    }

redundant special casing


[...]
> +    if (transmit_coeffs) {
> +        /** reconstruct the per channel data */
> +        inverse_channel_transform(s);
> +        for (i=0;i<s->channels_for_cur_subframe;i++) {
> +            int c = s->channel_indexes_for_cur_subframe[i];
> +            int* sf;
> +            int b;
> +

> +            if (s->channel[c].transmit_sf) {
> +                sf = s->channel[c].scale_factors;
> +            } else
> +                sf = s->channel[c].resampled_scale_factors;

cant they be put in the same array ? (just asking ...)

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

If you think the mosad wants you dead since a long time then you are either
wrong or dead since a long time.
-------------- 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/20090714/9fd904bc/attachment.pgp>



More information about the ffmpeg-devel mailing list