]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/wmaprodec.c
DCA: use a local variable for loop boundary
[ffmpeg] / libavcodec / wmaprodec.c
index 6ed55fd24ca99fae794248859068768878d55339..82f1b3623b28c3e57f93f8cf1c2c1cbcfa2dfa46 100644 (file)
@@ -98,7 +98,7 @@
 #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_MAX_SIZE (1 << WMAPRO_BLOCK_MAX_BITS)                 ///< maximum block size
@@ -137,11 +137,12 @@ 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
+    DECLARE_ALIGNED(16, float, out)[WMAPRO_BLOCK_MAX_SIZE + WMAPRO_BLOCK_MAX_SIZE / 2]; ///< output buffer
 } WMAProChannelCtx;
 
 /**
@@ -165,8 +166,8 @@ typedef struct WMAProDecodeCtx {
     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(16, 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) */
@@ -189,18 +190,18 @@ typedef struct WMAProDecodeCtx {
 
     /* packet decode state */
     GetBitContext    pgb;                           ///< bitstream reader context for the 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          output_buffer_full;            ///< flag indicating that the output buffer is full
+    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_start;                 ///< start samplebuffer pointer
     float*           samples;                       ///< current samplebuffer pointer
     float*           samples_end;                   ///< maximum samplebuffer pointer
     uint8_t          drc_gain;                      ///< gain for the DRC tool
@@ -342,9 +343,12 @@ 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;
+    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_VLC_STATIC(&sf_vlc, SCALEVLCBITS, HUFF_SCALE_SIZE,
@@ -424,9 +428,8 @@ static av_cold int decode_init(AVCodecContext *avctx)
 
     /** 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);
+        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];
     }
 
@@ -761,6 +764,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 int 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];
@@ -768,7 +780,7 @@ 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);
 
@@ -796,29 +808,32 @@ 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);
+                    int 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);
+                    ((float*)vals)[i  ] = v0;
+                    ((float*)vals)[i+1] = 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*)&ci->coeffs[cur_coeff] = vals[i] ^ sign<<31;
                 num_zeros = 0;
             } else {
                 ci->coeffs[cur_coeff] = 0;
@@ -860,7 +875,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
@@ -872,7 +889,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)) {
@@ -919,12 +936,8 @@ static int decode_scale_factors(WMAProDecodeCtx* s)
                     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;
         }
@@ -982,10 +995,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);
                 }
             }
         }
@@ -1215,10 +1231,10 @@ 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) */
@@ -1259,12 +1275,9 @@ static int decode_frame(WMAProDecodeCtx *s)
     /** check for potential output buffer overflow */
     if (s->num_channels * s->samples_per_frame > s->samples_end - s->samples) {
         /** return an error if no frame could be decoded at all */
-        if (s->samples_start == s->samples) {
-            av_log(s->avctx, AV_LOG_ERROR,
-                   "not enough space for the output samples\n");
-            s->packet_loss = 1;
-        } else
-            s->output_buffer_full = 1;
+        av_log(s->avctx, AV_LOG_ERROR,
+               "not enough space for the output samples\n");
+        s->packet_loss = 1;
         return 0;
     }
 
@@ -1333,14 +1346,12 @@ 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;
+        float* ptr  = s->samples + i;
         int incr = s->num_channels;
         float* iptr = s->channel[i].out;
-        int x;
+        float* iend = iptr + s->samples_per_frame;
 
-        ptr = s->samples + i;
-
-        for (x = 0; x < s->samples_per_frame; x++) {
+        while (iptr < iend) {
             *ptr = av_clipf(*iptr++, -1.0, 32767.0 / 32768.0);
             ptr += incr;
         }
@@ -1449,86 +1460,77 @@ static int decode_packet(AVCodecContext *avctx,
                          void *data, int *data_size, AVPacket* avpkt)
 {
     WMAProDecodeCtx *s = avctx->priv_data;
-    GetBitContext* gb    = &s->pgb;
-    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_start = data;
-    s->samples_end  = (float*)((int8_t*)data + *data_size);
+    s->samples       = data;
+    s->samples_end   = (float*)((int8_t*)data + *data_size);
     *data_size = 0;
 
-    if (!s->output_buffer_full) {
-    s->buf_bit_size = buf_size << 3;
+    if (s->packet_done || s->packet_loss) {
+        s->packet_done = 0;
+        s->buf_bit_size = buf_size << 3;
 
-    /** 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;
+        buf_size = avctx->block_align;
 
-    /** 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);
+        dprintf(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;
+
+        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);
+        }
 
-    s->packet_loss = 0;
+        s->packet_loss = 0;
 
     } else {
-        /** continue decoding */
-        s->output_buffer_full = 0;
-        more_frames = decode_frame(s);
-    }
-
-    /** decode the rest of the packet */
-    while (!s->packet_loss && !s->output_buffer_full && more_frames &&
-           remaining_bits(s, gb) > s->log2_frame_size) {
-        int frame_size = show_bits(gb, s->log2_frame_size);
-
-        /** there is enough data for a full frame */
-        if (remaining_bits(s, gb) >= frame_size && frame_size > 0) {
+        int frame_size;
+        s->buf_bit_size = avpkt->size << 3;
+        init_get_bits(gb, avpkt->data, s->buf_bit_size);
+        skip_bits(gb, s->packet_offset);
+        if (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);
-
-            /** decode the frame */
-            more_frames = decode_frame(s);
-
+            s->packet_done = !decode_frame(s);
         } else
-            more_frames = 0;
+            s->packet_done = 1;
     }
 
-    if (!s->output_buffer_full && !s->packet_loss &&
+    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 */
@@ -1536,8 +1538,9 @@ static int decode_packet(AVCodecContext *avctx,
     }
 
     *data_size = (int8_t *)s->samples - (int8_t *)data;
+    s->packet_offset = get_bits_count(gb) & 7;
 
-    return (s->output_buffer_full)?0: avctx->block_align;
+    return (s->packet_loss) ? AVERROR_INVALIDDATA : get_bits_count(gb) >> 3;
 }
 
 /**
@@ -1562,13 +1565,14 @@ static void flush(AVCodecContext *avctx)
  */
 AVCodec wmapro_decoder = {
     "wmapro",
-    CODEC_TYPE_AUDIO,
+    AVMEDIA_TYPE_AUDIO,
     CODEC_ID_WMAPRO,
     sizeof(WMAProDecodeCtx),
     decode_init,
     NULL,
     decode_end,
     decode_packet,
+    .capabilities = CODEC_CAP_SUBFRAMES,
     .flush= flush,
     .long_name = NULL_IF_CONFIG_SMALL("Windows Media Audio 9 Professional"),
 };