Mercurial > libavcodec.hg
view wmadec.c @ 10345:294c444866f7 libavcodec
Make avcodec_open set codec_id and codec_type if they haven't been set.
This fixes the API breakage introduced by the check that avctx codec id and type
match the opened codec and should make (almost?) all applications work again.
author | reimar |
---|---|
date | Thu, 01 Oct 2009 15:54:55 +0000 |
parents | 88e1eb862abd |
children | d0e17b0a6845 |
line wrap: on
line source
/* * WMA compatible decoder * Copyright (c) 2002 The FFmpeg Project * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file libavcodec/wmadec.c * WMA compatible decoder. * This decoder handles Microsoft Windows Media Audio data, versions 1 & 2. * WMA v1 is identified by audio format 0x160 in Microsoft media files * (ASF/AVI/WAV). WMA v2 is identified by audio format 0x161. * * To use this decoder, a calling application must supply the extra data * bytes provided with the WMA data. These are the extra, codec-specific * bytes at the end of a WAVEFORMATEX data structure. Transmit these bytes * to the decoder using the extradata[_size] fields in AVCodecContext. There * should be 4 extra bytes for v1 data and 6 extra bytes for v2 data. */ #include "avcodec.h" #include "wma.h" #undef NDEBUG #include <assert.h> #define EXPVLCBITS 8 #define EXPMAX ((19+EXPVLCBITS-1)/EXPVLCBITS) #define HGAINVLCBITS 9 #define HGAINMAX ((13+HGAINVLCBITS-1)/HGAINVLCBITS) static void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len); #ifdef TRACE static void dump_shorts(WMACodecContext *s, const char *name, const short *tab, int n) { int i; tprintf(s->avctx, "%s[%d]:\n", name, n); for(i=0;i<n;i++) { if ((i & 7) == 0) tprintf(s->avctx, "%4d: ", i); tprintf(s->avctx, " %5d.0", tab[i]); if ((i & 7) == 7) tprintf(s->avctx, "\n"); } } static void dump_floats(WMACodecContext *s, const char *name, int prec, const float *tab, int n) { int i; tprintf(s->avctx, "%s[%d]:\n", name, n); for(i=0;i<n;i++) { if ((i & 7) == 0) tprintf(s->avctx, "%4d: ", i); tprintf(s->avctx, " %8.*f", prec, tab[i]); if ((i & 7) == 7) tprintf(s->avctx, "\n"); } if ((i & 7) != 0) tprintf(s->avctx, "\n"); } #endif static int wma_decode_init(AVCodecContext * avctx) { WMACodecContext *s = avctx->priv_data; int i, flags2; uint8_t *extradata; s->avctx = avctx; /* extract flag infos */ flags2 = 0; extradata = avctx->extradata; if (avctx->codec->id == CODEC_ID_WMAV1 && avctx->extradata_size >= 4) { flags2 = AV_RL16(extradata+2); } else if (avctx->codec->id == CODEC_ID_WMAV2 && avctx->extradata_size >= 6) { flags2 = AV_RL16(extradata+4); } // for(i=0; i<avctx->extradata_size; i++) // av_log(NULL, AV_LOG_ERROR, "%02X ", extradata[i]); s->use_exp_vlc = flags2 & 0x0001; s->use_bit_reservoir = flags2 & 0x0002; s->use_variable_block_len = flags2 & 0x0004; if(ff_wma_init(avctx, flags2)<0) return -1; /* init MDCT */ for(i = 0; i < s->nb_block_sizes; i++) ff_mdct_init(&s->mdct_ctx[i], s->frame_len_bits - i + 1, 1, 1.0); if (s->use_noise_coding) { init_vlc(&s->hgain_vlc, HGAINVLCBITS, sizeof(ff_wma_hgain_huffbits), ff_wma_hgain_huffbits, 1, 1, ff_wma_hgain_huffcodes, 2, 2, 0); } if (s->use_exp_vlc) { init_vlc(&s->exp_vlc, EXPVLCBITS, sizeof(ff_wma_scale_huffbits), //FIXME move out of context ff_wma_scale_huffbits, 1, 1, ff_wma_scale_huffcodes, 4, 4, 0); } else { wma_lsp_to_curve_init(s, s->frame_len); } avctx->sample_fmt = SAMPLE_FMT_S16; return 0; } /** * compute x^-0.25 with an exponent and mantissa table. We use linear * interpolation to reduce the mantissa table size at a small speed * expense (linear interpolation approximately doubles the number of * bits of precision). */ static inline float pow_m1_4(WMACodecContext *s, float x) { union { float f; unsigned int v; } u, t; unsigned int e, m; float a, b; u.f = x; e = u.v >> 23; m = (u.v >> (23 - LSP_POW_BITS)) & ((1 << LSP_POW_BITS) - 1); /* build interpolation scale: 1 <= t < 2. */ t.v = ((u.v << LSP_POW_BITS) & ((1 << 23) - 1)) | (127 << 23); a = s->lsp_pow_m_table1[m]; b = s->lsp_pow_m_table2[m]; return s->lsp_pow_e_table[e] * (a + b * t.f); } static void wma_lsp_to_curve_init(WMACodecContext *s, int frame_len) { float wdel, a, b; int i, e, m; wdel = M_PI / frame_len; for(i=0;i<frame_len;i++) s->lsp_cos_table[i] = 2.0f * cos(wdel * i); /* tables for x^-0.25 computation */ for(i=0;i<256;i++) { e = i - 126; s->lsp_pow_e_table[i] = pow(2.0, e * -0.25); } /* NOTE: these two tables are needed to avoid two operations in pow_m1_4 */ b = 1.0; for(i=(1 << LSP_POW_BITS) - 1;i>=0;i--) { m = (1 << LSP_POW_BITS) + i; a = (float)m * (0.5 / (1 << LSP_POW_BITS)); a = pow(a, -0.25); s->lsp_pow_m_table1[i] = 2 * a - b; s->lsp_pow_m_table2[i] = b - a; b = a; } #if 0 for(i=1;i<20;i++) { float v, r1, r2; v = 5.0 / i; r1 = pow_m1_4(s, v); r2 = pow(v,-0.25); printf("%f^-0.25=%f e=%f\n", v, r1, r2 - r1); } #endif } /** * NOTE: We use the same code as Vorbis here * @todo optimize it further with SSE/3Dnow */ static void wma_lsp_to_curve(WMACodecContext *s, float *out, float *val_max_ptr, int n, float *lsp) { int i, j; float p, q, w, v, val_max; val_max = 0; for(i=0;i<n;i++) { p = 0.5f; q = 0.5f; w = s->lsp_cos_table[i]; for(j=1;j<NB_LSP_COEFS;j+=2){ q *= w - lsp[j - 1]; p *= w - lsp[j]; } p *= p * (2.0f - w); q *= q * (2.0f + w); v = p + q; v = pow_m1_4(s, v); if (v > val_max) val_max = v; out[i] = v; } *val_max_ptr = val_max; } /** * decode exponents coded with LSP coefficients (same idea as Vorbis) */ static void decode_exp_lsp(WMACodecContext *s, int ch) { float lsp_coefs[NB_LSP_COEFS]; int val, i; for(i = 0; i < NB_LSP_COEFS; i++) { if (i == 0 || i >= 8) val = get_bits(&s->gb, 3); else val = get_bits(&s->gb, 4); lsp_coefs[i] = ff_wma_lsp_codebook[i][val]; } wma_lsp_to_curve(s, s->exponents[ch], &s->max_exponent[ch], s->block_len, lsp_coefs); } /** pow(10, i / 16.0) for i in -60..67 */ static const float pow_tab[128] = { 1.7782794100389e-04, 2.0535250264571e-04, 2.3713737056617e-04, 2.7384196342644e-04, 3.1622776601684e-04, 3.6517412725484e-04, 4.2169650342858e-04, 4.8696752516586e-04, 5.6234132519035e-04, 6.4938163157621e-04, 7.4989420933246e-04, 8.6596432336006e-04, 1.0000000000000e-03, 1.1547819846895e-03, 1.3335214321633e-03, 1.5399265260595e-03, 1.7782794100389e-03, 2.0535250264571e-03, 2.3713737056617e-03, 2.7384196342644e-03, 3.1622776601684e-03, 3.6517412725484e-03, 4.2169650342858e-03, 4.8696752516586e-03, 5.6234132519035e-03, 6.4938163157621e-03, 7.4989420933246e-03, 8.6596432336006e-03, 1.0000000000000e-02, 1.1547819846895e-02, 1.3335214321633e-02, 1.5399265260595e-02, 1.7782794100389e-02, 2.0535250264571e-02, 2.3713737056617e-02, 2.7384196342644e-02, 3.1622776601684e-02, 3.6517412725484e-02, 4.2169650342858e-02, 4.8696752516586e-02, 5.6234132519035e-02, 6.4938163157621e-02, 7.4989420933246e-02, 8.6596432336007e-02, 1.0000000000000e-01, 1.1547819846895e-01, 1.3335214321633e-01, 1.5399265260595e-01, 1.7782794100389e-01, 2.0535250264571e-01, 2.3713737056617e-01, 2.7384196342644e-01, 3.1622776601684e-01, 3.6517412725484e-01, 4.2169650342858e-01, 4.8696752516586e-01, 5.6234132519035e-01, 6.4938163157621e-01, 7.4989420933246e-01, 8.6596432336007e-01, 1.0000000000000e+00, 1.1547819846895e+00, 1.3335214321633e+00, 1.5399265260595e+00, 1.7782794100389e+00, 2.0535250264571e+00, 2.3713737056617e+00, 2.7384196342644e+00, 3.1622776601684e+00, 3.6517412725484e+00, 4.2169650342858e+00, 4.8696752516586e+00, 5.6234132519035e+00, 6.4938163157621e+00, 7.4989420933246e+00, 8.6596432336007e+00, 1.0000000000000e+01, 1.1547819846895e+01, 1.3335214321633e+01, 1.5399265260595e+01, 1.7782794100389e+01, 2.0535250264571e+01, 2.3713737056617e+01, 2.7384196342644e+01, 3.1622776601684e+01, 3.6517412725484e+01, 4.2169650342858e+01, 4.8696752516586e+01, 5.6234132519035e+01, 6.4938163157621e+01, 7.4989420933246e+01, 8.6596432336007e+01, 1.0000000000000e+02, 1.1547819846895e+02, 1.3335214321633e+02, 1.5399265260595e+02, 1.7782794100389e+02, 2.0535250264571e+02, 2.3713737056617e+02, 2.7384196342644e+02, 3.1622776601684e+02, 3.6517412725484e+02, 4.2169650342858e+02, 4.8696752516586e+02, 5.6234132519035e+02, 6.4938163157621e+02, 7.4989420933246e+02, 8.6596432336007e+02, 1.0000000000000e+03, 1.1547819846895e+03, 1.3335214321633e+03, 1.5399265260595e+03, 1.7782794100389e+03, 2.0535250264571e+03, 2.3713737056617e+03, 2.7384196342644e+03, 3.1622776601684e+03, 3.6517412725484e+03, 4.2169650342858e+03, 4.8696752516586e+03, 5.6234132519035e+03, 6.4938163157621e+03, 7.4989420933246e+03, 8.6596432336007e+03, 1.0000000000000e+04, 1.1547819846895e+04, 1.3335214321633e+04, 1.5399265260595e+04, }; /** * decode exponents coded with VLC codes */ static int decode_exp_vlc(WMACodecContext *s, int ch) { int last_exp, n, code; const uint16_t *ptr; float v, max_scale; uint32_t *q, *q_end, iv; const float *ptab = pow_tab + 60; const uint32_t *iptab = (const uint32_t*)ptab; ptr = s->exponent_bands[s->frame_len_bits - s->block_len_bits]; q = (uint32_t *)s->exponents[ch]; q_end = q + s->block_len; max_scale = 0; if (s->version == 1) { last_exp = get_bits(&s->gb, 5) + 10; v = ptab[last_exp]; iv = iptab[last_exp]; max_scale = v; n = *ptr++; switch (n & 3) do { case 0: *q++ = iv; case 3: *q++ = iv; case 2: *q++ = iv; case 1: *q++ = iv; } while ((n -= 4) > 0); }else last_exp = 36; while (q < q_end) { code = get_vlc2(&s->gb, s->exp_vlc.table, EXPVLCBITS, EXPMAX); if (code < 0) return -1; /* NOTE: this offset is the same as MPEG4 AAC ! */ last_exp += code - 60; if ((unsigned)last_exp + 60 > FF_ARRAY_ELEMS(pow_tab)) return -1; v = ptab[last_exp]; iv = iptab[last_exp]; if (v > max_scale) max_scale = v; n = *ptr++; switch (n & 3) do { case 0: *q++ = iv; case 3: *q++ = iv; case 2: *q++ = iv; case 1: *q++ = iv; } while ((n -= 4) > 0); } s->max_exponent[ch] = max_scale; return 0; } /** * Apply MDCT window and add into output. * * We ensure that when the windows overlap their squared sum * is always 1 (MDCT reconstruction rule). */ static void wma_window(WMACodecContext *s, float *out) { float *in = s->output; int block_len, bsize, n; /* left part */ if (s->block_len_bits <= s->prev_block_len_bits) { block_len = s->block_len; bsize = s->frame_len_bits - s->block_len_bits; s->dsp.vector_fmul_add(out, in, s->windows[bsize], out, block_len); } else { block_len = 1 << s->prev_block_len_bits; n = (s->block_len - block_len) / 2; bsize = s->frame_len_bits - s->prev_block_len_bits; s->dsp.vector_fmul_add(out+n, in+n, s->windows[bsize], out+n, block_len); memcpy(out+n+block_len, in+n+block_len, n*sizeof(float)); } out += s->block_len; in += s->block_len; /* right part */ if (s->block_len_bits <= s->next_block_len_bits) { block_len = s->block_len; bsize = s->frame_len_bits - s->block_len_bits; s->dsp.vector_fmul_reverse(out, in, s->windows[bsize], block_len); } else { block_len = 1 << s->next_block_len_bits; n = (s->block_len - block_len) / 2; bsize = s->frame_len_bits - s->next_block_len_bits; memcpy(out, in, n*sizeof(float)); s->dsp.vector_fmul_reverse(out+n, in+n, s->windows[bsize], block_len); memset(out+n+block_len, 0, n*sizeof(float)); } } /** * @return 0 if OK. 1 if last block of frame. return -1 if * unrecorrable error. */ static int wma_decode_block(WMACodecContext *s) { int n, v, a, ch, bsize; int coef_nb_bits, total_gain; int nb_coefs[MAX_CHANNELS]; float mdct_norm; #ifdef TRACE tprintf(s->avctx, "***decode_block: %d:%d\n", s->frame_count - 1, s->block_num); #endif /* compute current block length */ if (s->use_variable_block_len) { n = av_log2(s->nb_block_sizes - 1) + 1; if (s->reset_block_lengths) { s->reset_block_lengths = 0; v = get_bits(&s->gb, n); if (v >= s->nb_block_sizes) return -1; s->prev_block_len_bits = s->frame_len_bits - v; v = get_bits(&s->gb, n); if (v >= s->nb_block_sizes) return -1; s->block_len_bits = s->frame_len_bits - v; } else { /* update block lengths */ s->prev_block_len_bits = s->block_len_bits; s->block_len_bits = s->next_block_len_bits; } v = get_bits(&s->gb, n); if (v >= s->nb_block_sizes) return -1; s->next_block_len_bits = s->frame_len_bits - v; } else { /* fixed block len */ s->next_block_len_bits = s->frame_len_bits; s->prev_block_len_bits = s->frame_len_bits; s->block_len_bits = s->frame_len_bits; } /* now check if the block length is coherent with the frame length */ s->block_len = 1 << s->block_len_bits; if ((s->block_pos + s->block_len) > s->frame_len) return -1; if (s->nb_channels == 2) { s->ms_stereo = get_bits1(&s->gb); } v = 0; for(ch = 0; ch < s->nb_channels; ch++) { a = get_bits1(&s->gb); s->channel_coded[ch] = a; v |= a; } bsize = s->frame_len_bits - s->block_len_bits; /* if no channel coded, no need to go further */ /* XXX: fix potential framing problems */ if (!v) goto next; /* read total gain and extract corresponding number of bits for coef escape coding */ total_gain = 1; for(;;) { a = get_bits(&s->gb, 7); total_gain += a; if (a != 127) break; } coef_nb_bits= ff_wma_total_gain_to_bits(total_gain); /* compute number of coefficients */ n = s->coefs_end[bsize] - s->coefs_start; for(ch = 0; ch < s->nb_channels; ch++) nb_coefs[ch] = n; /* complex coding */ if (s->use_noise_coding) { for(ch = 0; ch < s->nb_channels; ch++) { if (s->channel_coded[ch]) { int i, n, a; n = s->exponent_high_sizes[bsize]; for(i=0;i<n;i++) { a = get_bits1(&s->gb); s->high_band_coded[ch][i] = a; /* if noise coding, the coefficients are not transmitted */ if (a) nb_coefs[ch] -= s->exponent_high_bands[bsize][i]; } } } for(ch = 0; ch < s->nb_channels; ch++) { if (s->channel_coded[ch]) { int i, n, val, code; n = s->exponent_high_sizes[bsize]; val = (int)0x80000000; for(i=0;i<n;i++) { if (s->high_band_coded[ch][i]) { if (val == (int)0x80000000) { val = get_bits(&s->gb, 7) - 19; } else { code = get_vlc2(&s->gb, s->hgain_vlc.table, HGAINVLCBITS, HGAINMAX); if (code < 0) return -1; val += code - 18; } s->high_band_values[ch][i] = val; } } } } } /* exponents can be reused in short blocks. */ if ((s->block_len_bits == s->frame_len_bits) || get_bits1(&s->gb)) { for(ch = 0; ch < s->nb_channels; ch++) { if (s->channel_coded[ch]) { if (s->use_exp_vlc) { if (decode_exp_vlc(s, ch) < 0) return -1; } else { decode_exp_lsp(s, ch); } s->exponents_bsize[ch] = bsize; } } } /* parse spectral coefficients : just RLE encoding */ for(ch = 0; ch < s->nb_channels; ch++) { if (s->channel_coded[ch]) { int tindex; WMACoef* 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); memset(ptr, 0, s->block_len * sizeof(WMACoef)); 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); } } /* normalize */ { int n4 = s->block_len / 2; mdct_norm = 1.0 / (float)n4; if (s->version == 1) { mdct_norm *= sqrt(n4); } } /* finally compute the MDCT coefficients */ for(ch = 0; ch < s->nb_channels; ch++) { if (s->channel_coded[ch]) { WMACoef *coefs1; float *coefs, *exponents, mult, mult1, noise; int i, j, n, n1, last_high_band, esize; float exp_power[HIGH_BAND_MAX_SIZE]; coefs1 = s->coefs1[ch]; exponents = s->exponents[ch]; esize = s->exponents_bsize[ch]; mult = pow(10, total_gain * 0.05) / s->max_exponent[ch]; mult *= mdct_norm; coefs = s->coefs[ch]; if (s->use_noise_coding) { mult1 = mult; /* very low freqs : noise */ for(i = 0;i < s->coefs_start; i++) { *coefs++ = s->noise_table[s->noise_index] * exponents[i<<bsize>>esize] * mult1; s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); } n1 = s->exponent_high_sizes[bsize]; /* compute power of high bands */ exponents = s->exponents[ch] + (s->high_band_start[bsize]<<bsize); last_high_band = 0; /* avoid warning */ for(j=0;j<n1;j++) { n = s->exponent_high_bands[s->frame_len_bits - s->block_len_bits][j]; if (s->high_band_coded[ch][j]) { float e2, v; e2 = 0; for(i = 0;i < n; i++) { v = exponents[i<<bsize>>esize]; e2 += v * v; } exp_power[j] = e2 / n; last_high_band = j; tprintf(s->avctx, "%d: power=%f (%d)\n", j, exp_power[j], n); } exponents += n<<bsize; } /* main freqs and high freqs */ exponents = s->exponents[ch] + (s->coefs_start<<bsize); for(j=-1;j<n1;j++) { if (j < 0) { n = s->high_band_start[bsize] - s->coefs_start; } else { n = s->exponent_high_bands[s->frame_len_bits - s->block_len_bits][j]; } if (j >= 0 && s->high_band_coded[ch][j]) { /* use noise with specified power */ mult1 = sqrt(exp_power[j] / exp_power[last_high_band]); /* XXX: use a table */ mult1 = mult1 * pow(10, s->high_band_values[ch][j] * 0.05); mult1 = mult1 / (s->max_exponent[ch] * s->noise_mult); mult1 *= mdct_norm; for(i = 0;i < n; i++) { noise = s->noise_table[s->noise_index]; s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); *coefs++ = noise * exponents[i<<bsize>>esize] * mult1; } exponents += n<<bsize; } else { /* coded values + small noise */ for(i = 0;i < n; i++) { noise = s->noise_table[s->noise_index]; s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); *coefs++ = ((*coefs1++) + noise) * exponents[i<<bsize>>esize] * mult; } exponents += n<<bsize; } } /* very high freqs : noise */ n = s->block_len - s->coefs_end[bsize]; mult1 = mult * exponents[((-1<<bsize))>>esize]; for(i = 0; i < n; i++) { *coefs++ = s->noise_table[s->noise_index] * mult1; s->noise_index = (s->noise_index + 1) & (NOISE_TAB_SIZE - 1); } } else { /* XXX: optimize more */ for(i = 0;i < s->coefs_start; i++) *coefs++ = 0.0; n = nb_coefs[ch]; for(i = 0;i < n; i++) { *coefs++ = coefs1[i] * exponents[i<<bsize>>esize] * mult; } n = s->block_len - s->coefs_end[bsize]; for(i = 0;i < n; i++) *coefs++ = 0.0; } } } #ifdef TRACE for(ch = 0; ch < s->nb_channels; ch++) { if (s->channel_coded[ch]) { dump_floats(s, "exponents", 3, s->exponents[ch], s->block_len); dump_floats(s, "coefs", 1, s->coefs[ch], s->block_len); } } #endif if (s->ms_stereo && s->channel_coded[1]) { /* nominal case for ms stereo: we do it before mdct */ /* no need to optimize this case because it should almost never happen */ if (!s->channel_coded[0]) { tprintf(s->avctx, "rare ms-stereo case happened\n"); memset(s->coefs[0], 0, sizeof(float) * s->block_len); s->channel_coded[0] = 1; } s->dsp.butterflies_float(s->coefs[0], s->coefs[1], s->block_len); } next: for(ch = 0; ch < s->nb_channels; ch++) { int n4, index; n4 = s->block_len / 2; if(s->channel_coded[ch]){ ff_imdct_calc(&s->mdct_ctx[bsize], s->output, s->coefs[ch]); }else if(!(s->ms_stereo && ch==1)) memset(s->output, 0, sizeof(s->output)); /* multiply by the window and add in the frame */ index = (s->frame_len / 2) + s->block_pos - n4; wma_window(s, &s->frame_out[ch][index]); } /* update block number */ s->block_num++; s->block_pos += s->block_len; if (s->block_pos >= s->frame_len) return 1; else return 0; } /* decode a frame of frame_len samples */ static int wma_decode_frame(WMACodecContext *s, int16_t *samples) { int ret, i, n, ch, incr; int16_t *ptr; float *iptr; #ifdef TRACE tprintf(s->avctx, "***decode_frame: %d size=%d\n", s->frame_count++, s->frame_len); #endif /* read each block */ s->block_num = 0; s->block_pos = 0; for(;;) { ret = wma_decode_block(s); if (ret < 0) return -1; if (ret) break; } /* convert frame to integer */ n = s->frame_len; incr = s->nb_channels; for(ch = 0; ch < s->nb_channels; ch++) { ptr = samples + ch; iptr = s->frame_out[ch]; for(i=0;i<n;i++) { *ptr = av_clip_int16(lrintf(*iptr++)); ptr += incr; } /* prepare for next block */ memmove(&s->frame_out[ch][0], &s->frame_out[ch][s->frame_len], s->frame_len * sizeof(float)); } #ifdef TRACE dump_shorts(s, "samples", samples, n * s->nb_channels); #endif return 0; } static int wma_decode_superframe(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; WMACodecContext *s = avctx->priv_data; int nb_frames, bit_offset, i, pos, len; uint8_t *q; int16_t *samples; tprintf(avctx, "***decode_superframe:\n"); if(buf_size==0){ s->last_superframe_len = 0; return 0; } if (buf_size < s->block_align) return 0; buf_size = s->block_align; samples = data; init_get_bits(&s->gb, buf, buf_size*8); if (s->use_bit_reservoir) { /* read super frame header */ skip_bits(&s->gb, 4); /* super frame index */ nb_frames = get_bits(&s->gb, 4) - 1; if((nb_frames+1) * s->nb_channels * s->frame_len * sizeof(int16_t) > *data_size){ av_log(s->avctx, AV_LOG_ERROR, "Insufficient output space\n"); goto fail; } bit_offset = get_bits(&s->gb, s->byte_offset_bits + 3); if (s->last_superframe_len > 0) { // printf("skip=%d\n", s->last_bitoffset); /* add bit_offset bits to last frame */ if ((s->last_superframe_len + ((bit_offset + 7) >> 3)) > MAX_CODED_SUPERFRAME_SIZE) goto fail; q = s->last_superframe + s->last_superframe_len; len = bit_offset; while (len > 7) { *q++ = (get_bits)(&s->gb, 8); len -= 8; } if (len > 0) { *q++ = (get_bits)(&s->gb, len) << (8 - len); } /* XXX: bit_offset bits into last frame */ init_get_bits(&s->gb, s->last_superframe, MAX_CODED_SUPERFRAME_SIZE*8); /* skip unused bits */ if (s->last_bitoffset > 0) skip_bits(&s->gb, s->last_bitoffset); /* this frame is stored in the last superframe and in the current one */ if (wma_decode_frame(s, samples) < 0) goto fail; samples += s->nb_channels * s->frame_len; } /* read each frame starting from bit_offset */ pos = bit_offset + 4 + 4 + s->byte_offset_bits + 3; init_get_bits(&s->gb, buf + (pos >> 3), (MAX_CODED_SUPERFRAME_SIZE - (pos >> 3))*8); len = pos & 7; if (len > 0) skip_bits(&s->gb, len); s->reset_block_lengths = 1; for(i=0;i<nb_frames;i++) { if (wma_decode_frame(s, samples) < 0) goto fail; samples += s->nb_channels * s->frame_len; } /* we copy the end of the frame in the last frame buffer */ pos = get_bits_count(&s->gb) + ((bit_offset + 4 + 4 + s->byte_offset_bits + 3) & ~7); s->last_bitoffset = pos & 7; pos >>= 3; len = buf_size - pos; if (len > MAX_CODED_SUPERFRAME_SIZE || len < 0) { goto fail; } s->last_superframe_len = len; memcpy(s->last_superframe, buf + pos, len); } else { if(s->nb_channels * s->frame_len * sizeof(int16_t) > *data_size){ av_log(s->avctx, AV_LOG_ERROR, "Insufficient output space\n"); goto fail; } /* single frame decode */ if (wma_decode_frame(s, samples) < 0) goto fail; samples += s->nb_channels * s->frame_len; } //av_log(NULL, AV_LOG_ERROR, "%d %d %d %d outbytes:%d eaten:%d\n", s->frame_len_bits, s->block_len_bits, s->frame_len, s->block_len, (int8_t *)samples - (int8_t *)data, s->block_align); *data_size = (int8_t *)samples - (int8_t *)data; return s->block_align; fail: /* when error, we reset the bit reservoir */ s->last_superframe_len = 0; return -1; } AVCodec wmav1_decoder = { "wmav1", CODEC_TYPE_AUDIO, CODEC_ID_WMAV1, sizeof(WMACodecContext), wma_decode_init, NULL, ff_wma_end, wma_decode_superframe, .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 1"), }; AVCodec wmav2_decoder = { "wmav2", CODEC_TYPE_AUDIO, CODEC_ID_WMAV2, sizeof(WMACodecContext), wma_decode_init, NULL, ff_wma_end, wma_decode_superframe, .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 2"), };