]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/wmalosslessdec.c
ffv1: add 1 status byte to slices in in case crcs are stored too.
[ffmpeg] / libavcodec / wmalosslessdec.c
index 5529079fe14ffd720a056d9aa1c98f6dab176126..de5dca333c130a4d2977ec56b72aad9340e01a7a 100644 (file)
@@ -5,20 +5,20 @@
  * Copyright (c) 2011 Andreas Ă–man
  * Copyright (c) 2011 - 2012 Mashiat Sarker Shakkhar
  *
- * This file is part of Libav.
+ * This file is part of FFmpeg.
  *
- * Libav is free software; you can redistribute it and/or
+ * 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.
  *
- * Libav is distributed in the hope that it will be useful,
+ * 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 Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
@@ -126,8 +126,8 @@ typedef struct WmallDecodeCtx {
     int8_t  mclms_scaling;
     int16_t mclms_coeffs[128];
     int16_t mclms_coeffs_cur[4];
-    int16_t mclms_prevvalues[64];
-    int16_t mclms_updates[64];
+    int16_t mclms_prevvalues[WMALL_MAX_CHANNELS * 2 * 32];
+    int16_t mclms_updates[WMALL_MAX_CHANNELS * 2 * 32];
     int     mclms_recent;
 
     int     movave_scaling;
@@ -157,14 +157,14 @@ typedef struct WmallDecodeCtx {
 
     int ave_sum[2];
 
-    int channel_residues[2][2048];
+    int channel_residues[2][WMALL_BLOCK_MAX_SIZE];
 
     int lpc_coefs[2][40];
     int lpc_order;
     int lpc_scaling;
     int lpc_intbits;
 
-    int channel_coeffs[2][2048];
+    int channel_coeffs[2][WMALL_BLOCK_MAX_SIZE];
 } WmallDecodeCtx;
 
 
@@ -173,7 +173,7 @@ static av_cold int decode_init(AVCodecContext *avctx)
     WmallDecodeCtx *s  = avctx->priv_data;
     uint8_t *edata_ptr = avctx->extradata;
     unsigned int channel_mask;
-    int i, log2_max_num_subframes, num_possible_block_sizes;
+    int i, bits, log2_max_num_subframes, num_possible_block_sizes;
 
     s->avctx = avctx;
     init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
@@ -212,8 +212,12 @@ static av_cold int decode_init(AVCodecContext *avctx)
     s->len_prefix  = s->decode_flags & 0x40;
 
     /* get frame len */
-    s->samples_per_frame = 1 << ff_wma_get_frame_len_bits(avctx->sample_rate,
-                                                          3, s->decode_flags);
+    bits = ff_wma_get_frame_len_bits(avctx->sample_rate, 3, s->decode_flags);
+    if (bits > WMALL_BLOCK_MAX_BITS) {
+        av_log_missing_feature(avctx, "big-bits block sizes", 1);
+        return AVERROR_INVALIDDATA;
+    }
+    s->samples_per_frame = 1 << bits;
 
     /* init previous block len */
     for (i = 0; i < avctx->channels; i++)
@@ -225,7 +229,6 @@ static av_cold int decode_init(AVCodecContext *avctx)
     s->max_subframe_len_bit = 0;
     s->subframe_len_bits    = av_log2(log2_max_num_subframes) + 1;
 
-    num_possible_block_sizes     = log2_max_num_subframes + 1;
     s->min_samples_per_subframe  = s->samples_per_frame / s->max_num_subframes;
     s->dynamic_range_compression = s->decode_flags & 0x80;
     s->bV3RTM                    = s->decode_flags & 0x100;
@@ -330,21 +333,28 @@ static int decode_tilehdr(WmallDecodeCtx *s)
 
     /* loop until the frame data is split between the subframes */
     do {
-        int subframe_len;
+        int subframe_len, in_use = 0;
 
         /* check which channels contain the subframe */
         for (c = 0; c < s->num_channels; c++) {
             if (num_samples[c] == min_channel_len) {
                 if (fixed_channel_layout || channels_for_cur_subframe == 1 ||
                    (min_channel_len == s->samples_per_frame - s->min_samples_per_subframe)) {
-                    contains_subframe[c] = 1;
+                    contains_subframe[c] = in_use = 1;
                 } else {
-                    contains_subframe[c] = get_bits1(&s->gb);
+                    if (get_bits1(&s->gb))
+                        contains_subframe[c] = in_use = 1;
                 }
             } else
                 contains_subframe[c] = 0;
         }
 
+        if (!in_use) {
+            av_log(s->avctx, AV_LOG_ERROR,
+                   "Found empty subframe\n");
+            return AVERROR_INVALIDDATA;
+        }
+
         /* get subframe length, subframe_len == 0 is not allowed */
         if ((subframe_len = decode_subframe_length(s, min_channel_len)) <= 0)
             return AVERROR_INVALIDDATA;
@@ -396,7 +406,7 @@ static void decode_ac_filter(WmallDecodeCtx *s)
     s->acfilter_scaling = get_bits(&s->gb, 4);
 
     for (i = 0; i < s->acfilter_order; i++)
-        s->acfilter_coeffs[i] = get_bits(&s->gb, s->acfilter_scaling) + 1;
+        s->acfilter_coeffs[i] = (s->acfilter_scaling ? get_bits(&s->gb, s->acfilter_scaling) : 0) + 1;
 }
 
 static void decode_mclms(WmallDecodeCtx *s)
@@ -489,9 +499,9 @@ static int decode_channel_residues(WmallDecodeCtx *s, int ch, int tile_size)
 
     if (s->seekable_tile) {
         if (s->do_inter_ch_decorr)
-            s->channel_residues[ch][0] = get_sbits(&s->gb, s->bits_per_sample + 1);
+            s->channel_residues[ch][0] = get_sbits_long(&s->gb, s->bits_per_sample + 1);
         else
-            s->channel_residues[ch][0] = get_sbits(&s->gb, s->bits_per_sample);
+            s->channel_residues[ch][0] = get_sbits_long(&s->gb, s->bits_per_sample);
         i++;
     }
     for (; i < tile_size; i++) {
@@ -509,7 +519,7 @@ static int decode_channel_residues(WmallDecodeCtx *s, int ch, int tile_size)
             residue = quo;
         else {
             rem_bits = av_ceil_log2(ave_mean);
-            rem      = rem_bits ? get_bits(&s->gb, rem_bits) : 0;
+            rem      = get_bits_long(&s->gb, rem_bits);
             residue  = (quo << rem_bits) + rem;
         }
 
@@ -896,6 +906,7 @@ static int decode_subframe(WmallDecodeCtx *s)
     } else if (!s->cdlms[0][0].order) {
         av_log(s->avctx, AV_LOG_DEBUG,
                "Waiting for seekable tile\n");
+        s->frame.nb_samples = 0;
         return -1;
     }
 
@@ -928,12 +939,17 @@ static int decode_subframe(WmallDecodeCtx *s)
 
     if (rawpcm_tile) {
         int bits = s->bits_per_sample - padding_zeroes;
+        if (bits <= 0) {
+            av_log(s->avctx, AV_LOG_ERROR,
+                   "Invalid number of padding bits in raw PCM tile\n");
+            return AVERROR_INVALIDDATA;
+        }
         av_dlog(s->avctx, "RAWPCM %d bits per sample. "
                 "total %d bits, remain=%d\n", bits,
                 bits * s->num_channels * subframe_len, get_bits_count(&s->gb));
         for (i = 0; i < s->num_channels; i++)
             for (j = 0; j < subframe_len; j++)
-                s->channel_coeffs[i][j] = get_sbits(&s->gb, bits);
+                s->channel_coeffs[i][j] = get_sbits_long(&s->gb, bits);
     } else {
         for (i = 0; i < s->num_channels; i++)
             if (s->is_channel_coded[i]) {
@@ -943,7 +959,8 @@ static int decode_subframe(WmallDecodeCtx *s)
                 else
                     use_normal_update_speed(s, i);
                 revert_cdlms(s, i, 0, subframe_len);
-            }
+            } else
+                memset(s->channel_residues[i], 0, sizeof(s->channel_residues[i]));
     }
     if (s->do_mclms)
         revert_mclms(s, subframe_len);
