]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mlpdec.c
flacenc : do not #include libavutil/lls.h since lpc code is now
[ffmpeg] / libavcodec / mlpdec.c
index 6d148b4735c39b6aea2c21db4abdebe8c6a12569..e74d146af0abcfb01d60d154edeb5ac2288eb7eb 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "avcodec.h"
 #include "libavutil/intreadwrite.h"
-#include "bitstream.h"
+#include "get_bits.h"
 #include "libavutil/crc.h"
 #include "parser.h"
 #include "mlp_parser.h"
@@ -117,6 +117,9 @@ typedef struct SubStream {
 typedef struct MLPDecodeContext {
     AVCodecContext *avctx;
 
+    //! Current access unit being read has a major sync.
+    int         is_major_sync_unit;
+
     //! Set if a valid major sync block has been read. Otherwise no decoding is possible.
     uint8_t     params_valid;
 
@@ -135,6 +138,9 @@ typedef struct MLPDecodeContext {
 
     ChannelParams channel_params[MAX_CHANNELS];
 
+    int         matrix_changed;
+    int         filter_changed[MAX_CHANNELS][NUM_FILTERS];
+
     int8_t      noise_buffer[MAX_BLOCKSIZE_POW2];
     int8_t      bypassed_lsbs[MAX_BLOCKSIZE][MAX_CHANNELS];
     int32_t     sample_buffer[MAX_BLOCKSIZE][MAX_CHANNELS+2];
@@ -440,6 +446,8 @@ static int read_filter_params(MLPDecodeContext *m, GetBitContext *gbp,
     // Filter is 0 for FIR, 1 for IIR.
     assert(filter < 2);
 
+    m->filter_changed[channel][filter]++;
+
     order = get_bits(gbp, 4);
     if (order > max_order) {
         av_log(m->avctx, AV_LOG_ERROR,
@@ -501,6 +509,7 @@ static int read_matrix_params(MLPDecodeContext *m, SubStream *s, GetBitContext *
     unsigned int mat, ch;
 
     s->num_primitive_matrices = get_bits(gbp, 4);
+    m->matrix_changed++;
 
     for (mat = 0; mat < s->num_primitive_matrices; mat++) {
         int frac_bits, max_chan;
@@ -508,7 +517,7 @@ static int read_matrix_params(MLPDecodeContext *m, SubStream *s, GetBitContext *
         frac_bits             = get_bits(gbp, 4);
         s->lsb_bypass   [mat] = get_bits1(gbp);
 
-        if (s->matrix_out_ch[mat] > s->max_channel) {
+        if (s->matrix_out_ch[mat] > s->max_matrix_channel) {
             av_log(m->avctx, AV_LOG_ERROR,
                     "Invalid channel %d specified as output from matrix.\n",
                     s->matrix_out_ch[mat]);
@@ -895,8 +904,10 @@ static int output_data(MLPDecodeContext *m, unsigned int substr,
  *  otherwise returns the number of bytes consumed. */
 
 static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size,
-                            const uint8_t *buf, int buf_size)
+                            AVPacket *avpkt)
 {
+    const uint8_t *buf = avpkt->data;
+    int buf_size = avpkt->size;
     MLPDecodeContext *m = avctx->priv_data;
     GetBitContext gb;
     unsigned int length, substr;
@@ -917,9 +928,11 @@ static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size,
 
     init_get_bits(&gb, (buf + 4), (length - 4) * 8);
 
+    m->is_major_sync_unit = 0;
     if (show_bits_long(&gb, 31) == (0xf8726fba >> 1)) {
         if (read_major_sync(m, &gb) < 0)
             goto error;
+        m->is_major_sync_unit = 1;
         header_size += 28;
     }
 
@@ -933,10 +946,10 @@ static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size,
     substream_start = 0;
 
     for (substr = 0; substr < m->num_substreams; substr++) {
-        int extraword_present, checkdata_present, end;
+        int extraword_present, checkdata_present, end, nonrestart_substr;
 
         extraword_present = get_bits1(&gb);
-        skip_bits1(&gb);
+        nonrestart_substr = get_bits1(&gb);
         checkdata_present = get_bits1(&gb);
         skip_bits1(&gb);
 
@@ -945,10 +958,19 @@ static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size,
         substr_header_size += 2;
 
         if (extraword_present) {
+            if (m->avctx->codec_id == CODEC_ID_MLP) {
+                av_log(m->avctx, AV_LOG_ERROR, "There must be no extraword for MLP.\n");
+                goto error;
+            }
             skip_bits(&gb, 16);
             substr_header_size += 2;
         }
 
+        if (!(nonrestart_substr ^ m->is_major_sync_unit)) {
+            av_log(m->avctx, AV_LOG_ERROR, "Invalid nonrestart_substr.\n");
+            goto error;
+        }
+
         if (end + header_size + substr_header_size > length) {
             av_log(m->avctx, AV_LOG_ERROR,
                    "Indicated length of substream %d data goes off end of "
@@ -986,8 +1008,13 @@ static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size,
         SubStream *s = &m->substream[substr];
         init_get_bits(&gb, buf, substream_data_len[substr] * 8);
 
+        m->matrix_changed = 0;
+        memset(m->filter_changed, 0, sizeof(m->filter_changed));
+
         s->blockpos = 0;
         do {
+            unsigned int ch;
+
             if (get_bits1(&gb)) {
                 if (get_bits1(&gb)) {
                     /* A restart header should be present. */
@@ -1004,6 +1031,17 @@ static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size,
                     goto next_substr;
             }
 
+            if (m->matrix_changed > 1) {
+                av_log(m->avctx, AV_LOG_ERROR, "Matrices may change only once per access unit.\n");
+                goto next_substr;
+            }
+            for (ch = 0; ch < s->max_channel; ch++)
+                if (m->filter_changed[ch][FIR] > 1 ||
+                    m->filter_changed[ch][IIR] > 1) {
+                    av_log(m->avctx, AV_LOG_ERROR, "Filters may change only once per access unit.\n");
+                    goto next_substr;
+                }
+
             if (!s->restart_seen) {
                 goto next_substr;
             }