[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