diff options
author | Sascha Sommer <saschasommer@freenet.de> | 2009-08-26 21:23:21 +0000 |
---|---|---|
committer | Sascha Sommer <saschasommer@freenet.de> | 2009-08-26 21:23:21 +0000 |
commit | 85fecafe49ca7fc27801149e38bed42ba1cd4d58 (patch) | |
tree | a46713e825dafd5c4fb0dcf8bc24da3dec4af8e4 /libavcodec/wmaprodec.c | |
parent | f53e96ed4170425ea70f818ea600b7a5f2a026d7 (diff) | |
download | ffmpeg-85fecafe49ca7fc27801149e38bed42ba1cd4d58.tar.gz |
add decode_coeffs()
Originally committed as revision 19719 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/wmaprodec.c')
-rw-r--r-- | libavcodec/wmaprodec.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/libavcodec/wmaprodec.c b/libavcodec/wmaprodec.c index 8f48aff8ad..d06af5e284 100644 --- a/libavcodec/wmaprodec.c +++ b/libavcodec/wmaprodec.c @@ -153,6 +153,94 @@ static void decode_decorrelation_matrix(WMA3DecodeContext *s, } /** + *@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; +} + +/** *@brief Reconstruct the individual channel data. *@param s codec context */ |