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; | 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_init(AVCodecContext * avctx, int flags2); | ||||
| int ff_wma_total_gain_to_bits(int total_gain); | int ff_wma_total_gain_to_bits(int total_gain); | ||||
| int ff_wma_end(AVCodecContext *avctx); | 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 */ | #endif /* AVCODEC_WMA_H */ | ||||
| @@ -349,7 +349,7 @@ static void wma_window(WMACodecContext *s, float *out) | |||||
| */ | */ | ||||
| static int wma_decode_block(WMACodecContext *s) | 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 coef_nb_bits, total_gain; | ||||
| int nb_coefs[MAX_CHANNELS]; | int nb_coefs[MAX_CHANNELS]; | ||||
| float mdct_norm; | float mdct_norm; | ||||
| @@ -485,53 +485,17 @@ static int wma_decode_block(WMACodecContext *s) | |||||
| /* parse spectral coefficients : just RLE encoding */ | /* parse spectral coefficients : just RLE encoding */ | ||||
| for(ch = 0; ch < s->nb_channels; ch++) { | for(ch = 0; ch < s->nb_channels; ch++) { | ||||
| if (s->channel_coded[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 | /* special VLC tables are used for ms stereo because | ||||
| there is potentially less energy there */ | there is potentially less energy there */ | ||||
| tindex = (ch == 1 && s->ms_stereo); | 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)); | 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) { | if (s->version == 1 && s->nb_channels >= 2) { | ||||
| align_get_bits(&s->gb); | align_get_bits(&s->gb); | ||||