]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/atrac9dec.c
avcodec/atrac9dec: Don't create VLCs that are never used
[ffmpeg] / libavcodec / atrac9dec.c
index 805d46f3b8089d0f4842cdf3e988532d3f190c0d..c7c6a12f010c564433c3ec81f162b0e7b5cd063b 100644 (file)
@@ -26,6 +26,8 @@
 #include "libavutil/lfg.h"
 #include "libavutil/float_dsp.h"
 
+#define ATRAC9_SF_VLC_BITS 8
+
 typedef struct ATRAC9ChannelData {
     int band_ext;
     int q_unit_cnt;
@@ -71,6 +73,8 @@ typedef struct ATRAC9BlockData {
     int cpe_base_channel;
     int is_signs[30];
 
+    int reuseable;
+
 } ATRAC9BlockData;
 
 typedef struct ATRAC9Context {
@@ -119,10 +123,7 @@ static inline int parse_gradient(ATRAC9Context *s, ATRAC9BlockData *b,
     }
     b->grad_boundary = get_bits(gb, 4);
 
-    if (grad_range[0] >= grad_range[1] || grad_range[1] > 47)
-        return AVERROR_INVALIDDATA;
-
-    if (grad_value[0] > 31 || grad_value[1] > 31)
+    if (grad_range[0] >= grad_range[1] || grad_range[1] > 31)
         return AVERROR_INVALIDDATA;
 
     if (b->grad_boundary > b->q_unit_cnt)
@@ -188,7 +189,7 @@ static inline void calc_precision(ATRAC9Context *s, ATRAC9BlockData *b,
     for (int i = 0; i < b->q_unit_cnt; i++) {
         c->precision_fine[i] = 0;
         if (c->precision_coarse[i] > 15) {
-            c->precision_fine[i] = c->precision_coarse[i] - 15;
+            c->precision_fine[i] = FFMIN(c->precision_coarse[i], 30) - 15;
             c->precision_coarse[i] = 15;
         }
     }
@@ -200,6 +201,8 @@ static inline int parse_band_ext(ATRAC9Context *s, ATRAC9BlockData *b,
     int ext_band = 0;
 
     if (b->has_band_ext) {
+        if (b->q_unit_cnt < 13 || b->q_unit_cnt > 20)
+            return AVERROR_INVALIDDATA;
         ext_band = at9_tab_band_ext_group[b->q_unit_cnt - 13][2];
         if (stereo) {
             b->channel[1].band_ext = get_bits(gb, 2);
@@ -222,8 +225,18 @@ static inline int parse_band_ext(ATRAC9Context *s, ATRAC9BlockData *b,
     b->channel[0].band_ext = get_bits(gb, 2);
     b->channel[0].band_ext = ext_band > 2 ? b->channel[0].band_ext : 4;
 
-    if (!get_bits(gb, 5))
+    if (!get_bits(gb, 5)) {
+        for (int i = 0; i <= stereo; i++) {
+            ATRAC9ChannelData *c = &b->channel[i];
+            const int count = at9_tab_band_ext_cnt[c->band_ext][ext_band];
+            for (int j = 0; j < count; j++) {
+                int len = at9_tab_band_ext_lengths[c->band_ext][ext_band][j];
+                c->band_ext_data[j] = av_clip_uintp2_c(c->band_ext_data[j], len);
+            }
+        }
+
         return 0;
+    }
 
     for (int i = 0; i <= stereo; i++) {
         ATRAC9ChannelData *c = &b->channel[i];
@@ -241,7 +254,7 @@ static inline int read_scalefactors(ATRAC9Context *s, ATRAC9BlockData *b,
                                     ATRAC9ChannelData *c, GetBitContext *gb,
                                     int channel_idx, int first_in_pkt)
 {
-    static const int mode_map[2][4] = { { 0, 1, 2, 3 }, { 0, 2, 3, 4 } };
+    static const uint8_t mode_map[2][4] = { { 0, 1, 2, 3 }, { 0, 2, 3, 4 } };
     const int mode = mode_map[channel_idx][get_bits(gb, 2)];
 
     memset(c->scalefactors, 0, sizeof(c->scalefactors));
@@ -261,7 +274,8 @@ static inline int read_scalefactors(ATRAC9Context *s, ATRAC9BlockData *b,
         c->scalefactors[0] = get_bits(gb, len);
 
         for (int i = 1; i < b->band_ext_q_unit; i++) {
-            int val = c->scalefactors[i - 1] + get_vlc2(gb, tab->table, 9, 2);
+            int val = c->scalefactors[i - 1] + get_vlc2(gb, tab->table,
+                                                        ATRAC9_SF_VLC_BITS, 1);
             c->scalefactors[i] = val & ((1 << len) - 1);
         }
 
@@ -291,7 +305,7 @@ static inline int read_scalefactors(ATRAC9Context *s, ATRAC9BlockData *b,
         const VLC *tab = &s->sf_vlc[1][len];
 
         for (int i = 0; i < unit_cnt; i++) {
-            int dist = get_vlc2(gb, tab->table, 9, 2);
+            int dist = get_vlc2(gb, tab->table, ATRAC9_SF_VLC_BITS, 1);
             c->scalefactors[i] = baseline[i] + dist;
         }
 
@@ -314,7 +328,8 @@ static inline int read_scalefactors(ATRAC9Context *s, ATRAC9BlockData *b,
         c->scalefactors[0] = get_bits(gb, len);
 
         for (int i = 1; i < unit_cnt; i++) {
-            int val = c->scalefactors[i - 1] + get_vlc2(gb, tab->table, 9, 2);
+            int val = c->scalefactors[i - 1] + get_vlc2(gb, tab->table,
+                                                        ATRAC9_SF_VLC_BITS, 1);
             c->scalefactors[i] = val & ((1 << len) - 1);
         }
 
@@ -400,7 +415,7 @@ static inline void read_coeffs_coarse(ATRAC9Context *s, ATRAC9BlockData *b,
             const int groups = bands >> huff->value_cnt_pow;
 
             for (int j = 0; j < groups; j++) {
-                uint16_t val = get_vlc2(gb, tab->table, 9, huff->max_bit_size);
+                uint16_t val = get_vlc2(gb, tab->table, 9, 2);
 
                 for (int k = 0; k < huff->value_cnt; k++) {
                     coeffs[k] = sign_extend(val, huff->value_bits);
@@ -535,9 +550,6 @@ static inline void apply_band_extension(ATRAC9Context *s, ATRAC9BlockData *b,
         at9_q_unit_to_coeff_idx[g_units[3]],
     };
 
-    if (!b->has_band_ext || !b->has_band_ext_data)
-        return;
-
     for (int ch = 0; ch <= stereo; ch++) {
         ATRAC9ChannelData *c = &b->channel[ch];
 
@@ -668,6 +680,7 @@ static int atrac9_decode_block(ATRAC9Context *s, GetBitContext *gb,
     if (!reuse_params) {
         int stereo_band, ext_band;
         const int min_band_count = s->samplerate_idx > 7 ? 1 : 3;
+        b->reuseable = 0;
         b->band_count = get_bits(gb, 4) + min_band_count;
         b->q_unit_cnt = at9_tab_band_q_unit_map[b->band_count];
 
@@ -699,6 +712,11 @@ static int atrac9_decode_block(ATRAC9Context *s, GetBitContext *gb,
             }
             b->band_ext_q_unit = at9_tab_band_q_unit_map[ext_band];
         }
+        b->reuseable = 1;
+    }
+    if (!b->reuseable) {
+        av_log(s->avctx, AV_LOG_ERROR, "invalid block reused!\n");
+        return AVERROR_INVALIDDATA;
     }
 
     /* Calculate bit alloc gradient */
@@ -741,7 +759,9 @@ static int atrac9_decode_block(ATRAC9Context *s, GetBitContext *gb,
 
     apply_intensity_stereo(s, b, stereo);
     apply_scalefactors    (s, b, stereo);
-    apply_band_extension  (s, b, stereo);
+
+    if (b->has_band_ext && b->has_band_ext_data)
+        apply_band_extension  (s, b, stereo);
 
 imdct:
     for (int i = 0; i <= stereo; i++) {
@@ -818,7 +838,7 @@ static av_cold int atrac9_decode_close(AVCodecContext *avctx)
                 ff_free_vlc(&s->coeff_vlc[i][j][k]);
 
     ff_mdct_end(&s->imdct);
-    av_free(s->fdsp);
+    av_freep(&s->fdsp);
 
     return 0;
 }
@@ -828,11 +848,18 @@ static av_cold int atrac9_decode_init(AVCodecContext *avctx)
     GetBitContext gb;
     ATRAC9Context *s = avctx->priv_data;
     int version, block_config_idx, superframe_idx, alloc_c_len;
+    const uint8_t (*tab)[2];
+    int ret;
 
     s->avctx = avctx;
 
     av_lfg_init(&s->lfg, 0xFBADF00D);
 
+    if (avctx->block_align <= 0) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid block align\n");
+        return AVERROR_INVALIDDATA;
+    }
+
     if (avctx->extradata_size != 12) {
         av_log(avctx, AV_LOG_ERROR, "Invalid extradata length!\n");
         return AVERROR_INVALIDDATA;
@@ -862,6 +889,7 @@ static av_cold int atrac9_decode_init(AVCodecContext *avctx)
     s->block_config = &at9_block_layout[block_config_idx];
 
     avctx->channel_layout = s->block_config->channel_layout;
+    avctx->channels       = av_get_channel_layout_nb_channels(avctx->channel_layout);
     avctx->sample_fmt     = AV_SAMPLE_FMT_FLTP;
 
     if (get_bits1(&gb)) {
@@ -905,33 +933,46 @@ static av_cold int atrac9_decode_init(AVCodecContext *avctx)
             s->alloc_curve[i - 1][j] = at9_tab_b_dist[(j * alloc_c_len) / i];
 
     /* Unsigned scalefactor VLCs */
+    tab = at9_sfb_a_tab;
     for (int i = 1; i < 7; i++) {
         const HuffmanCodebook *hf = &at9_huffman_sf_unsigned[i];
 
-        init_vlc(&s->sf_vlc[0][i], 9, hf->size, hf->bits, 1, 1, hf->codes,
-                 2, 2, 0);
+        ret = ff_init_vlc_from_lengths(&s->sf_vlc[0][i], ATRAC9_SF_VLC_BITS,
+                                       hf->size, &tab[0][1], 2,
+                                       &tab[0][0], 2, 1, 0, 0, avctx);
+        if (ret < 0)
+            return ret;
+        tab += hf->size;
     }
 
     /* Signed scalefactor VLCs */
+    tab = at9_sfb_b_tab;
     for (int i = 2; i < 6; i++) {
         const HuffmanCodebook *hf = &at9_huffman_sf_signed[i];
 
-        int nums = hf->size;
-        int16_t sym[32];
-        for (int j = 0; j < nums; j++)
-            sym[j] = sign_extend(j, hf->value_bits);
-
-        ff_init_vlc_sparse(&s->sf_vlc[1][i], 9, hf->size, hf->bits, 1, 1,
-                           hf->codes, 2, 2, sym, sizeof(*sym), sizeof(*sym), 0);
+        /* The symbols are signed integers in the range -16..15;
+         * the values in the source table are offset by 16 to make
+         * them fit into an uint8_t; the -16 reverses this shift. */
+        ret = ff_init_vlc_from_lengths(&s->sf_vlc[1][i], ATRAC9_SF_VLC_BITS,
+                                       hf->size, &tab[0][1], 2,
+                                       &tab[0][0], 2, 1, -16, 0, avctx);
+        if (ret < 0)
+            return ret;
+        tab += hf->size;
     }
 
     /* Coefficient VLCs */
+    tab = at9_coeffs_tab;
     for (int i = 0; i < 2; i++) {
-        for (int j = 0; j < 8; j++) {
-            for (int k = 0; k < 4; k++) {
+        for (int j = 2; j < 8; j++) {
+            for (int k = i; k < 4; k++) {
                 const HuffmanCodebook *hf = &at9_huffman_coeffs[i][j][k];
-                init_vlc(&s->coeff_vlc[i][j][k], 9, hf->size, hf->bits, 1, 1,
-                         hf->codes, 2, 2, 0);
+                ret = ff_init_vlc_from_lengths(&s->coeff_vlc[i][j][k], 9,
+                                               hf->size, &tab[0][1], 2,
+                                               &tab[0][0], 2, 1, 0, 0, avctx);
+                if (ret < 0)
+                    return ret;
+                tab += hf->size;
             }
         }
     }