]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blobdiff - libavcodec/mlpdec.c
Fix segault
[frescor/ffmpeg.git] / libavcodec / mlpdec.c
index 7b5ad80689a0ae06a6cb7772cfb796ae180a4aec..0a64d79897bf2751ce1a929bdecdcd681ab9b312 100644 (file)
@@ -27,6 +27,7 @@
 #include <stdint.h>
 
 #include "avcodec.h"
+#include "dsputil.h"
 #include "libavutil/intreadwrite.h"
 #include "get_bits.h"
 #include "libavutil/crc.h"
@@ -93,7 +94,7 @@ typedef struct SubStream {
     //! Whether the LSBs of the matrix output are encoded in the bitstream.
     uint8_t     lsb_bypass[MAX_MATRICES];
     //! Matrix coefficients, stored as 2.14 fixed point.
-    int32_t     matrix_coeff[MAX_MATRICES][MAX_CHANNELS+2];
+    int32_t     matrix_coeff[MAX_MATRICES][MAX_CHANNELS];
     //! Left shift to apply to noise values in 0x31eb substreams.
     uint8_t     matrix_noise_shift[MAX_MATRICES];
     //@}
@@ -143,7 +144,9 @@ typedef struct MLPDecodeContext {
 
     int8_t      noise_buffer[MAX_BLOCKSIZE_POW2];
     int8_t      bypassed_lsbs[MAX_BLOCKSIZE][MAX_CHANNELS];
-    int32_t     sample_buffer[MAX_BLOCKSIZE][MAX_CHANNELS+2];
+    int32_t     sample_buffer[MAX_BLOCKSIZE][MAX_CHANNELS];
+
+    DSPContext  dsp;
 } MLPDecodeContext;
 
 static VLC huff_vlc[3];
@@ -231,6 +234,7 @@ static av_cold int mlp_decode_init(AVCodecContext *avctx)
     m->avctx = avctx;
     for (substr = 0; substr < MAX_SUBSTREAMS; substr++)
         m->substream[substr].lossless_check_data = 0xffffffff;
+    dsputil_init(&m->dsp, avctx);
 
     return 0;
 }
@@ -335,6 +339,9 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp,
     uint8_t checksum;
     uint8_t lossless_check;
     int start_count = get_bits_count(gbp);
+    const int max_matrix_channel = m->avctx->codec_id == CODEC_ID_MLP
+                                 ? MAX_MATRIX_CHANNEL_MLP
+                                 : MAX_MATRIX_CHANNEL_TRUEHD;
 
     sync_word = get_bits(gbp, 13);
 
@@ -343,14 +350,42 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp,
                "restart header sync incorrect (got 0x%04x)\n", sync_word);
         return -1;
     }
+
     s->noise_type = get_bits1(gbp);
 
+    if (m->avctx->codec_id == CODEC_ID_MLP && s->noise_type) {
+        av_log(m->avctx, AV_LOG_ERROR, "MLP must have 0x31ea sync word.\n");
+        return -1;
+    }
+
     skip_bits(gbp, 16); /* Output timestamp */
 
     s->min_channel        = get_bits(gbp, 4);
     s->max_channel        = get_bits(gbp, 4);
     s->max_matrix_channel = get_bits(gbp, 4);
 
