static av_cold int decode_init(WMAProDecodeCtx *s, AVCodecContext *avctx)

{

    uint8_t *edata_ptr = avctx->extradata;

    unsigned int channel_mask;

    int i, bits;

    int log2_max_num_subframes;

    int num_possible_block_sizes;



    if (avctx->codec_id == AV_CODEC_ID_XMA1 || avctx->codec_id == AV_CODEC_ID_XMA2)

        avctx->block_align = 2048;



    if (!avctx->block_align) {

        av_log(avctx, AV_LOG_ERROR, "block_align is not set\n");

        return AVERROR(EINVAL);

    }



    s->avctx = avctx;

    s->fdsp = avpriv_float_dsp_alloc(avctx->flags & AV_CODEC_FLAG_BITEXACT);

    if (!s->fdsp)

        return AVERROR(ENOMEM);



    init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);



    avctx->sample_fmt = AV_SAMPLE_FMT_FLTP;



    /** dump the extradata */

    av_log(avctx, AV_LOG_DEBUG, "extradata:\n");

    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");

    if (avctx->codec_id == AV_CODEC_ID_XMA2 && (!avctx->extradata || avctx->extradata_size >= 6)) {

        s->decode_flags    = 0x10d6;

        channel_mask       = avctx->extradata ? AV_RL32(edata_ptr+2) : 0;

        s->bits_per_sample = 16;

     } else if (avctx->codec_id == AV_CODEC_ID_XMA1) {

        s->decode_flags    = 0x10d6;

        s->bits_per_sample = 16;

        channel_mask       = 0;

     } else if (avctx->codec_id == AV_CODEC_ID_WMAPRO && 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);



        if (s->bits_per_sample > 32 || s->bits_per_sample < 1) {

            avpriv_request_sample(avctx, "bits per sample is %d", s->bits_per_sample);

            return AVERROR_PATCHWELCOME;

        }

    } else {

        avpriv_request_sample(avctx, "Unknown extradata size");

        return AVERROR_PATCHWELCOME;

    }



    if (avctx->codec_id != AV_CODEC_ID_WMAPRO && avctx->channels > 2) {

        s->nb_channels = 2;

    } else {

        s->nb_channels = avctx->channels;

    }



    /** generic init */

    s->log2_frame_size = av_log2(avctx->block_align) + 4;

    if (s->log2_frame_size > 25) {

        avpriv_request_sample(avctx, "Large block align");

        return AVERROR_PATCHWELCOME;

    }



    /** frame info */

    if (avctx->codec_id != AV_CODEC_ID_WMAPRO)

        s->skip_frame = 0;

    else

        s->skip_frame = 1; /* skip first frame */



    s->packet_loss = 1;

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



    /** get frame len */

    if (avctx->codec_id == AV_CODEC_ID_WMAPRO) {

        bits = ff_wma_get_frame_len_bits(avctx->sample_rate, 3, s->decode_flags);

        if (bits > WMAPRO_BLOCK_MAX_BITS) {

            avpriv_request_sample(avctx, "14-bit block sizes");

            return AVERROR_PATCHWELCOME;

        }

        s->samples_per_frame = 1 << bits;

    } else {

        s->samples_per_frame = 512;

    }



    /** subframe info */

    log2_max_num_subframes       = ((s->decode_flags & 0x38) >> 3);

    s->max_num_subframes         = 1 << log2_max_num_subframes;

    if (s->max_num_subframes == 16 || s->max_num_subframes == 4)

        s->max_subframe_len_bit = 1;

    s->subframe_len_bits = av_log2(log2_max_num_subframes) + 1;



    num_possible_block_sizes     = log2_max_num_subframes + 1;

    s->min_samples_per_subframe  = s->samples_per_frame / s->max_num_subframes;

    s->dynamic_range_compression = (s->decode_flags & 0x80);



    if (s->max_num_subframes > MAX_SUBFRAMES) {

        av_log(avctx, AV_LOG_ERROR, "invalid number of subframes %"PRId8"\n",

               s->max_num_subframes);

        return AVERROR_INVALIDDATA;

    }



    if (s->min_samples_per_subframe < WMAPRO_BLOCK_MIN_SIZE) {

        av_log(avctx, AV_LOG_ERROR, "min_samples_per_subframe of %d too small\n",

               s->min_samples_per_subframe);

        return AVERROR_INVALIDDATA;

    }



    if (s->avctx->sample_rate <= 0) {

        av_log(avctx, AV_LOG_ERROR, "invalid sample rate\n");

        return AVERROR_INVALIDDATA;

    }



    if (s->nb_channels <= 0) {

        av_log(avctx, AV_LOG_ERROR, "invalid number of channels %d\n",

               s->nb_channels);

        return AVERROR_INVALIDDATA;

    } else if (s->nb_channels > WMAPRO_MAX_CHANNELS) {

        avpriv_request_sample(avctx,

                              "More than %d channels", WMAPRO_MAX_CHANNELS);

        return AVERROR_PATCHWELCOME;

    }



    /** init previous block len */

    for (i = 0; i < s->nb_channels; i++)

        s->channel[i].prev_block_len = s->samples_per_frame;



    /** 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;

        }

    }



    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);



    /** calculate number of scale factor bands and their offsets

        for every possible block size */

    for (i = 0; i < num_possible_block_sizes; i++) {

        int subframe_len = s->samples_per_frame >> i;

        int x;

        int band = 1;

        int rate = get_rate(avctx);



        s->sfb_offsets[i][0] = 0;



        for (x = 0; x < MAX_BANDS-1 && s->sfb_offsets[i][band - 1] < subframe_len; x++) {

            int offset = (subframe_len * 2 * critical_freq[x]) / rate + 2;

            offset &= ~3;

            if (offset > s->sfb_offsets[i][band - 1])

                s->sfb_offsets[i][band++] = offset;



            if (offset >= subframe_len)

                break;

        }

        s->sfb_offsets[i][band - 1] = subframe_len;

        s->num_sfb[i]               = band - 1;

        if (s->num_sfb[i] <= 0) {

            av_log(avctx, AV_LOG_ERROR, "num_sfb invalid\n");

            return AVERROR_INVALIDDATA;

        }

    }





    /** 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 < num_possible_block_sizes; i++) {

        int b;

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

            int x;

            int offset = ((s->sfb_offsets[i][b]

                           + s->sfb_offsets[i][b + 1] - 1) << i) >> 1;

            for (x = 0; x < num_possible_block_sizes; x++) {

                int v = 0;

                while (s->sfb_offsets[x][v + 1] << x < offset) {

                    v++;

                    av_assert0(v < MAX_BANDS);

                }

                s->sf_offsets[i][x][b] = v;

            }

        }

    }



    /** init MDCT, FIXME: only init needed sizes */

    for (i = 0; i < WMAPRO_BLOCK_SIZES; i++)

        ff_mdct_init(&s->mdct_ctx[i], WMAPRO_BLOCK_MIN_BITS+1+i, 1,

                     1.0 / (1 << (WMAPRO_BLOCK_MIN_BITS + i - 1))

                     / (1 << (s->bits_per_sample - 1)));



    /** init MDCT windows: simple sine window */

    for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) {

        const int win_idx = WMAPRO_BLOCK_MAX_BITS - i;

        ff_init_ff_sine_windows(win_idx);

        s->windows[WMAPRO_BLOCK_SIZES - i - 1] = ff_sine_windows[win_idx];

    }



    /** calculate subwoofer cutoff values */

    for (i = 0; i < num_possible_block_sizes; i++) {

        int block_size = s->samples_per_frame >> i;

        int cutoff = (440*block_size + 3LL * (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);



    if (avctx->debug & FF_DEBUG_BITSTREAM)

        dump_context(s);



    avctx->channel_layout = channel_mask;



    return 0;

}
