/**
- * @file libavcodec/vorbis_dec.c
+ * @file
* Vorbis I decoder
* @author Denes Balatoni ( dbalatoni programozo hu )
*
#include "avcodec.h"
#include "get_bits.h"
#include "dsputil.h"
+#include "fft.h"
#include "vorbis.h"
#include "xiph.h"
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;
} 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];
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 {
#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;
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);
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;
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];
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));
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;
}
// 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;
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;
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);
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]);
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;
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);
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]);
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;
}
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]);
}
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);
}
}
if (!headers_len) {
- av_log(avccontext, AV_LOG_ERROR, "Extradata corrupt.\n");
+ av_log(avccontext, AV_LOG_ERROR, "Extradata missing.\n");
return -1;
}
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 ;
}
// 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;
}
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;
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;
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
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 {
{
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;
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;
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];
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;
}
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;
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;
AVCodec vorbis_decoder = {
"vorbis",
- CODEC_TYPE_AUDIO,
+ AVMEDIA_TYPE_AUDIO,
CODEC_ID_VORBIS,
sizeof(vorbis_context),
vorbis_decode_init,
vorbis_decode_close,
vorbis_decode_frame,
.long_name = NULL_IF_CONFIG_SMALL("Vorbis"),
+ .channel_layouts = ff_vorbis_channel_layouts,
};