]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/wmaprodec.c
WMAL: Shift output samples by the specified number of padding zeroes.
[ffmpeg] / libavcodec / wmaprodec.c
index f96e4dbed3d71a7126f10b51f0e8aabd18242803..30a43c85859b3b8432f4604f9c40ccfafe8bae0e 100644 (file)
@@ -1,27 +1,27 @@
 /*
  * Wmapro compatible decoder
  * Copyright (c) 2007 Baptiste Coudurier, Benjamin Larsson, Ulion
- * Copyright (c) 2008 - 2009 Sascha Sommer, Benjamin Larsson
+ * Copyright (c) 2008 - 2011 Sascha Sommer, Benjamin Larsson
  *
- * This file is part of FFmpeg.
+ * This file is part of Libav.
  *
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav 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,
+ * Libav 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
+ * License along with Libav; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 /**
- * @file  libavcodec/wmaprodec.c
+ * @file
  * @brief wmapro decoder implementation
  * Wmapro is an MDCT based codec comparable to wma standard or AAC.
  * The decoding therefore consists of the following steps:
  * subframe in order to reconstruct the output samples.
  */
 
+#include "libavutil/intfloat.h"
+#include "libavutil/intreadwrite.h"
 #include "avcodec.h"
 #include "internal.h"
 #include "get_bits.h"
 #include "put_bits.h"
 #include "wmaprodata.h"
 #include "dsputil.h"
+#include "fmtconvert.h"
+#include "sinewin.h"
 #include "wma.h"
+#include "wma_common.h"
 
 /** current decoder limitations */
 #define WMAPRO_MAX_CHANNELS    8                             ///< max number of handled channels
 #define MAX_SUBFRAMES  32                                    ///< max number of subframes per channel
 #define MAX_BANDS      29                                    ///< max number of scale factor bands
-#define MAX_FRAMESIZE  16384                                 ///< maximum compressed frame size
+#define MAX_FRAMESIZE  32768                                 ///< maximum compressed frame size
 
-#define WMAPRO_BLOCK_MAX_BITS 12                                           ///< log2 of max block size
+#define WMAPRO_BLOCK_MIN_BITS  6                                           ///< log2 of min block size
+#define WMAPRO_BLOCK_MAX_BITS 13                                           ///< log2 of max block size
 #define WMAPRO_BLOCK_MAX_SIZE (1 << WMAPRO_BLOCK_MAX_BITS)                 ///< maximum block size
-#define WMAPRO_BLOCK_SIZES    (WMAPRO_BLOCK_MAX_BITS - BLOCK_MIN_BITS + 1) ///< possible block sizes
+#define WMAPRO_BLOCK_SIZES    (WMAPRO_BLOCK_MAX_BITS - WMAPRO_BLOCK_MIN_BITS + 1) ///< possible block sizes
 
 
 #define VLCBITS            9
@@ -137,11 +143,13 @@ typedef struct {
     int8_t   reuse_sf;                                ///< share scale factors between subframes
     int8_t   scale_factor_step;                       ///< scaling step for the current subframe
     int      max_scale_factor;                        ///< maximum scale factor for the current subframe
-    int      scale_factors[MAX_BANDS];                ///< scale factor values for the current subframe
-    int      saved_scale_factors[MAX_BANDS];          ///< scale factors from a previous subframe
+    int      saved_scale_factors[2][MAX_BANDS];       ///< resampled and (previously) transmitted scale factor values
+    int8_t   scale_factor_idx;                        ///< index for the transmitted scale factor values (used for resampling)
+    int*     scale_factors;                           ///< pointer to the scale factor values used for decoding
     uint8_t  table_idx;                               ///< index in sf_offsets for the scale factor reference block
     float*   coeffs;                                  ///< pointer to the subframe decode buffer
-    DECLARE_ALIGNED_16(float, out[WMAPRO_BLOCK_MAX_SIZE + WMAPRO_BLOCK_MAX_SIZE / 2]); ///< output buffer
+    uint16_t num_vec_coeffs;                          ///< number of vector coded coefficients
+    DECLARE_ALIGNED(32, float, out)[WMAPRO_BLOCK_MAX_SIZE + WMAPRO_BLOCK_MAX_SIZE / 2]; ///< output buffer
 } WMAProChannelCtx;
 
 /**
@@ -161,12 +169,14 @@ typedef struct {
 typedef struct WMAProDecodeCtx {
     /* generic decoder variables */
     AVCodecContext*  avctx;                         ///< codec context for av_log
+    AVFrame          frame;                         ///< AVFrame for decoded output
     DSPContext       dsp;                           ///< accelerated DSP functions
+    FmtConvertContext fmt_conv;
     uint8_t          frame_data[MAX_FRAMESIZE +
                       FF_INPUT_BUFFER_PADDING_SIZE];///< compressed frame data
     PutBitContext    pb;                            ///< context for filling the frame_data buffer
-    MDCTContext      mdct_ctx[WMAPRO_BLOCK_SIZES];  ///< MDCT context per block size
-    DECLARE_ALIGNED_16(float, tmp[WMAPRO_BLOCK_MAX_SIZE]); ///< IMDCT output buffer
+    FFTContext       mdct_ctx[WMAPRO_BLOCK_SIZES];  ///< MDCT context per block size
+    DECLARE_ALIGNED(32, float, tmp)[WMAPRO_BLOCK_MAX_SIZE]; ///< IMDCT output buffer
     float*           windows[WMAPRO_BLOCK_SIZES];   ///< windows for the different block sizes
 
     /* frame size dependent frame information (set during initialization) */
