+ av_free(s->int_table[i]);
+ }
+
+ return 0;
+}
+
+/**
+ * Decode an uncompressed coefficient.
+ * @param bc BitstreamContext
+ * @return the decoded coefficient
+ */
+unsigned int ff_wma_get_large_val(BitstreamContext *bc)
+{
+ /** consumes up to 34 bits */
+ int n_bits = 8;
+ /** decode length */
+ if (bitstream_read_bit(bc)) {
+ n_bits += 8;
+ if (bitstream_read_bit(bc)) {
+ n_bits += 8;
+ if (bitstream_read_bit(bc))
+ n_bits += 7;
+ }
+ }
+ return bitstream_read(bc, n_bits);
+}
+
+/**
+ * Decode run level compressed coefficients.
+ * @param avctx codec context
+ * @param bc bitstream reader context
+ * @param vlc VLC table for bitstream_read_vlc
+ * @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 coefficients
+ * @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, BitstreamContext *bc,
+ VLC *vlc, const float *level_table,
+ const uint16_t *run_table, int version,
+ WMACoef *ptr, int offset, int num_coefs,
+ int block_len, int frame_len_bits,
+ int coef_nb_bits)
+{
+ int code, level, sign;
+ const uint32_t *ilvl = (const uint32_t *) level_table;
+ uint32_t *iptr = (uint32_t *) ptr;
+ const unsigned int coef_mask = block_len - 1;
+ for (; offset < num_coefs; offset++) {
+ code = bitstream_read_vlc(bc, vlc->table, VLCBITS, VLCMAX);
+ if (code > 1) {
+ /** normal code */
+ offset += run_table[code];
+ sign = bitstream_read_bit(bc) - 1;
+ iptr[offset & coef_mask] = ilvl[code] ^ sign << 31;
+ } else if (code == 1) {
+ /** EOB */
+ break;
+ } else {
+ /** escape */
+ if (!version) {
+ level = bitstream_read(bc, coef_nb_bits);
+ /** NOTE: this is rather suboptimal. reading
+ * block_len_bits would be better */
+ offset += bitstream_read(bc, frame_len_bits);
+ } else {
+ level = ff_wma_get_large_val(bc);
+ /** escape decode */
+ if (bitstream_read_bit(bc)) {
+ if (bitstream_read_bit(bc)) {
+ if (bitstream_read_bit(bc)) {
+ av_log(avctx, AV_LOG_ERROR,
+ "broken escape sequence\n");
+ return -1;
+ } else
+ offset += bitstream_read(bc, frame_len_bits) + 4;
+ } else
+ offset += bitstream_read(bc, 2) + 1;
+ }
+ }
+ sign = bitstream_read_bit(bc) - 1;
+ ptr[offset & coef_mask] = (level ^ sign) - sign;
+ }
+ }
+ /** NOTE: EOB can be omitted */
+ if (offset > num_coefs) {
+ av_log(avctx, AV_LOG_ERROR, "overflow in spectral RLE, ignoring\n");
+ return -1;