+    if (s->max_matrix_channel > max_matrix_channel) {
+        av_log(m->avctx, AV_LOG_ERROR,
+               "Max matrix channel cannot be greater than %d.\n",
+               max_matrix_channel);
+        return -1;
+    }
+
+    if (s->max_channel != s->max_matrix_channel) {
+        av_log(m->avctx, AV_LOG_ERROR,
+               "Max channel must be equal max matrix channel.\n");
+        return -1;
+    }
+
+    /* This should happen for TrueHD streams with >6 channels and MLP's noise
+     * type. It is not yet known if this is allowed. */
+    if (s->max_channel > MAX_MATRIX_CHANNEL_MLP && !s->noise_type) {
+        av_log(m->avctx, AV_LOG_ERROR,
+               "Number of channels %d is larger than the maximum supported "
+               "by the decoder. %s\n", s->max_channel+2, sample_message);
+        return -1;
+    }
+
     if (s->min_channel > s->max_channel) {
         av_log(m->avctx, AV_LOG_ERROR,
                "Substream min channel cannot be greater than max channel.\n");
@@ -510,6 +545,9 @@ static int read_matrix_params(MLPDecodeContext *m, unsigned int substr, GetBitCo
 {
     SubStream *s = &m->substream[substr];
     unsigned int mat, ch;
+    const int max_primitive_matrices = m->avctx->codec_id == CODEC_ID_MLP
+                                     ? MAX_MATRICES_MLP
+                                     : MAX_MATRICES_TRUEHD;
 
     if (m->matrix_changed++ > 1) {
         av_log(m->avctx, AV_LOG_ERROR, "Matrices may change only once per access unit.\n");
@@ -518,6 +556,13 @@ static int read_matrix_params(MLPDecodeContext *m, unsigned int substr, GetBitCo
 
     s->num_primitive_matrices = get_bits(gbp, 4);
 
+    if (s->num_primitive_matrices > max_primitive_matrices) {
+        av_log(m->avctx, AV_LOG_ERROR,
+               "Number of primitive matrices cannot be greater than %d.\n",
+               max_primitive_matrices);
+        return -1;
+    }
+
     for (mat = 0; mat < s->num_primitive_matrices; mat++) {
         int frac_bits, max_chan;
         s->matrix_out_ch[mat] = get_bits(gbp, 4);
@@ -589,10 +634,10 @@ static int read_channel_params(MLPDecodeContext *m, unsigned int substr,
         return -1;
     }
     /* The FIR and IIR filters must have the same precision.
-        * To simplify the filtering code, only the precision of the
-        * FIR filter is considered. If only the IIR filter is employed,
-        * the FIR filter precision is set to that of the IIR filter, so
-        * that the filtering code can use it. */
+     * To simplify the filtering code, only the precision of the
+     * FIR filter is considered. If only the IIR filter is employed,
+     * the FIR filter precision is set to that of the IIR filter, so
+     * that the filtering code can use it. */
     if (!fir->order && iir->order)
         fir->shift = iir->shift;
 
@@ -673,44 +718,25 @@ static void filter_channel(MLPDecodeContext *m, unsigned int substr,
                            unsigned int channel)
 {
     SubStream *s = &m->substream[substr];
-    int32_t firbuf[MAX_BLOCKSIZE + MAX_FIR_ORDER];
-    int32_t iirbuf[MAX_BLOCKSIZE + MAX_IIR_ORDER];
+    int32_t fir_state_buffer[MAX_BLOCKSIZE + MAX_FIR_ORDER];
+    int32_t iir_state_buffer[MAX_BLOCKSIZE + MAX_IIR_ORDER];
+    int32_t *firbuf = fir_state_buffer + MAX_BLOCKSIZE;
+    int32_t *iirbuf = iir_state_buffer + MAX_BLOCKSIZE;
     FilterParams *fir = &m->channel_params[channel].filter_params[FIR];
     FilterParams *iir = &m->channel_params[channel].filter_params[IIR];
     unsigned int filter_shift = fir->shift;
     int32_t mask = MSB_MASK(s->quant_step_size[channel]);
-    int index = MAX_BLOCKSIZE;
-    int i;
 
-    memcpy(&firbuf[index], fir->state, MAX_FIR_ORDER * sizeof(int32_t));
-    memcpy(&iirbuf[index], iir->state, MAX_IIR_ORDER * sizeof(int32_t));
+    memcpy(firbuf, fir->state, MAX_FIR_ORDER * sizeof(int32_t));
+    memcpy(iirbuf, iir->state, MAX_IIR_ORDER * sizeof(int32_t));
 
-    for (i = 0; i < s->blocksize; i++) {
-        int32_t residual = m->sample_buffer[i + s->blockpos][channel];
-        unsigned int order;
-        int64_t accum = 0;
-        int32_t result;
-
-        /* TODO: Move this code to DSPContext? */
-
-        for (order = 0; order < fir->order; order++)
-            accum += (int64_t) firbuf[index + order] * fir->coeff[order];
-        for (order = 0; order < iir->order; order++)
-            accum += (int64_t) iirbuf[index + order] * iir->coeff[order];
-
-        accum  = accum >> filter_shift;
-        result = (accum + residual) & mask;
-
-        --index;
-
-        firbuf[index] = result;
-        iirbuf[index] = result - accum;
-
-        m->sample_buffer[i + s->blockpos][channel] = result;
-    }
+    m->dsp.mlp_filter_channel(firbuf, fir->coeff, fir->order,
+                              iirbuf, iir->coeff, iir->order,
+                              filter_shift, mask, s->blocksize,
+                              &m->sample_buffer[s->blockpos][channel]);
 
-    memcpy(fir->state, &firbuf[index], MAX_FIR_ORDER * sizeof(int32_t));
-    memcpy(iir->state, &iirbuf[index], MAX_IIR_ORDER * sizeof(int32_t));
+    memcpy(fir->state, firbuf - s->blocksize, MAX_FIR_ORDER * sizeof(int32_t));
+    memcpy(iir->state, iirbuf - s->blocksize, MAX_IIR_ORDER * sizeof(int32_t));
 }
 
 /** Read a block of PCM residual data (or actual if no filtering active). */
@@ -849,6 +875,7 @@ static void rematrix_channels(MLPDecodeContext *m, unsigned int substr)
         /* TODO: DSPContext? */
 
         for (i = 0; i < s->blockpos; i++) {
+            int32_t bypassed_lsb = m->bypassed_lsbs[i][mat];
             int32_t *samples = m->sample_buffer[i];
             int64_t accum = 0;
 
@@ -861,8 +888,7 @@ static void rematrix_channels(MLPDecodeContext *m, unsigned int substr)
                 index += index2;
             }
 
-            samples[dest_ch] = ((accum >> 14) & mask)
-                             + m->bypassed_lsbs[i][mat];
+            samples[dest_ch] = ((accum >> 14) & mask) + bypassed_lsb;
         }
     }
 }