@@ -188,18 +198,20 @@ typedef struct WMAProDecodeCtx {
     int16_t          subwoofer_cutoffs[WMAPRO_BLOCK_SIZES]; ///< subwoofer cutoff values
 
     /* packet decode state */
+    GetBitContext    pgb;                           ///< bitstream reader context for the packet
+    int              next_packet_start;             ///< start offset of the next wma packet in the demuxer packet
+    uint8_t          packet_offset;                 ///< frame offset in the packet
     uint8_t          packet_sequence_number;        ///< current packet number
     int              num_saved_bits;                ///< saved number of bits
     int              frame_offset;                  ///< frame offset in the bit reservoir
     int              subframe_offset;               ///< subframe offset in the bit reservoir
     uint8_t          packet_loss;                   ///< set in case of bitstream error
+    uint8_t          packet_done;                   ///< set when a packet is fully decoded
 
     /* frame decode state */
     uint32_t         frame_num;                     ///< current frame number (not used for decoding)
     GetBitContext    gb;                            ///< bitstream reader context
     int              buf_bit_size;                  ///< buffer size in bits
-    float*           samples;                       ///< current samplebuffer pointer
-    float*           samples_end;                   ///< maximum samplebuffer pointer
     uint8_t          drc_gain;                      ///< gain for the DRC tool
     int8_t           skip_frame;                    ///< skip output step
     int8_t           parsed_all_subframes;          ///< all subframes decoded?
@@ -209,6 +221,7 @@ typedef struct WMAProDecodeCtx {
     int8_t           channels_for_cur_subframe;     ///< number of channels that contain the subframe
     int8_t           channel_indexes_for_cur_subframe[WMAPRO_MAX_CHANNELS];
     int8_t           num_bands;                     ///< number of scale factor bands
+    int8_t           transmit_num_vec_coeffs;       ///< number of vector coded coefficients is part of the bitstream
     int16_t*         cur_sfb_offsets;               ///< sfb offsets for the current block
     uint8_t          table_idx;                     ///< index for the num_sfb, sfb_offsets, sf_offsets and subwoofer_cutoffs tables
     int8_t           esc_len;                       ///< length of escaped coefficients
@@ -224,7 +237,7 @@ typedef struct WMAProDecodeCtx {
  *@brief helper function to print the most important members of the context
  *@param s context
  */
-static void av_cold dump_context(WMAProDecodeCtx *s)
+static av_cold void dump_context(WMAProDecodeCtx *s)
 {
 #define PRINT(a, b)     av_log(s->avctx, AV_LOG_DEBUG, " %s = %d\n", a, b);
 #define PRINT_HEX(a, b) av_log(s->avctx, AV_LOG_DEBUG, " %s = %x\n", a, b);
@@ -262,17 +275,18 @@ static av_cold int decode_end(AVCodecContext *avctx)
 static av_cold int decode_init(AVCodecContext *avctx)
 {
     WMAProDecodeCtx *s = avctx->priv_data;
-    uint8_t *edata_ptr   = avctx->extradata;
+    uint8_t *edata_ptr = avctx->extradata;
     unsigned int channel_mask;
-    int i;
+    int i, bits;
     int log2_max_num_subframes;
     int num_possible_block_sizes;
 
     s->avctx = avctx;
-    dsputil_init(&s->dsp, avctx);
+    ff_dsputil_init(&s->dsp, avctx);
+    ff_fmt_convert_init(&s->fmt_conv, avctx);
     init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
 
-    avctx->sample_fmt = SAMPLE_FMT_FLT;
+    avctx->sample_fmt = AV_SAMPLE_FMT_FLT;
 
     if (avctx->extradata_size >= 18) {
         s->decode_flags    = AV_RL16(edata_ptr+14);
@@ -280,8 +294,8 @@ static av_cold int decode_init(AVCodecContext *avctx)
         s->bits_per_sample = AV_RL16(edata_ptr);
         /** dump the extradata */
         for (i = 0; i < avctx->extradata_size; i++)
-            dprintf(avctx, "[%x] ", avctx->extradata[i]);
-        dprintf(avctx, "\n");
+            av_dlog(avctx, "[%x] ", avctx->extradata[i]);
+        av_dlog(avctx, "\n");
 
     } else {
         av_log_ask_for_sample(avctx, "Unknown extradata size\n");
@@ -292,27 +306,22 @@ static av_cold int decode_init(AVCodecContext *avctx)
     s->log2_frame_size = av_log2(avctx->block_align) + 4;
 
     /** frame info */
-    s->skip_frame  = 1; /** skip first frame */
+    s->skip_frame  = 1; /* skip first frame */
     s->packet_loss = 1;
     s->len_prefix  = (s->decode_flags & 0x40);
 
-    if (!s->len_prefix) {
-        av_log_ask_for_sample(avctx, "no length prefix\n");
+    /** get frame len */
+    bits = ff_wma_get_frame_len_bits(avctx->sample_rate, 3, s->decode_flags);
+    if (bits > WMAPRO_BLOCK_MAX_BITS) {
+        av_log_missing_feature(avctx, "14-bits block sizes", 1);
         return AVERROR_INVALIDDATA;
     }
-
-    /** get frame len */
-    s->samples_per_frame = 1 << ff_wma_get_frame_len_bits(avctx->sample_rate,
-                                                          3, s->decode_flags);
-
-    /** init previous block len */
-    for (i = 0; i < avctx->channels; i++)
-        s->channel[i].prev_block_len = s->samples_per_frame;
+    s->samples_per_frame = 1 << bits;
 
     /** subframe info */
     log2_max_num_subframes       = ((s->decode_flags & 0x38) >> 3);
     s->max_num_subframes         = 1 << log2_max_num_subframes;
-    if (s->max_num_subframes == 16)
+    if (s->max_num_subframes == 16 || s->max_num_subframes == 4)
         s->max_subframe_len_bit = 1;
     s->subframe_len_bits = av_log2(log2_max_num_subframes) + 1;
 
@@ -328,6 +337,18 @@ static av_cold int decode_init(AVCodecContext *avctx)
 
     s->num_channels = avctx->channels;
 
+    if (s->num_channels < 0) {
+        av_log(avctx, AV_LOG_ERROR, "invalid number of channels %d\n", s->num_channels);
+        return AVERROR_INVALIDDATA;
+    } else if (s->num_channels > WMAPRO_MAX_CHANNELS) {
+        av_log_ask_for_sample(avctx, "unsupported number of channels\n");
+        return AVERROR_PATCHWELCOME;
+    }
+
+    /** init previous block len */
+    for (i = 0; i < s->num_channels; i++)
+        s->channel[i].prev_block_len = s->samples_per_frame;
+
     /** extract lfe channel position */
     s->lfe_channel = -1;
 
@@ -339,11 +360,6 @@ static av_cold int decode_init(AVCodecContext *avctx)
         }
     }
 
-    if (s->num_channels < 0 || s->num_channels > WMAPRO_MAX_CHANNELS) {
-        av_log_ask_for_sample(avctx, "invalid number of channels\n");
-        return AVERROR_NOTSUPP;
-    }
-
     INIT_VLC_STATIC(&sf_vlc, SCALEVLCBITS, HUFF_SCALE_SIZE,
                     scale_huffbits, 1, 1,
                     scale_huffcodes, 2, 2, 616);
@@ -381,11 +397,11 @@ static av_cold int decode_init(AVCodecContext *avctx)
 
         s->sfb_offsets[i][0] = 0;
 
-        for (x = 0; x < MAX_BANDS-1 && s->sfb_offsets[i][band-1] < subframe_len; x++) {
+        for (x = 0; x < MAX_BANDS-1 && s->sfb_offsets[i][band - 1] < subframe_len; x++) {
             int offset = (subframe_len * 2 * critical_freq[x])
                           / s->avctx->sample_rate + 2;
             offset &= ~3;
-            if ( offset > s->sfb_offsets[i][band - 1] )
+            if (offset > s->sfb_offsets[i][band - 1])
                 s->sfb_offsets[i][band++] = offset;
         }
         s->sfb_offsets[i][band - 1] = subframe_len;
@@ -403,7 +419,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
         for (b = 0; b < s->num_sfb[i]; b++) {
             int x;
             int offset = ((s->sfb_offsets[i][b]
-                         + s->sfb_offsets[i][b + 1] - 1)<<i) >> 1;
+                           + s->sfb_offsets[i][b + 1] - 1) << i) >> 1;
             for (x = 0; x < num_possible_block_sizes; x++) {
                 int v = 0;
                 while (s->sfb_offsets[x][v + 1] << x < offset)
@@ -415,16 +431,15 @@ static av_cold int decode_init(AVCodecContext *avctx)
 
     /** init MDCT, FIXME: only init needed sizes */
     for (i = 0; i < WMAPRO_BLOCK_SIZES; i++)
-        ff_mdct_init(&s->mdct_ctx[i], BLOCK_MIN_BITS+1+i, 1,
-                     1.0 / (1 <<(BLOCK_MIN_BITS + i - 1))
+        ff_mdct_init(&s->mdct_ctx[i], WMAPRO_BLOCK_MIN_BITS+1+i, 1,
+                     1.0 / (1 << (WMAPRO_BLOCK_MIN_BITS + i - 1))
                      / (1 << (s->bits_per_sample - 1)));
 
     /** init MDCT windows: simple sinus window */
     for (i = 0; i < WMAPRO_BLOCK_SIZES; i++) {
-        const int n       = 1 << (WMAPRO_BLOCK_MAX_BITS - i);
-        const int win_idx = WMAPRO_BLOCK_MAX_BITS - i - 7;
-        ff_sine_window_init(ff_sine_windows[win_idx], n);
-        s->windows[WMAPRO_BLOCK_SIZES-i-1] = ff_sine_windows[win_idx];
+        const int win_idx = WMAPRO_BLOCK_MAX_BITS - i;
+        ff_init_ff_sine_windows(win_idx);
+        s->windows[WMAPRO_BLOCK_SIZES - i - 1] = ff_sine_windows[win_idx];
     }
 
     /** calculate subwoofer cutoff values */
@@ -443,6 +458,10 @@ static av_cold int decode_init(AVCodecContext *avctx)
         dump_context(s);
 
     avctx->channel_layout = channel_mask;
+
+    avcodec_get_frame_defaults(&s->frame);
+    avctx->coded_frame = &s->frame;
+
     return 0;
 }
 
@@ -471,8 +490,8 @@ static int decode_subframe_length(WMAProDecodeCtx *s, int offset)
     subframe_len = s->samples_per_frame >> frame_len_shift;
 
     /** sanity check the length */
-    if (subframe_len < s->min_samples_per_subframe
-              || subframe_len > s->samples_per_frame) {
+    if (subframe_len < s->min_samples_per_subframe ||
+        subframe_len > s->samples_per_frame) {
         av_log(s->avctx, AV_LOG_ERROR, "broken frame: subframe_len %i\n",
                subframe_len);
         return AVERROR_INVALIDDATA;
@@ -502,11 +521,11 @@ static int decode_subframe_length(WMAProDecodeCtx *s, int offset)
  */
 static int decode_tilehdr(WMAProDecodeCtx *s)
 {
-    uint16_t num_samples[WMAPRO_MAX_CHANNELS];        /** sum of samples for all currently known subframes of a channel */
-    uint8_t  contains_subframe[WMAPRO_MAX_CHANNELS];  /** flag indicating if a channel contains the current subframe */
-    int channels_for_cur_subframe = s->num_channels;  /** number of channels that contain the current subframe */
-    int fixed_channel_layout = 0;                     /** flag indicating that all channels use the same subframe offsets and sizes */
-    int min_channel_len = 0;                          /** smallest sum of samples (channels with this length will be processed first) */
+    uint16_t num_samples[WMAPRO_MAX_CHANNELS] = { 0 };/**< sum of samples for all currently known subframes of a channel */
+    uint8_t  contains_subframe[WMAPRO_MAX_CHANNELS];  /**< flag indicating if a channel contains the current subframe */
+    int channels_for_cur_subframe = s->num_channels;  /**< number of channels that contain the current subframe */
+    int fixed_channel_layout = 0;                     /**< flag indicating that all channels use the same subframe offsets and sizes */
+    int min_channel_len = 0;                          /**< smallest sum of samples (channels with this length will be processed first) */
     int c;
 
     /* Should never consume more than 3073 bits (256 iterations for the
@@ -519,8 +538,6 @@ static int decode_tilehdr(WMAProDecodeCtx *s)
     for (c = 0; c < s->num_channels; c++)
         s->channel[c].num_subframes = 0;
 
-    memset(num_samples, 0, sizeof(num_samples));
-
     if (s->max_num_subframes == 1 || get_bits1(&s->gb))
         fixed_channel_layout = 1;
 
@@ -559,11 +576,11 @@ static int decode_tilehdr(WMAProDecodeCtx *s)
                 num_samples[c] += subframe_len;
                 ++chan->num_subframes;
                 if (num_samples[c] > s->samples_per_frame) {
-                    av_log(s->avctx, AV_LOG_ERROR,"broken frame: "
+                    av_log(s->avctx, AV_LOG_ERROR, "broken frame: "
                            "channel len > samples_per_frame\n");
                     return AVERROR_INVALIDDATA;
                 }
-            } else if(num_samples[c] <= min_channel_len) {
+            } else if (num_samples[c] <= min_channel_len) {
                 if (num_samples[c] < min_channel_len) {
                     channels_for_cur_subframe = 0;
                     min_channel_len = num_samples[c];
@@ -577,8 +594,9 @@ static int decode_tilehdr(WMAProDecodeCtx *s)
         int i;
         int offset = 0;
         for (i = 0; i < s->channel[c].num_subframes; i++) {
-            dprintf(s->avctx, "frame[%i] channel[%i] subframe[%i]"
-                   " len %i\n", s->frame_num, c, i, s->channel[c].subframe_len[i]);
+            av_dlog(s->avctx, "frame[%i] channel[%i] subframe[%i]"
+                    " len %i\n", s->frame_num, c, i,
+                    s->channel[c].subframe_len[i]);
             s->channel[c].subframe_offset[i] = offset;
             offset += s->channel[c].subframe_len[i];
         }
@@ -606,7 +624,7 @@ static void decode_decorrelation_matrix(WMAProDecodeCtx *s,
 
     for (i = 0; i < chgroup->num_channels; i++)
         chgroup->decorrelation_matrix[chgroup->num_channels * i + i] =
-                                                get_bits1(&s->gb) ? 1.0 : -1.0;
+            get_bits1(&s->gb) ? 1.0 : -1.0;
 
     for (i = 1; i < chgroup->num_channels; i++) {
         int x;
@@ -621,10 +639,10 @@ static void decode_decorrelation_matrix(WMAProDecodeCtx *s,
 
                 if (n < 32) {
                     sinv = sin64[n];
-                    cosv = sin64[32-n];
+                    cosv = sin64[32 - n];
                 } else {
-                    sinv = sin64[64-n];
-                    cosv = -sin64[n-32];
+                    sinv =  sin64[64 -  n];
+                    cosv = -sin64[n  - 32];
                 }
 
                 chgroup->decorrelation_matrix[y + x * chgroup->num_channels] =
@@ -646,7 +664,7 @@ static int decode_channel_transform(WMAProDecodeCtx* s)
 {
     int i;
     /* should never consume more than 1921 bits for the 8 channel case
-     * 1 + MAX_CHANNELS * ( MAX_CHANNELS + 2 + 3 * MAX_CHANNELS * MAX_CHANNELS
+     * 1 + MAX_CHANNELS * (MAX_CHANNELS + 2 + 3 * MAX_CHANNELS * MAX_CHANNELS
      * + MAX_CHANNELS + MAX_BANDS + 1)
      */
 
@@ -662,7 +680,7 @@ static int decode_channel_transform(WMAProDecodeCtx* s)
         }
 
         for (s->num_chgroups = 0; remaining_channels &&
-            s->num_chgroups < s->channels_for_cur_subframe; s->num_chgroups++) {
+             s->num_chgroups < s->channels_for_cur_subframe; s->num_chgroups++) {
             WMAProChannelGrp* chgroup = &s->chgroup[s->num_chgroups];
             float** channel_data = chgroup->channel_data;
             chgroup->num_channels = 0;
@@ -694,7 +712,7 @@ static int decode_channel_transform(WMAProDecodeCtx* s)
                 if (get_bits1(&s->gb)) {
                     if (get_bits1(&s->gb)) {
                         av_log_ask_for_sample(s->avctx,
-                               "unsupported channel transform type\n");
+                                              "unsupported channel transform type\n");
                     }
                 } else {
                     chgroup->transform = 1;
@@ -720,12 +738,12 @@ static int decode_channel_transform(WMAProDecodeCtx* s)
                         /** FIXME: more than 6 coupled channels not supported */
                         if (chgroup->num_channels > 6) {
                             av_log_ask_for_sample(s->avctx,
-                                   "coupled channels > 6\n");
+                                                  "coupled channels > 6\n");
                         } else {
                             memcpy(chgroup->decorrelation_matrix,
-                              default_decorrelation[chgroup->num_channels],
-                              chgroup->num_channels * chgroup->num_channels *
-                              sizeof(*chgroup->decorrelation_matrix));
+                                   default_decorrelation[chgroup->num_channels],
+                                   chgroup->num_channels * chgroup->num_channels *
+                                   sizeof(*chgroup->decorrelation_matrix));
                         }
                     }
                 }
@@ -757,6 +775,15 @@ static int decode_channel_transform(WMAProDecodeCtx* s)
  */
 static int decode_coeffs(WMAProDecodeCtx *s, int c)
 {
+    /* Integers 0..15 as single-precision floats.  The table saves a
+       costly int to float conversion, and storing the values as
+       integers allows fast sign-flipping. */
+    static const uint32_t fval_tab[16] = {
+        0x00000000, 0x3f800000, 0x40000000, 0x40400000,
+        0x40800000, 0x40a00000, 0x40c00000, 0x40e00000,
+        0x41000000, 0x41100000, 0x41200000, 0x41300000,
+        0x41400000, 0x41500000, 0x41600000, 0x41700000,
+    };
     int vlctable;
     VLC* vlc;
     WMAProChannelCtx* ci = &s->channel[c];
@@ -764,9 +791,9 @@ static int decode_coeffs(WMAProDecodeCtx *s, int c)
     int cur_coeff = 0;
     int num_zeros = 0;
     const uint16_t* run;
-    const uint16_t* level;
+    const float* level;
 
-    dprintf(s->avctx, "decode coefficients for channel %i\n", c);
+    av_dlog(s->avctx, "decode coefficients for channel %i\n", c);
 
     vlctable = get_bits1(&s->gb);
     vlc = &coef_vlc[vlctable];
@@ -781,8 +808,9 @@ static int decode_coeffs(WMAProDecodeCtx *s, int c)
 
     /** 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];
+    while ((s->transmit_num_vec_coeffs || !rl_mode) &&
+           (cur_coeff + 3 < ci->num_vec_coeffs)) {
+        uint32_t vals[4];
         int i;
         unsigned int idx;
 
@@ -792,42 +820,45 @@ static int decode_coeffs(WMAProDecodeCtx *s, int c)
             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);
+                    uint32_t v0, v1;
+                    v0 = get_vlc2(&s->gb, vec1_vlc.table, VLCBITS, VEC1MAXDEPTH);
+                    if (v0 == HUFF_VEC1_SIZE - 1)
+                        v0 += ff_wma_get_large_val(&s->gb);
+                    v1 = get_vlc2(&s->gb, vec1_vlc.table, VLCBITS, VEC1MAXDEPTH);
+                    if (v1 == HUFF_VEC1_SIZE - 1)
+                        v1 += ff_wma_get_large_val(&s->gb);
+                    vals[i  ] = av_float2int(v0);
+                    vals[i+1] = av_float2int(v1);
                 } else {
-                    vals[i]   = symbol_to_vec2[idx] >> 4;
-                    vals[i+1] = symbol_to_vec2[idx] & 0xF;
+                    vals[i]   = fval_tab[symbol_to_vec2[idx] >> 4 ];
+                    vals[i+1] = fval_tab[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;
+            vals[0] = fval_tab[ symbol_to_vec4[idx] >> 12      ];
+            vals[1] = fval_tab[(symbol_to_vec4[idx] >> 8) & 0xF];
+            vals[2] = fval_tab[(symbol_to_vec4[idx] >> 4) & 0xF];
+            vals[3] = fval_tab[ 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;
+                uint32_t sign = get_bits1(&s->gb) - 1;
+                AV_WN32A(&ci->coeffs[cur_coeff], vals[i] ^ sign << 31);
                 num_zeros = 0;
             } else {
                 ci->coeffs[cur_coeff] = 0;
                 /** switch to run level mode when subframe_len / 128 zeros
-                   were found in a row */
-                rl_mode |= (++num_zeros > s->subframe_len>>8);
+                    were found in a row */
+                rl_mode |= (++num_zeros > s->subframe_len >> 8);
             }
             ++cur_coeff;
         }
     }
 
     /** decode run level coded coefficients */
-    if (rl_mode) {
+    if (cur_coeff < s->subframe_len) {
         memset(&ci->coeffs[cur_coeff], 0,
                sizeof(*ci->coeffs) * (s->subframe_len - cur_coeff));
         if (ff_wma_run_level_decode(s->avctx, &s->gb, vlc,
@@ -856,7 +887,9 @@ static int decode_scale_factors(WMAProDecodeCtx* s)
     for (i = 0; i < s->channels_for_cur_subframe; i++) {
         int c = s->channel_indexes_for_cur_subframe[i];
         int* sf;
-        int* sf_end = s->channel[c].scale_factors + s->num_bands;
+        int* sf_end;
+        s->channel[c].scale_factors = s->channel[c].saved_scale_factors[!s->channel[c].scale_factor_idx];
+        sf_end = s->channel[c].scale_factors + s->num_bands;
 
         /** resample scale factors for the new block size
          *  as the scale factors might need to be resampled several times
@@ -868,7 +901,7 @@ static int decode_scale_factors(WMAProDecodeCtx* s)
             int b;
             for (b = 0; b < s->num_bands; b++)
                 s->channel[c].scale_factors[b] =
-                                   s->channel[c].saved_scale_factors[*sf_offsets++];
+                    s->channel[c].saved_scale_factors[s->channel[c].scale_factor_idx][*sf_offsets++];
         }
 
         if (!s->channel[c].cur_subframe || get_bits1(&s->gb)) {
@@ -893,7 +926,7 @@ static int decode_scale_factors(WMAProDecodeCtx* s)
 
                     idx = get_vlc2(&s->gb, sf_rl_vlc.table, VLCBITS, SCALERLMAXDEPTH);
 
-                    if ( !idx ) {
+                    if (!idx) {
                         uint32_t code = get_bits(&s->gb, 14);
                         val  =  code >> 6;
                         sign = (code & 1) - 1;
@@ -908,19 +941,15 @@ static int decode_scale_factors(WMAProDecodeCtx* s)
 
                     i += skip;
                     if (i >= s->num_bands) {
-                        av_log(s->avctx,AV_LOG_ERROR,
+                        av_log(s->avctx, AV_LOG_ERROR,
                                "invalid scale factor coding\n");
                         return AVERROR_INVALIDDATA;
                     }
                     s->channel[c].scale_factors[i] += (val ^ sign) - sign;
                 }
             }
-
-            /** save transmitted scale factors so that they can be reused for
-                the next subframe */
-            memcpy(s->channel[c].saved_scale_factors,
-                   s->channel[c].scale_factors, s->num_bands *
-                   sizeof(*s->channel[c].saved_scale_factors));
+            /** swap buffers */
+            s->channel[c].scale_factor_idx = !s->channel[c].scale_factor_idx;
             s->channel[c].table_idx = s->table_idx;
             s->channel[c].reuse_sf  = 1;
         }
@@ -955,7 +984,7 @@ static void inverse_channel_transform(WMAProDecodeCtx *s)
 
             /** multichannel decorrelation */
             for (sfb = s->cur_sfb_offsets;
-                sfb < s->cur_sfb_offsets + s->num_bands;sfb++) {
+                 sfb < s->cur_sfb_offsets + s->num_bands; sfb++) {
                 int y;
                 if (*tb++ == 1) {
                     /** multiply values with the decorrelation_matrix */
@@ -966,7 +995,7 @@ static void inverse_channel_transform(WMAProDecodeCtx *s)
                         float** ch;
 
                         for (ch = ch_data; ch < ch_end; ch++)
-                           *data_ptr++ = (*ch)[y];
+                            *data_ptr++ = (*ch)[y];
 
                         for (ch = ch_data; ch < ch_end; ch++) {
                             float sum = 0;
@@ -978,10 +1007,13 @@ static void inverse_channel_transform(WMAProDecodeCtx *s)
                         }
                     }
                 } else if (s->num_channels == 2) {
-                    for (y = sfb[0]; y < FFMIN(sfb[1], s->subframe_len); y++) {
-                        ch_data[0][y] *= 181.0 / 128;
-                        ch_data[1][y] *= 181.0 / 128;
-                    }
+                    int len = FFMIN(sfb[1], s->subframe_len) - sfb[0];
+                    s->dsp.vector_fmul_scalar(ch_data[0] + sfb[0],
+                                              ch_data[0] + sfb[0],
+                                              181.0 / 128, len);
+                    s->dsp.vector_fmul_scalar(ch_data[1] + sfb[0],
+                                              ch_data[1] + sfb[0],
+                                              181.0 / 128, len);
                 }
             }
         }
@@ -995,23 +1027,23 @@ static void inverse_channel_transform(WMAProDecodeCtx *s)
 static void wmapro_window(WMAProDecodeCtx *s)
 {
     int i;
-    for (i = 0; i< s->channels_for_cur_subframe; i++) {
+    for (i = 0; i < s->channels_for_cur_subframe; i++) {
         int c = s->channel_indexes_for_cur_subframe[i];
         float* window;
         int winlen = s->channel[c].prev_block_len;
         float* start = s->channel[c].coeffs - (winlen >> 1);
 
         if (s->subframe_len < winlen) {
-            start += (winlen - s->subframe_len)>>1;
+            start += (winlen - s->subframe_len) >> 1;
             winlen = s->subframe_len;
         }
 
-        window = s->windows[av_log2(winlen)-BLOCK_MIN_BITS];
+        window = s->windows[av_log2(winlen) - WMAPRO_BLOCK_MIN_BITS];
 
         winlen >>= 1;
 
         s->dsp.vector_fmul_window(start, start, start + winlen,
-                                  window, 0, winlen);
+                                  window, winlen);
 
         s->channel[c].prev_block_len = s->subframe_len;
     }
@@ -1046,8 +1078,8 @@ static int decode_subframe(WMAProDecodeCtx *s)
         }
     }
 
-    dprintf(s->avctx,
-           "processing subframe with offset %i len %i\n", offset, subframe_len);
+    av_dlog(s->avctx,
+            "processing subframe with offset %i len %i\n", offset, subframe_len);
 
     /** get a list of all channels that contain the estimated block */
     s->channels_for_cur_subframe = 0;
@@ -1058,7 +1090,7 @@ static int decode_subframe(WMAProDecodeCtx *s)
 
         /** and count if there are multiple subframes that match our profile */
         if (offset == s->channel[i].decoded_samples &&
-           subframe_len == s->channel[i].subframe_len[cur_subframe]) {
+            subframe_len == s->channel[i].subframe_len[cur_subframe]) {
             total_samples -= s->channel[i].subframe_len[cur_subframe];
             s->channel[i].decoded_samples +=
                 s->channel[i].subframe_len[cur_subframe];
@@ -1073,8 +1105,8 @@ static int decode_subframe(WMAProDecodeCtx *s)
         s->parsed_all_subframes = 1;
 
 
-    dprintf(s->avctx, "subframe is part of %i channels\n",
-           s->channels_for_cur_subframe);
+    av_dlog(s->avctx, "subframe is part of %i channels\n",
+            s->channels_for_cur_subframe);
 
     /** calculate number of scale factor bands and their offsets */
     s->table_idx         = av_log2(s->samples_per_frame/subframe_len);
@@ -1086,7 +1118,7 @@ static int decode_subframe(WMAProDecodeCtx *s)
     for (i = 0; i < s->channels_for_cur_subframe; i++) {
         int c = s->channel_indexes_for_cur_subframe[i];
 
-        s->channel[c].coeffs = &s->channel[c].out[(s->samples_per_frame>>1)
+        s->channel[c].coeffs = &s->channel[c].out[(s->samples_per_frame >> 1)
                                                   + offset];
     }
 
@@ -1103,7 +1135,7 @@ static int decode_subframe(WMAProDecodeCtx *s)
 
         if (num_fill_bits >= 0) {
             if (get_bits_count(&s->gb) + num_fill_bits > s->num_saved_bits) {
-                av_log(s->avctx,AV_LOG_ERROR,"invalid number of fill bits\n");
+                av_log(s->avctx, AV_LOG_ERROR, "invalid number of fill bits\n");
                 return AVERROR_INVALIDDATA;
             }
 
@@ -1131,10 +1163,19 @@ static int decode_subframe(WMAProDecodeCtx *s)
     if (transmit_coeffs) {
         int step;
         int quant_step = 90 * s->bits_per_sample >> 4;
-        if ((get_bits1(&s->gb))) {
-            /** FIXME: might change run level mode decision */
-            av_log_ask_for_sample(s->avctx, "unsupported quant step coding\n");
-            return AVERROR_INVALIDDATA;
+
+        /** decode number of vector coded coefficients */
+        if ((s->transmit_num_vec_coeffs = get_bits1(&s->gb))) {
+            int num_bits = av_log2((s->subframe_len + 3)/4) + 1;
+            for (i = 0; i < s->channels_for_cur_subframe; i++) {
+                int c = s->channel_indexes_for_cur_subframe[i];
+                s->channel[c].num_vec_coeffs = get_bits(&s->gb, num_bits) << 2;
+            }
+        } else {
+            for (i = 0; i < s->channels_for_cur_subframe; i++) {
+                int c = s->channel_indexes_for_cur_subframe[i];
+                s->channel[c].num_vec_coeffs = s->subframe_len;
+            }
         }
         /** decode quantization step */
         step = get_sbits(&s->gb, 6);
@@ -1143,13 +1184,13 @@ static int decode_subframe(WMAProDecodeCtx *s)
             const int sign = (step == 31) - 1;
             int quant = 0;
             while (get_bits_count(&s->gb) + 5 < s->num_saved_bits &&
-                   (step = get_bits(&s->gb, 5)) == 31 ) {
-                     quant += 31;
+                   (step = get_bits(&s->gb, 5)) == 31) {
+                quant += 31;
             }
             quant_step += ((quant + step) ^ sign) - sign;
         }
         if (quant_step < 0) {
-            av_log(s->avctx,AV_LOG_DEBUG,"negative quant step\n");
+            av_log(s->avctx, AV_LOG_DEBUG, "negative quant step\n");
         }
 
         /** decode quantization step modifiers for every channel */
@@ -1163,8 +1204,7 @@ static int decode_subframe(WMAProDecodeCtx *s)
                 s->channel[c].quant_step = quant_step;
                 if (get_bits1(&s->gb)) {
                     if (modifier_len) {
-                        s->channel[c].quant_step +=
-                                get_bits(&s->gb, modifier_len) + 1;
+                        s->channel[c].quant_step += get_bits(&s->gb, modifier_len) + 1;
                     } else
                         ++s->channel[c].quant_step;
                 }
@@ -1176,24 +1216,25 @@ static int decode_subframe(WMAProDecodeCtx *s)
             return AVERROR_INVALIDDATA;
     }
 
-    dprintf(s->avctx, "BITSTREAM: subframe header length was %i\n",
-           get_bits_count(&s->gb) - s->subframe_offset);
+    av_dlog(s->avctx, "BITSTREAM: subframe header length was %i\n",
+            get_bits_count(&s->gb) - s->subframe_offset);
 
     /** parse coefficients */
     for (i = 0; i < s->channels_for_cur_subframe; i++) {
         int c = s->channel_indexes_for_cur_subframe[i];
         if (s->channel[c].transmit_coefs &&
-           get_bits_count(&s->gb) < s->num_saved_bits) {
-                decode_coeffs(s, c);
+            get_bits_count(&s->gb) < s->num_saved_bits) {
+            decode_coeffs(s, c);
         } else
             memset(s->channel[c].coeffs, 0,
                    sizeof(*s->channel[c].coeffs) * subframe_len);
     }
 
-    dprintf(s->avctx, "BITSTREAM: subframe length was %i\n",
-           get_bits_count(&s->gb) - s->subframe_offset);
+    av_dlog(s->avctx, "BITSTREAM: subframe length was %i\n",
+            get_bits_count(&s->gb) - s->subframe_offset);
 
     if (transmit_coeffs) {
+        FFTContext *mdct = &s->mdct_ctx[av_log2(subframe_len) - WMAPRO_BLOCK_MIN_BITS];
         /** reconstruct the per channel data */
         inverse_channel_transform(s);
         for (i = 0; i < s->channels_for_cur_subframe; i++) {
@@ -1212,15 +1253,14 @@ static int decode_subframe(WMAProDecodeCtx *s)
                             (s->channel[c].max_scale_factor - *sf++) *
                             s->channel[c].scale_factor_step;
                 const float quant = pow(10.0, exp / 20.0);
-                int start;
-
-                for (start = s->cur_sfb_offsets[b]; start < end; start++)
-                    s->tmp[start] = s->channel[c].coeffs[start] * quant;
+                int start = s->cur_sfb_offsets[b];
+                s->dsp.vector_fmul_scalar(s->tmp + start,
+                                          s->channel[c].coeffs + start,
+                                          quant, end - start);
             }
 
-            /** apply imdct (ff_imdct_half == DCTIV with reverse) */
-            ff_imdct_half(&s->mdct_ctx[av_log2(subframe_len)-BLOCK_MIN_BITS],
-                          s->channel[c].coeffs, s->tmp);
+            /** apply imdct (imdct_half == DCTIV with reverse) */
+            mdct->imdct_half(mdct, s->channel[c].coeffs, s->tmp);
         }
     }
 
@@ -1231,7 +1271,7 @@ static int decode_subframe(WMAProDecodeCtx *s)
     for (i = 0; i < s->channels_for_cur_subframe; i++) {
         int c = s->channel_indexes_for_cur_subframe[i];
         if (s->channel[c].cur_subframe >= s->channel[c].num_subframes) {
-            av_log(s->avctx,AV_LOG_ERROR,"broken subframe\n");
+            av_log(s->avctx, AV_LOG_ERROR, "broken subframe\n");
             return AVERROR_INVALIDDATA;
         }
         ++s->channel[c].cur_subframe;
@@ -1246,26 +1286,21 @@ static int decode_subframe(WMAProDecodeCtx *s)
  *@return 0 if the trailer bit indicates that this is the last frame,
  *        1 if there are additional frames
  */
-static int decode_frame(WMAProDecodeCtx *s)
+static int decode_frame(WMAProDecodeCtx *s, int *got_frame_ptr)
 {
+    AVCodecContext *avctx = s->avctx;
     GetBitContext* gb = &s->gb;
     int more_frames = 0;
     int len = 0;
-    int i;
-
-    /** check for potential output buffer overflow */
-    if (s->num_channels * s->samples_per_frame > s->samples_end - s->samples) {
-        av_log(s->avctx,AV_LOG_ERROR,
-               "not enough space for the output samples\n");
-        s->packet_loss = 1;
-        return 0;
-    }
+    int i, ret;
+    const float *out_ptr[WMAPRO_MAX_CHANNELS];
+    float *samples;
 
     /** get frame length */
     if (s->len_prefix)
         len = get_bits(gb, s->log2_frame_size);
 
-    dprintf(s->avctx, "decoding frame with length %x\n", len);
+    av_dlog(s->avctx, "decoding frame with length %x\n", len);
 
     /** decode tile information */
     if (decode_tilehdr(s)) {
@@ -1275,38 +1310,39 @@ static int decode_frame(WMAProDecodeCtx *s)
 
     /** read postproc transform */
     if (s->num_channels > 1 && get_bits1(gb)) {
-        av_log_ask_for_sample(s->avctx, "Unsupported postproc transform found\n");
-        s->packet_loss = 1;
-        return 0;
+        if (get_bits1(gb)) {
+            for (i = 0; i < s->num_channels * s->num_channels; i++)
+                skip_bits(gb, 4);
+        }
     }
 
     /** read drc info */
     if (s->dynamic_range_compression) {
         s->drc_gain = get_bits(gb, 8);
-        dprintf(s->avctx, "drc_gain %i\n", s->drc_gain);
+        av_dlog(s->avctx, "drc_gain %i\n", s->drc_gain);
     }
 
     /** no idea what these are for, might be the number of samples
         that need to be skipped at the beginning or end of a stream */
     if (get_bits1(gb)) {
-        int skip;
+        int av_unused skip;
 
         /** usually true for the first frame */
         if (get_bits1(gb)) {
             skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
-            dprintf(s->avctx, "start skip: %i\n", skip);
+            av_dlog(s->avctx, "start skip: %i\n", skip);
         }
 
         /** sometimes true for the last frame */
         if (get_bits1(gb)) {
             skip = get_bits(gb, av_log2(s->samples_per_frame * 2));
-            dprintf(s->avctx, "end skip: %i\n", skip);
+            av_dlog(s->avctx, "end skip: %i\n", skip);
         }
 
     }
 
-    dprintf(s->avctx, "BITSTREAM: frame header length was %i\n",
-           get_bits_count(gb) - s->frame_offset);
+    av_dlog(s->avctx, "BITSTREAM: frame header length was %i\n",
+            get_bits_count(gb) - s->frame_offset);
 
     /** reset subframe states */
     s->parsed_all_subframes = 0;
@@ -1324,20 +1360,22 @@ static int decode_frame(WMAProDecodeCtx *s)
         }
     }
 
-    /** interleave samples and write them to the output buffer */
-    for (i = 0; i < s->num_channels; i++) {
-        float* ptr;
-        int incr = s->num_channels;
-        float* iptr = s->channel[i].out;
-        int x;
-
-        ptr = s->samples + i;
+    /* get output buffer */
+    s->frame.nb_samples = s->samples_per_frame;
+    if ((ret = avctx->get_buffer(avctx, &s->frame)) < 0) {
+        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
+        s->packet_loss = 1;
+        return 0;
+    }
+    samples = (float *)s->frame.data[0];
 
-        for (x = 0; x < s->samples_per_frame; x++) {
-            *ptr = av_clipf(*iptr++, -1.0, 32767.0 / 32768.0);
-            ptr += incr;
-        }
+    /** interleave samples and write them to the output buffer */
+    for (i = 0; i < s->num_channels; i++)
+        out_ptr[i] = s->channel[i].out;
+    s->fmt_conv.float_interleave(samples, out_ptr, s->samples_per_frame,
+                                 s->num_channels);
 
+    for (i = 0; i < s->num_channels; i++) {
         /** reuse second half of the IMDCT output for the next frame */
         memcpy(&s->channel[i].out[0],
                &s->channel[i].out[s->samples_per_frame],
@@ -1346,19 +1384,27 @@ static int decode_frame(WMAProDecodeCtx *s)
 
     if (s->skip_frame) {
         s->skip_frame = 0;
-    } else
-        s->samples += s->num_channels * s->samples_per_frame;
-
-    if (len != (get_bits_count(gb) - s->frame_offset) + 2) {
-        /** FIXME: not sure if this is always an error */
-        av_log(s->avctx,AV_LOG_ERROR,"frame[%i] would have to skip %i bits\n",
-               s->frame_num, len - (get_bits_count(gb) - s->frame_offset) - 1);
-        s->packet_loss = 1;
-        return 0;
+        *got_frame_ptr = 0;
+    } else {
+        *got_frame_ptr = 1;
     }
 
-    /** skip the rest of the frame data */
-    skip_bits_long(gb, len - (get_bits_count(gb) - s->frame_offset) - 1);
+    if (s->len_prefix) {
+        if (len != (get_bits_count(gb) - s->frame_offset) + 2) {
+            /** FIXME: not sure if this is always an error */
+            av_log(s->avctx, AV_LOG_ERROR,
+                   "frame[%i] would have to skip %i bits\n", s->frame_num,
+                   len - (get_bits_count(gb) - s->frame_offset) - 1);
+            s->packet_loss = 1;
+            return 0;
+        }
+
+        /** skip the rest of the frame data */
+        skip_bits_long(gb, len - (get_bits_count(gb) - s->frame_offset) - 1);
+    } else {
+        while (get_bits_count(gb) < s->num_saved_bits && get_bits1(gb) == 0) {
+        }
+    }
 
     /** decode trailer bit */
     more_frames = get_bits1(gb);
@@ -1373,7 +1419,7 @@ static int decode_frame(WMAProDecodeCtx *s)
  *@param gb bitstream reader context
  *@return remaining size in bits
  */
-static int remaining_bits(WMAProDecodeCtx *s, GetBitContextgb)
+static int remaining_bits(WMAProDecodeCtx *s, GetBitContext *gb)
 {
     return s->buf_bit_size - get_bits_count(gb);
 }
@@ -1383,10 +1429,10 @@ static int remaining_bits(WMAProDecodeCtx *s, GetBitContext* gb)
  *@param s codec context
  *@param gb bitstream reader context
  *@param len length of the partial frame
- *@param append decides wether to reset the buffer or not
+ *@param append decides whether to reset the buffer or not
  */
 static void save_bits(WMAProDecodeCtx *s, GetBitContext* gb, int len,
-                          int append)
+                      int append)
 {
     int buflen;
 
@@ -1403,26 +1449,27 @@ static void save_bits(WMAProDecodeCtx *s, GetBitContext* gb, int len,
     buflen = (s->num_saved_bits + len + 8) >> 3;
 
     if (len <= 0 || buflen > MAX_FRAMESIZE) {
-         av_log_ask_for_sample(s->avctx, "input buffer too small\n");
-         s->packet_loss = 1;
-         return;
+        av_log_ask_for_sample(s->avctx, "input buffer too small\n");
+        s->packet_loss = 1;
+        return;
     }
 
     s->num_saved_bits += len;
     if (!append) {
-        ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), s->num_saved_bits);
+        avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3),
+                     s->num_saved_bits);
     } else {
         int align = 8 - (get_bits_count(gb) & 7);
         align = FFMIN(align, len);
         put_bits(&s->pb, align, get_bits(gb, align));
         len -= align;
-        ff_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len);
+        avpriv_copy_bits(&s->pb, gb->buffer + (get_bits_count(gb) >> 3), len);
     }
     skip_bits_long(gb, len);
 
     {
-    PutBitContext tmp = s->pb;
-    flush_put_bits(&tmp);
+        PutBitContext tmp = s->pb;
+        flush_put_bits(&tmp);
     }
 
     init_get_bits(&s->gb, s->frame_data, s->num_saved_bits);
@@ -1433,97 +1480,119 @@ static void save_bits(WMAProDecodeCtx *s, GetBitContext* gb, int len,
  *@brief Decode a single WMA packet.
  *@param avctx codec context
  *@param data the output buffer
- *@param data_size number of bytes that were written to the output buffer
  *@param avpkt input packet
  *@return number of bytes that were read from the input buffer
  */
-static int decode_packet(AVCodecContext *avctx,
-                             void *data, int *data_size, AVPacket* avpkt)
+static int decode_packet(AVCodecContext *avctx, void *data,
+                         int *got_frame_ptr, AVPacket* avpkt)
 {
-    GetBitContext gb;
     WMAProDecodeCtx *s = avctx->priv_data;
-    const uint8_t* buf   = avpkt->data;
-    int buf_size         = avpkt->size;
-    int more_frames      = 1;
+    GetBitContext* gb  = &s->pgb;
+    const uint8_t* buf = avpkt->data;
+    int buf_size       = avpkt->size;
     int num_bits_prev_frame;
     int packet_sequence_number;
 
-    s->samples      = data;
-    s->samples_end  = (float*)((int8_t*)data + *data_size);
-    s->buf_bit_size = buf_size << 3;
+    *got_frame_ptr = 0;
 
+    if (s->packet_done || s->packet_loss) {
+        s->packet_done = 0;
 
-    *data_size = 0;
-
-    /** sanity check for the buffer length */
-    if (buf_size < avctx->block_align)
-        return 0;
+        /** sanity check for the buffer length */
+        if (buf_size < avctx->block_align)
+            return 0;
 
-    buf_size = avctx->block_align;
+        s->next_packet_start = buf_size - avctx->block_align;
+        buf_size = avctx->block_align;
+        s->buf_bit_size = buf_size << 3;
 
-    /** parse packet header */
-    init_get_bits(&gb, buf, s->buf_bit_size);
-    packet_sequence_number = get_bits(&gb, 4);
-    skip_bits(&gb, 2);
+        /** parse packet header */
+        init_get_bits(gb, buf, s->buf_bit_size);
+        packet_sequence_number = get_bits(gb, 4);
+        skip_bits(gb, 2);
 
-    /** get number of bits that need to be added to the previous frame */
-    num_bits_prev_frame = get_bits(&gb, s->log2_frame_size);
-    dprintf(avctx, "packet[%d]: nbpf %x\n", avctx->frame_number,
-                  num_bits_prev_frame);
+        /** get number of bits that need to be added to the previous frame */
+        num_bits_prev_frame = get_bits(gb, s->log2_frame_size);
+        av_dlog(avctx, "packet[%d]: nbpf %x\n", avctx->frame_number,
+                num_bits_prev_frame);
 
-    /** check for packet loss */
-    if (!s->packet_loss &&
-        ((s->packet_sequence_number + 1)&0xF) != packet_sequence_number) {
-        s->packet_loss = 1;
-        av_log(avctx, AV_LOG_ERROR, "Packet loss detected! seq %x vs %x\n",
-                      s->packet_sequence_number, packet_sequence_number);
-    }
-    s->packet_sequence_number = packet_sequence_number;
-
-    if (num_bits_prev_frame > 0) {
-        /** append the previous frame data to the remaining data from the
-            previous packet to create a full frame */
-        save_bits(s, &gb, num_bits_prev_frame, 1);
-        dprintf(avctx, "accumulated %x bits of frame data\n",
-                      s->num_saved_bits - s->frame_offset);
-
-        /** decode the cross packet frame if it is valid */
-        if (!s->packet_loss)
-            decode_frame(s);
-    } else if (s->num_saved_bits - s->frame_offset) {
-        dprintf(avctx, "ignoring %x previously saved bits\n",
-                      s->num_saved_bits - s->frame_offset);
-    }
+        /** check for packet loss */
+        if (!s->packet_loss &&
+            ((s->packet_sequence_number + 1) & 0xF) != packet_sequence_number) {
+            s->packet_loss = 1;
+            av_log(avctx, AV_LOG_ERROR, "Packet loss detected! seq %x vs %x\n",
+                   s->packet_sequence_number, packet_sequence_number);
+        }
+        s->packet_sequence_number = packet_sequence_number;
 
-    s->packet_loss = 0;
-    /** decode the rest of the packet */
-    while (!s->packet_loss && more_frames &&
-          remaining_bits(s, &gb) > s->log2_frame_size) {
-        int frame_size = show_bits(&gb, s->log2_frame_size);
+        if (num_bits_prev_frame > 0) {
+            int remaining_packet_bits = s->buf_bit_size - get_bits_count(gb);
+            if (num_bits_prev_frame >= remaining_packet_bits) {
+                num_bits_prev_frame = remaining_packet_bits;
+                s->packet_done = 1;
+            }
 
-        /** there is enough data for a full frame */
-        if (remaining_bits(s,&gb) >= frame_size && frame_size > 0) {
-            save_bits(s, &gb, frame_size, 0);
+            /** append the previous frame data to the remaining data from the
+                previous packet to create a full frame */
+            save_bits(s, gb, num_bits_prev_frame, 1);
+            av_dlog(avctx, "accumulated %x bits of frame data\n",
+                    s->num_saved_bits - s->frame_offset);
+
+            /** decode the cross packet frame if it is valid */
+            if (!s->packet_loss)
+                decode_frame(s, got_frame_ptr);
+        } else if (s->num_saved_bits - s->frame_offset) {
+            av_dlog(avctx, "ignoring %x previously saved bits\n",
+                    s->num_saved_bits - s->frame_offset);
+        }
 
-            /** decode the frame */
-            more_frames = decode_frame(s);
+        if (s->packet_loss) {
+            /** reset number of saved bits so that the decoder
+                does not start to decode incomplete frames in the
+                s->len_prefix == 0 case */
+            s->num_saved_bits = 0;
+            s->packet_loss = 0;
+        }
 
-            if (!more_frames) {
-                dprintf(avctx, "no more frames\n");
-            }
+    } else {
+        int frame_size;
+        s->buf_bit_size = (avpkt->size - s->next_packet_start) << 3;
+        init_get_bits(gb, avpkt->data, s->buf_bit_size);
+        skip_bits(gb, s->packet_offset);
+        if (s->len_prefix && remaining_bits(s, gb) > s->log2_frame_size &&
+            (frame_size = show_bits(gb, s->log2_frame_size)) &&
+            frame_size <= remaining_bits(s, gb)) {
+            save_bits(s, gb, frame_size, 0);
+            s->packet_done = !decode_frame(s, got_frame_ptr);
+        } else if (!s->len_prefix
+                   && s->num_saved_bits > get_bits_count(&s->gb)) {
+            /** when the frames do not have a length prefix, we don't know
+                the compressed length of the individual frames
+                however, we know what part of a new packet belongs to the
+                previous frame
+                therefore we save the incoming packet first, then we append
+                the "previous frame" data from the next packet so that
+                we get a buffer that only contains full frames */
+            s->packet_done = !decode_frame(s, got_frame_ptr);
         } else
-            more_frames = 0;
+            s->packet_done = 1;
     }
 
-    if (!s->packet_loss && remaining_bits(s,&gb) > 0) {
+    if (s->packet_done && !s->packet_loss &&
+        remaining_bits(s, gb) > 0) {
         /** save the rest of the data so that it can be decoded
             with the next packet */
-        save_bits(s, &gb, remaining_bits(s,&gb), 0);
+        save_bits(s, gb, remaining_bits(s, gb), 0);
     }
 
-    *data_size = (int8_t *)s->samples - (int8_t *)data;
+    s->packet_offset = get_bits_count(gb) & 7;
+    if (s->packet_loss)
+        return AVERROR_INVALIDDATA;
+
+    if (*got_frame_ptr)
+        *(AVFrame *)data = s->frame;
 
-    return avctx->block_align;
+    return get_bits_count(gb) >> 3;
 }
 
 /**
@@ -1546,15 +1615,15 @@ static void flush(AVCodecContext *avctx)
 /**
  *@brief wmapro decoder
  */
-AVCodec wmapro_decoder = {
-    "wmapro",
-    CODEC_TYPE_AUDIO,
-    CODEC_ID_WMAPRO,
-    sizeof(WMAProDecodeCtx),
-    decode_init,
-    NULL,
-    decode_end,
-    decode_packet,
-    .flush= flush,
-    .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"),
+AVCodec ff_wmapro_decoder = {
+    .name           = "wmapro",
+    .type           = AVMEDIA_TYPE_AUDIO,
+    .id             = CODEC_ID_WMAPRO,
+    .priv_data_size = sizeof(WMAProDecodeCtx),
+    .init           = decode_init,
+    .close          = decode_end,
+    .decode         = decode_packet,
+    .capabilities   = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1,
+    .flush          = flush,
+    .long_name      = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"),
 };