@@ -1145,14 +1162,6 @@ static void save_bits(WmallDecodeCtx *s, GetBitContext* gb, int len,
     skip_bits(&s->gb, s->frame_offset);
 }
 
-/**
- * @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 *got_frame_ptr,
                          AVPacket* avpkt)
 {
@@ -1160,8 +1169,9 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr,
     GetBitContext* gb  = &s->pgb;
     const uint8_t* buf = avpkt->data;
     int buf_size       = avpkt->size;
-    int num_bits_prev_frame, packet_sequence_number,
-        seekable_frame_in_packet, spliced_packet;
+    int num_bits_prev_frame, packet_sequence_number, spliced_packet;
+
+    s->frame.nb_samples = 0;
 
     if (s->packet_done || s->packet_loss) {
         s->packet_done = 0;
@@ -1176,9 +1186,11 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr,
 
         /* parse packet header */
         init_get_bits(gb, buf, s->buf_bit_size);
-        packet_sequence_number   = get_bits(gb, 4);
-        seekable_frame_in_packet = get_bits1(gb);
-        spliced_packet           = get_bits1(gb);
+        packet_sequence_number = get_bits(gb, 4);
+        skip_bits(gb, 1);   // Skip seekable_frame_in_packet, currently ununused
+        spliced_packet = get_bits1(gb);
+        if (spliced_packet)
+            av_log_missing_feature(avctx, "Bitstream splicing", 1);
 
         /* get number of bits that need to be added to the previous frame */
         num_bits_prev_frame = get_bits(gb, s->log2_frame_size);
@@ -1215,6 +1227,7 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr,
             /* 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;
+            init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
             s->packet_loss    = 0;
         }
 
@@ -1258,6 +1271,18 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr,
     return (s->packet_loss) ? AVERROR_INVALIDDATA : get_bits_count(gb) >> 3;
 }
 
+static void flush(AVCodecContext *avctx)
+{
+    WmallDecodeCtx *s    = avctx->priv_data;
+    s->packet_loss       = 1;
+    s->packet_done       = 0;
+    s->num_saved_bits    = 0;
+    init_put_bits(&s->pb, s->frame_data, MAX_FRAMESIZE);
+    s->frame_offset      = 0;
+    s->next_packet_start = 0;
+    s->cdlms[0][0].order = 0;
+    s->frame.nb_samples  = 0;
+}
 
 AVCodec ff_wmalossless_decoder = {
     .name           = "wmalossless",
@@ -1266,6 +1291,7 @@ AVCodec ff_wmalossless_decoder = {
     .priv_data_size = sizeof(WmallDecodeCtx),
     .init           = decode_init,
     .decode         = decode_packet,
+    .flush          = flush,
     .capabilities   = CODEC_CAP_SUBFRAMES | CODEC_CAP_DR1 | CODEC_CAP_DELAY,
     .long_name      = NULL_IF_CONFIG_SMALL("Windows Media Audio Lossless"),
 };