so that it can be reused for wmapro Originally committed as revision 19171 to svn://svn.ffmpeg.org/ffmpeg/trunktags/v0.6
@@ -424,3 +424,64 @@ int ff_wma_end(AVCodecContext *avctx) | |||
return 0; | |||
} | |||
/** | |||
* Decode run level compressed coefficients. | |||
* @param avctx codec context | |||
* @param gb bitstream reader context | |||
* @param vlc vlc table for get_vlc2 | |||
* @param level_table level codes | |||
* @param run_table run codes | |||
* @param version 0 for wma1,2 1 for wmapro | |||
* @param ptr output buffer | |||
* @param offset offset in the output buffer | |||
* @param num_coefs number of input coefficents | |||
* @param block_len input buffer length (2^n) | |||
* @param frame_len_bits number of bits for escaped run codes | |||
* @param coef_nb_bits number of bits for escaped level codes | |||
* @return 0 on success, -1 otherwise | |||
*/ | |||
int ff_wma_run_level_decode(AVCodecContext* avctx, GetBitContext* gb, | |||
VLC *vlc, | |||
const uint16_t *level_table, const uint16_t *run_table, | |||
int version, int16_t *ptr, int offset, | |||
int num_coefs, int block_len, int frame_len_bits, | |||
int coef_nb_bits) | |||
{ | |||
int code, run, level, sign; | |||
int16_t* eptr = ptr + num_coefs; | |||
for(;;) { | |||
code = get_vlc2(gb, vlc->table, VLCBITS, VLCMAX); | |||
if (code < 0) | |||
return -1; | |||
if (code == 1) { | |||
/* EOB */ | |||
break; | |||
} else if (code == 0) { | |||
/* escape */ | |||
level = get_bits(gb, coef_nb_bits); | |||
/* NOTE: this is rather suboptimal. reading | |||
block_len_bits would be better */ | |||
run = get_bits(gb, frame_len_bits); | |||
} else { | |||
/* normal code */ | |||
run = run_table[code]; | |||
level = level_table[code]; | |||
} | |||
sign = get_bits1(gb); | |||
if (!sign) | |||
level = -level; | |||
ptr += run; | |||
if (ptr >= eptr) | |||
{ | |||
av_log(NULL, AV_LOG_ERROR, "overflow in spectral RLE, ignoring\n"); | |||
break; | |||
} | |||
*ptr++ = level; | |||
/* NOTE: EOB can be omitted */ | |||
if (ptr >= eptr) | |||
break; | |||
} | |||
return 0; | |||
} | |||
@@ -148,5 +148,11 @@ int av_cold ff_wma_get_frame_len_bits(int sample_rate, int version, | |||
int ff_wma_init(AVCodecContext * avctx, int flags2); | |||
int ff_wma_total_gain_to_bits(int total_gain); | |||
int ff_wma_end(AVCodecContext *avctx); | |||
int ff_wma_run_level_decode(AVCodecContext* avctx, GetBitContext* gb, | |||
VLC *vlc, | |||
const uint16_t *level_table, const uint16_t *run_table, | |||
int version, int16_t *ptr, int offset, | |||
int num_coefs, int block_len, int frame_len_bits, | |||
int coef_nb_bits); | |||
#endif /* AVCODEC_WMA_H */ |
@@ -349,7 +349,7 @@ static void wma_window(WMACodecContext *s, float *out) | |||
*/ | |||
static int wma_decode_block(WMACodecContext *s) | |||
{ | |||
int n, v, a, ch, code, bsize; | |||
int n, v, a, ch, bsize; | |||
int coef_nb_bits, total_gain; | |||
int nb_coefs[MAX_CHANNELS]; | |||
float mdct_norm; | |||
@@ -485,53 +485,17 @@ static int wma_decode_block(WMACodecContext *s) | |||
/* parse spectral coefficients : just RLE encoding */ | |||
for(ch = 0; ch < s->nb_channels; ch++) { | |||
if (s->channel_coded[ch]) { | |||
VLC *coef_vlc; | |||
int level, run, sign, tindex; | |||
int16_t *ptr, *eptr; | |||
const uint16_t *level_table, *run_table; | |||
int tindex; | |||
int16_t* ptr = &s->coefs1[ch][0]; | |||
/* special VLC tables are used for ms stereo because | |||
there is potentially less energy there */ | |||
tindex = (ch == 1 && s->ms_stereo); | |||
coef_vlc = &s->coef_vlc[tindex]; | |||
run_table = s->run_table[tindex]; | |||
level_table = s->level_table[tindex]; | |||
/* XXX: optimize */ | |||
ptr = &s->coefs1[ch][0]; | |||
eptr = ptr + nb_coefs[ch]; | |||
memset(ptr, 0, s->block_len * sizeof(int16_t)); | |||
for(;;) { | |||
code = get_vlc2(&s->gb, coef_vlc->table, VLCBITS, VLCMAX); | |||
if (code < 0) | |||
return -1; | |||
if (code == 1) { | |||
/* EOB */ | |||
break; | |||
} else if (code == 0) { | |||
/* escape */ | |||
level = get_bits(&s->gb, coef_nb_bits); | |||
/* NOTE: this is rather suboptimal. reading | |||
block_len_bits would be better */ | |||
run = get_bits(&s->gb, s->frame_len_bits); | |||
} else { | |||
/* normal code */ | |||
run = run_table[code]; | |||
level = level_table[code]; | |||
} | |||
sign = get_bits1(&s->gb); | |||
if (!sign) | |||
level = -level; | |||
ptr += run; | |||
if (ptr >= eptr) | |||
{ | |||
av_log(NULL, AV_LOG_ERROR, "overflow in spectral RLE, ignoring\n"); | |||
break; | |||
} | |||
*ptr++ = level; | |||
/* NOTE: EOB can be omitted */ | |||
if (ptr >= eptr) | |||
break; | |||
} | |||
ff_wma_run_level_decode(s->avctx, &s->gb, &s->coef_vlc[tindex], | |||
s->level_table[tindex], s->run_table[tindex], | |||
0, ptr, 0, nb_coefs[ch], | |||
s->block_len, s->frame_len_bits, coef_nb_bits); | |||
} | |||
if (s->version == 1 && s->nb_channels >= 2) { | |||
align_get_bits(&s->gb); | |||