]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/vorbis_dec.c
Show profile in avcodec_string().
[ffmpeg] / libavcodec / vorbis_dec.c
index f9dd08833f0d6db16c165d14d3c1b78e13a16f10..749e9a939681cec052a63f3540f5a690af989cfd 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * @file libavcodec/vorbis_dec.c
+ * @file
  * Vorbis I decoder
  * @author Denes Balatoni  ( dbalatoni programozo hu )
  *
@@ -30,6 +30,7 @@
 #include "avcodec.h"
 #include "get_bits.h"
 #include "dsputil.h"
+#include "fft.h"
 
 #include "vorbis.h"
 #include "xiph.h"
@@ -60,8 +61,8 @@ typedef struct vorbis_floor0_s vorbis_floor0;
 typedef struct vorbis_floor1_s vorbis_floor1;
 struct vorbis_context_s;
 typedef
-uint_fast8_t (* vorbis_floor_decode_func)
-             (struct vorbis_context_s *, vorbis_floor_data *, float *);
+int (* vorbis_floor_decode_func)
+    (struct vorbis_context_s *, vorbis_floor_data *, float *);
 typedef struct {
     uint_fast8_t floor_type;
     vorbis_floor_decode_func decode;
@@ -80,8 +81,7 @@ typedef struct {
         } t0;
         struct vorbis_floor1_s {
             uint_fast8_t partitions;
-            uint_fast8_t maximum_class;
-            uint_fast8_t partition_class[32];
+            uint8_t      partition_class[32];
             uint_fast8_t class_dimensions[16];
             uint_fast8_t class_subclasses[16];
             uint_fast8_t class_masterbook[16];
@@ -97,11 +97,13 @@ typedef struct {
     uint_fast16_t type;
     uint_fast32_t begin;
     uint_fast32_t end;
-    uint_fast32_t partition_size;
+    unsigned      partition_size;
     uint_fast8_t  classifications;
     uint_fast8_t  classbook;
     int_fast16_t  books[64][8];
     uint_fast8_t  maxpass;
+    uint_fast16_t ptns_to_read;
+    uint8_t *classifs;
 } vorbis_residue;
 
 typedef struct {
@@ -160,6 +162,20 @@ typedef struct vorbis_context_s {
 #define BARK(x) \
     (13.1f * atan(0.00074f * (x)) + 2.24f * atan(1.85e-8f * (x) * (x)) + 1e-4f * (x))
 
+static const char idx_err_str[] = "Index value %d out of range (0 - %d) for %s at %s:%i\n";
+#define VALIDATE_INDEX(idx, limit) \
+    if (idx >= limit) {\
+        av_log(vc->avccontext, AV_LOG_ERROR,\
+               idx_err_str,\
+               (int)(idx), (int)(limit - 1), #idx, __FILE__, __LINE__);\
+        return -1;\
+    }
+#define GET_VALIDATED_INDEX(idx, bits, limit) \
+    {\
+        idx = get_bits(gb, bits);\
+        VALIDATE_INDEX(idx, limit)\
+    }
+
 static float vorbisfloat2float(uint_fast32_t val)
 {
     double mant = val & 0x1fffff;
@@ -180,6 +196,8 @@ static void vorbis_free(vorbis_context *vc)
     av_freep(&vc->channel_floors);
     av_freep(&vc->saved);
 
+    for (i = 0; i < vc->residue_count; i++)
+        av_free(vc->residues[i].classifs);
     av_freep(&vc->residues);
     av_freep(&vc->modes);
 
@@ -222,6 +240,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc)
     uint8_t  *tmp_vlc_bits;
     uint32_t *tmp_vlc_codes;
     GetBitContext *gb = &vc->gb;
+    uint_fast16_t *codebook_multiplicands;
 
     vc->codebook_count = get_bits(gb, 8) + 1;
 
@@ -230,6 +249,7 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc)
     vc->codebooks = av_mallocz(vc->codebook_count * sizeof(vorbis_codebook));
     tmp_vlc_bits  = av_mallocz(V_MAX_VLCS * sizeof(uint8_t));
     tmp_vlc_codes = av_mallocz(V_MAX_VLCS * sizeof(uint32_t));
+    codebook_multiplicands = av_malloc(V_MAX_VLCS * sizeof(*codebook_multiplicands));
 
     for (cb = 0; cb < vc->codebook_count; ++cb) {
         vorbis_codebook *codebook_setup = &vc->codebooks[cb];
@@ -322,7 +342,6 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc)
         if (codebook_setup->lookup_type == 1) {
             uint_fast16_t i, j, k;
             uint_fast16_t codebook_lookup_values = ff_vorbis_nth_root(entries, codebook_setup->dimensions);
-            uint_fast16_t codebook_multiplicands[codebook_lookup_values];
 
             float codebook_minimum_value = vorbisfloat2float(get_bits_long(gb, 32));
             float codebook_delta_value   = vorbisfloat2float(get_bits_long(gb, 32));
@@ -406,12 +425,14 @@ static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc)
 
     av_free(tmp_vlc_bits);
     av_free(tmp_vlc_codes);
+    av_free(codebook_multiplicands);
     return 0;
 
 // Error:
 error:
     av_free(tmp_vlc_bits);
     av_free(tmp_vlc_codes);
+    av_free(codebook_multiplicands);
     return -1;
 }
 
@@ -438,15 +459,15 @@ static int vorbis_parse_setup_hdr_tdtransforms(vorbis_context *vc)
 
 // Process floors part
 
-static uint_fast8_t vorbis_floor0_decode(vorbis_context *vc,
-                                         vorbis_floor_data *vfu, float *vec);
+static int vorbis_floor0_decode(vorbis_context *vc,
+                                vorbis_floor_data *vfu, float *vec);
 static void create_map(vorbis_context *vc, uint_fast8_t floor_number);
-static uint_fast8_t vorbis_floor1_decode(vorbis_context *vc,
-                                         vorbis_floor_data *vfu, float *vec);
+static int vorbis_floor1_decode(vorbis_context *vc,
+                                vorbis_floor_data *vfu, float *vec);
 static int vorbis_parse_setup_hdr_floors(vorbis_context *vc)
 {
     GetBitContext *gb = &vc->gb;
-    uint_fast16_t i,j,k;
+    int i,j,k;
 
     vc->floor_count = get_bits(gb, 6) + 1;
 
@@ -460,7 +481,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc)
         AV_DEBUG(" %d. floor type %d \n", i, floor_setup->floor_type);
 
         if (floor_setup->floor_type == 1) {
-            uint_fast8_t  maximum_class = 0;
+            int maximum_class = -1;
             uint_fast8_t  rangebits;
             uint_fast16_t floor1_values = 2;
 
@@ -481,8 +502,6 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc)
 
             AV_DEBUG(" maximum class %d \n", maximum_class);
 
-            floor_setup->data.t1.maximum_class = maximum_class;
-
             for (j = 0; j <= maximum_class; ++j) {
                 floor_setup->data.t1.class_dimensions[j] = get_bits(gb, 3) + 1;
                 floor_setup->data.t1.class_subclasses[j] = get_bits(gb, 2);
@@ -490,22 +509,15 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc)
                 AV_DEBUG(" %d floor %d class dim: %d subclasses %d \n", i, j, floor_setup->data.t1.class_dimensions[j], floor_setup->data.t1.class_subclasses[j]);
 
                 if (floor_setup->data.t1.class_subclasses[j]) {
-                    int bits = get_bits(gb, 8);
-                    if (bits >= vc->codebook_count) {
-                        av_log(vc->avccontext, AV_LOG_ERROR, "Masterbook index %d is out of range.\n", bits);
-                        return -1;
-                    }
-                    floor_setup->data.t1.class_masterbook[j] = bits;
+                    GET_VALIDATED_INDEX(floor_setup->data.t1.class_masterbook[j], 8, vc->codebook_count)
 
                     AV_DEBUG("   masterbook: %d \n", floor_setup->data.t1.class_masterbook[j]);
                 }
 
                 for (k = 0; k < (1 << floor_setup->data.t1.class_subclasses[j]); ++k) {
                     int16_t bits = get_bits(gb, 8) - 1;
-                    if (bits != -1 && bits >= vc->codebook_count) {
-                        av_log(vc->avccontext, AV_LOG_ERROR, "Subclass book index %d is out of range.\n", bits);
-                        return -1;
-                    }
+                    if (bits != -1)
+                        VALIDATE_INDEX(bits, vc->codebook_count)
                     floor_setup->data.t1.subclass_books[j][k] = bits;
 
                     AV_DEBUG("    book %d. : %d \n", k, floor_setup->data.t1.subclass_books[j][k]);
@@ -564,9 +576,7 @@ static int vorbis_parse_setup_hdr_floors(vorbis_context *vc)
                 int idx;
                 uint_fast8_t book_idx;
                 for (idx = 0; idx < floor_setup->data.t0.num_books; ++idx) {
-                    book_idx = get_bits(gb, 8);
-                    if (book_idx >= vc->codebook_count)
-                        return -1;
+                    GET_VALIDATED_INDEX(book_idx, 8, vc->codebook_count)
                     floor_setup->data.t0.book_list[idx] = book_idx;
                     if (vc->codebooks[book_idx].dimensions > max_codebook_dim)
                         max_codebook_dim = vc->codebooks[book_idx].dimensions;
@@ -643,18 +653,22 @@ static int vorbis_parse_setup_hdr_residues(vorbis_context *vc)
         res_setup->partition_size = get_bits(gb, 24) + 1;
         /* Validations to prevent a buffer overflow later. */
         if (res_setup->begin>res_setup->end ||
-            res_setup->end>vc->blocksize[1] / (res_setup->type == 2 ? 1 : 2) ||
+            res_setup->end > vc->avccontext->channels * vc->blocksize[1] / (res_setup->type == 2 ? 1 : 2) ||
             (res_setup->end-res_setup->begin) / res_setup->partition_size > V_MAX_PARTITIONS) {
-            av_log(vc->avccontext, AV_LOG_ERROR, "partition out of bounds: type, begin, end, size, blocksize: %"PRIdFAST16", %"PRIdFAST32", %"PRIdFAST32", %"PRIdFAST32", %"PRIdFAST32"\n", res_setup->type, res_setup->begin, res_setup->end, res_setup->partition_size, vc->blocksize[1] / 2);
+            av_log(vc->avccontext, AV_LOG_ERROR, "partition out of bounds: type, begin, end, size, blocksize: %"PRIdFAST16", %"PRIdFAST32", %"PRIdFAST32", %u, %"PRIdFAST32"\n", res_setup->type, res_setup->begin, res_setup->end, res_setup->partition_size, vc->blocksize[1] / 2);
             return -1;
         }
 
         res_setup->classifications = get_bits(gb, 6) + 1;
-        res_setup->classbook = get_bits(gb, 8);
-        if (res_setup->classbook >= vc->codebook_count) {
-            av_log(vc->avccontext, AV_LOG_ERROR, "classbook value %d out of range. \n", res_setup->classbook);
-            return -1;
-        }
+        GET_VALIDATED_INDEX(res_setup->classbook, 8, vc->codebook_count)
+
+        res_setup->ptns_to_read =
+            (res_setup->end - res_setup->begin) / res_setup->partition_size;
+        res_setup->classifs = av_malloc(res_setup->ptns_to_read *
+                                        vc->audio_channels *
+                                        sizeof(*res_setup->classifs));
+        if (!res_setup->classifs)
+            return AVERROR(ENOMEM);
 
         AV_DEBUG("    begin %d end %d part.size %d classif.s %d classbook %d \n", res_setup->begin, res_setup->end, res_setup->partition_size,
           res_setup->classifications, res_setup->classbook);
@@ -673,12 +687,7 @@ static int vorbis_parse_setup_hdr_residues(vorbis_context *vc)
         for (j = 0; j < res_setup->classifications; ++j) {
             for (k = 0; k < 8; ++k) {
                 if (cascade[j]&(1 << k)) {
-                    int bits = get_bits(gb, 8);
-                    if (bits >= vc->codebook_count) {
-                        av_log(vc->avccontext, AV_LOG_ERROR, "book value %d out of range. \n", bits);
-                        return -1;
-                    }
-                    res_setup->books[j][k] = bits;
+                    GET_VALIDATED_INDEX(res_setup->books[j][k], 8, vc->codebook_count)
 
                     AV_DEBUG("     %d class casscade depth %d book: %d \n", j, k, res_setup->books[j][k]);
 
@@ -723,16 +732,8 @@ static int vorbis_parse_setup_hdr_mappings(vorbis_context *vc)
             mapping_setup->magnitude      = av_mallocz(mapping_setup->coupling_steps * sizeof(uint_fast8_t));
             mapping_setup->angle          = av_mallocz(mapping_setup->coupling_steps * sizeof(uint_fast8_t));
             for (j = 0; j < mapping_setup->coupling_steps; ++j) {
-                mapping_setup->magnitude[j] = get_bits(gb, ilog(vc->audio_channels - 1));
-                mapping_setup->angle[j] = get_bits(gb, ilog(vc->audio_channels - 1));
-                if (mapping_setup->magnitude[j] >= vc->audio_channels) {
-                    av_log(vc->avccontext, AV_LOG_ERROR, "magnitude channel %d out of range. \n", mapping_setup->magnitude[j]);
-                    return -1;
-                }
-                if (mapping_setup->angle[j] >= vc->audio_channels) {
-                    av_log(vc->avccontext, AV_LOG_ERROR, "angle channel %d out of range. \n", mapping_setup->angle[j]);
-                    return -1;
-                }
+                GET_VALIDATED_INDEX(mapping_setup->magnitude[j], ilog(vc->audio_channels - 1), vc->audio_channels)
+                GET_VALIDATED_INDEX(mapping_setup->angle[j],     ilog(vc->audio_channels - 1), vc->audio_channels)
             }
         } else {
             mapping_setup->coupling_steps = 0;
@@ -752,20 +753,9 @@ static int vorbis_parse_setup_hdr_mappings(vorbis_context *vc)
         }
 
         for (j = 0; j < mapping_setup->submaps; ++j) {
-            int bits;
             skip_bits(gb, 8); // FIXME check?
-            bits = get_bits(gb, 8);
-            if (bits >= vc->floor_count) {
-                av_log(vc->avccontext, AV_LOG_ERROR, "submap floor value %d out of range. \n", bits);
-                return -1;
-            }
-            mapping_setup->submap_floor[j] = bits;
-            bits = get_bits(gb, 8);
-            if (bits >= vc->residue_count) {
-                av_log(vc->avccontext, AV_LOG_ERROR, "submap residue value %d out of range. \n", bits);
-                return -1;
-            }
-            mapping_setup->submap_residue[j] = bits;
+            GET_VALIDATED_INDEX(mapping_setup->submap_floor[j],   8, vc->floor_count)
+            GET_VALIDATED_INDEX(mapping_setup->submap_residue[j], 8, vc->residue_count)
 
             AV_DEBUG("   %d mapping %d submap : floor %d, residue %d \n", i, j, mapping_setup->submap_floor[j], mapping_setup->submap_residue[j]);
         }
@@ -827,11 +817,7 @@ static int vorbis_parse_setup_hdr_modes(vorbis_context *vc)
         mode_setup->blockflag     = get_bits1(gb);
         mode_setup->windowtype    = get_bits(gb, 16); //FIXME check
         mode_setup->transformtype = get_bits(gb, 16); //FIXME check
-        mode_setup->mapping       = get_bits(gb,  8);
-        if (mode_setup->mapping >= vc->mapping_count) {
-            av_log(vc->avccontext, AV_LOG_ERROR, "mode mapping value %d out of range. \n", mode_setup->mapping);
-            return -1;
-        }
+        GET_VALIDATED_INDEX(mode_setup->mapping, 8, vc->mapping_count);
 
         AV_DEBUG(" %d mode: blockflag %d, windowtype %d, transformtype %d, mapping %d \n", i, mode_setup->blockflag, mode_setup->windowtype, mode_setup->transformtype, mode_setup->mapping);
     }
@@ -978,7 +964,7 @@ static av_cold int vorbis_decode_init(AVCodecContext *avccontext)
     }
 
     if (!headers_len) {
-        av_log(avccontext, AV_LOG_ERROR, "Extradata corrupt.\n");
+        av_log(avccontext, AV_LOG_ERROR, "Extradata missing.\n");
         return -1;
     }
 
@@ -1012,10 +998,15 @@ static av_cold int vorbis_decode_init(AVCodecContext *avccontext)
         return -1;
     }
 
+    if (vc->audio_channels > 8)
+        avccontext->channel_layout = 0;
+    else
+        avccontext->channel_layout = ff_vorbis_channel_layouts[vc->audio_channels - 1];
+
     avccontext->channels    = vc->audio_channels;
     avccontext->sample_rate = vc->audio_samplerate;
     avccontext->frame_size  = FFMIN(vc->blocksize[0], vc->blocksize[1]) >> 2;
-    avccontext->sample_fmt  = SAMPLE_FMT_S16;
+    avccontext->sample_fmt  = AV_SAMPLE_FMT_S16;
 
     return 0 ;
 }
@@ -1024,8 +1015,8 @@ static av_cold int vorbis_decode_init(AVCodecContext *avccontext)
 
 // Read and decode floor
 
-static uint_fast8_t vorbis_floor0_decode(vorbis_context *vc,
-                                         vorbis_floor_data *vfu, float *vec)
+static int vorbis_floor0_decode(vorbis_context *vc,
+                                vorbis_floor_data *vfu, float *vec)
 {
     vorbis_floor0 *vf = &vfu->t0;
     float *lsp = vf->lsp;
@@ -1049,6 +1040,9 @@ static uint_fast8_t vorbis_floor0_decode(vorbis_context *vc,
         }
         AV_DEBUG("floor0 dec: booknumber: %u\n", book_idx);
         codebook = vc->codebooks[vf->book_list[book_idx]];
+        /* Invalid codebook! */
+        if (!codebook.codevectors)
+            return -1;
 
         while (lsp_len<vf->order) {
             int vec_off;
@@ -1134,16 +1128,16 @@ static uint_fast8_t vorbis_floor0_decode(vorbis_context *vc,
     return 0;
 }
 
-static uint_fast8_t vorbis_floor1_decode(vorbis_context *vc,
-                                         vorbis_floor_data *vfu, float *vec)
+static int vorbis_floor1_decode(vorbis_context *vc,
+                                vorbis_floor_data *vfu, float *vec)
 {
     vorbis_floor1 *vf = &vfu->t1;
     GetBitContext *gb = &vc->gb;
     uint_fast16_t range_v[4] = { 256, 128, 86, 64 };
     uint_fast16_t range = range_v[vf->multiplier-1];
-    uint_fast16_t floor1_Y[vf->x_list_dim];
-    uint_fast16_t floor1_Y_final[vf->x_list_dim];
-    int floor1_flag[vf->x_list_dim];
+    uint_fast16_t floor1_Y[258];
+    uint_fast16_t floor1_Y_final[258];
+    int floor1_flag[258];
     uint_fast8_t class_;
     uint_fast8_t cdim;
     uint_fast8_t cbits;
@@ -1152,8 +1146,8 @@ static uint_fast8_t vorbis_floor1_decode(vorbis_context *vc,
     int_fast16_t book;
     uint_fast16_t offset;
     uint_fast16_t i,j;
-    /*u*/int_fast16_t adx, ady, off, predicted; // WTF ? dy/adx =  (unsigned)dy/adx ?
-    int_fast16_t dy, err;
+    int_fast16_t adx, ady, dy, off, predicted;
+    int_fast32_t err;
 
 
     if (!get_bits1(gb)) // silence
@@ -1216,7 +1210,7 @@ static uint_fast8_t vorbis_floor1_decode(vorbis_context *vc,
         adx = vf->list[high_neigh_offs].x - vf->list[low_neigh_offs].x;
         ady = FFABS(dy);
         err = ady * (vf->list[i].x - vf->list[low_neigh_offs].x);
-        off = (int16_t)err / (int16_t)adx;
+        off = err / adx;
         if (dy < 0) {
             predicted = floor1_Y_final[low_neigh_offs] - off;
         } else {
@@ -1277,9 +1271,8 @@ static av_always_inline int vorbis_residue_decode_internal(vorbis_context *vc,
 {
     GetBitContext *gb = &vc->gb;
     uint_fast8_t c_p_c = vc->codebooks[vr->classbook].dimensions;
-    uint_fast16_t n_to_read = vr->end-vr->begin;
-    uint_fast16_t ptns_to_read = n_to_read/vr->partition_size;
-    uint_fast8_t classifs[ptns_to_read*vc->audio_channels];
+    uint_fast16_t ptns_to_read = vr->ptns_to_read;
+    uint8_t *classifs = vr->classifs;
     uint_fast8_t pass;
     uint_fast8_t ch_used;
     uint_fast8_t i,j,l;
@@ -1475,12 +1468,12 @@ static int vorbis_parse_audio_packet(vorbis_context *vc)
     uint_fast8_t blockflag;
     uint_fast16_t blocksize;
     int_fast32_t i,j;
-    uint_fast8_t no_residue[vc->audio_channels];
-    uint_fast8_t do_not_decode[vc->audio_channels];
+    uint_fast8_t no_residue[255];
+    uint_fast8_t do_not_decode[255];
     vorbis_mapping *mapping;
     float *ch_res_ptr   = vc->channel_residues;
     float *ch_floor_ptr = vc->channel_floors;
-    uint_fast8_t res_chan[vc->audio_channels];
+    uint_fast8_t res_chan[255];
     uint_fast8_t res_num = 0;
     int_fast16_t retlen  = 0;
     float fadd_bias = vc->add_bias;
@@ -1493,11 +1486,7 @@ static int vorbis_parse_audio_packet(vorbis_context *vc)
     if (vc->mode_count == 1) {
         mode_number = 0;
     } else {
-        mode_number = get_bits(gb, ilog(vc->mode_count-1));
-    }
-    if (mode_number >= vc->mode_count) {
-        av_log(vc->avccontext, AV_LOG_ERROR, "mode number %d out of range.\n", mode_number);
-        return -1;
+        GET_VALIDATED_INDEX(mode_number, ilog(vc->mode_count-1), vc->mode_count)
     }
     vc->mode_number = mode_number;
     mapping = &vc->mappings[vc->modes[mode_number].mapping];
@@ -1516,13 +1505,20 @@ static int vorbis_parse_audio_packet(vorbis_context *vc)
 
     for (i = 0; i < vc->audio_channels; ++i) {
         vorbis_floor *floor;
+        int ret;
         if (mapping->submaps > 1) {
             floor = &vc->floors[mapping->submap_floor[mapping->mux[i]]];
         } else {
             floor = &vc->floors[mapping->submap_floor[0]];
         }
 
-        no_residue[i] = floor->decode(vc, &floor->data, ch_floor_ptr);
+        ret = floor->decode(vc, &floor->data, ch_floor_ptr);
+
+        if (ret < 0) {
+            av_log(vc->avccontext, AV_LOG_ERROR, "Invalid codebook in vorbis_floor_decode.\n");
+            return -1;
+        }
+        no_residue[i] = ret;
         ch_floor_ptr += blocksize / 2;
     }
 
@@ -1616,7 +1612,7 @@ static int vorbis_decode_frame(AVCodecContext *avccontext,
     int buf_size       = avpkt->size;
     vorbis_context *vc = avccontext->priv_data ;
     GetBitContext *gb = &(vc->gb);
-    const float *channel_ptrs[vc->audio_channels];
+    const float *channel_ptrs[255];
     int i;
 
     int_fast16_t len;
@@ -1643,8 +1639,15 @@ static int vorbis_decode_frame(AVCodecContext *avccontext,
 
     AV_DEBUG("parsed %d bytes %d bits, returned %d samples (*ch*bits) \n", get_bits_count(gb)/8, get_bits_count(gb)%8, len);
 
-    for (i = 0; i < vc->audio_channels; i++)
-        channel_ptrs[i] = vc->channel_floors + i * len;
+    if (vc->audio_channels > 8) {
+        for (i = 0; i < vc->audio_channels; i++)
+            channel_ptrs[i] = vc->channel_floors + i * len;
+    } else {
+        for (i = 0; i < vc->audio_channels; i++)
+            channel_ptrs[i] = vc->channel_floors +
+                              len * ff_vorbis_channel_layout_offsets[vc->audio_channels - 1][i];
+    }
+
     vc->dsp.float_to_int16_interleave(data, channel_ptrs, len, vc->audio_channels);
     *data_size = len * 2 * vc->audio_channels;
 
@@ -1664,7 +1667,7 @@ static av_cold int vorbis_decode_close(AVCodecContext *avccontext)
 
 AVCodec vorbis_decoder = {
     "vorbis",
-    CODEC_TYPE_AUDIO,
+    AVMEDIA_TYPE_AUDIO,
     CODEC_ID_VORBIS,
     sizeof(vorbis_context),
     vorbis_decode_init,
@@ -1672,5 +1675,6 @@ AVCodec vorbis_decoder = {
     vorbis_decode_close,
     vorbis_decode_frame,
     .long_name = NULL_IF_CONFIG_SMALL("Vorbis"),
+    .channel_layouts = ff_vorbis_channel_layouts,
 };