#define V_MAX_VLCS (1 << 16)
#define V_MAX_PARTITIONS (1 << 20)
-#undef NDEBUG
-#include <assert.h>
-
typedef struct {
uint8_t dimensions;
uint8_t lookup_type;
static int vorbis_parse_setup_hdr_codebooks(vorbis_context *vc)
{
unsigned cb;
- uint8_t *tmp_vlc_bits;
- uint32_t *tmp_vlc_codes;
+ uint8_t *tmp_vlc_bits = NULL;
+ uint32_t *tmp_vlc_codes = NULL;
GetBitContext *gb = &vc->gb;
- uint16_t *codebook_multiplicands;
+ uint16_t *codebook_multiplicands = NULL;
int ret = 0;
vc->codebook_count = get_bits(gb, 8) + 1;
tmp_vlc_bits = av_mallocz(V_MAX_VLCS * sizeof(*tmp_vlc_bits));
tmp_vlc_codes = av_mallocz(V_MAX_VLCS * sizeof(*tmp_vlc_codes));
codebook_multiplicands = av_malloc(V_MAX_VLCS * sizeof(*codebook_multiplicands));
+ if (!vc->codebooks ||
+ !tmp_vlc_bits || !tmp_vlc_codes || !codebook_multiplicands) {
+ ret = AVERROR(ENOMEM);
+ goto error;
+ }
for (cb = 0; cb < vc->codebook_count; ++cb) {
vorbis_codebook *codebook_setup = &vc->codebooks[cb];
static int vorbis_floor0_decode(vorbis_context *vc,
vorbis_floor_data *vfu, float *vec);
-static void create_map(vorbis_context *vc, unsigned floor_number);
+static int create_map(vorbis_context *vc, unsigned floor_number);
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;
- int i,j,k;
+ int i, j, k, ret;
vc->floor_count = get_bits(gb, 6) + 1;
vc->floors = av_mallocz(vc->floor_count * sizeof(*vc->floors));
+ if (!vc->floors)
+ return AVERROR(ENOMEM);
for (i = 0; i < vc->floor_count; ++i) {
vorbis_floor *floor_setup = &vc->floors[i];
floor_setup->data.t1.list = av_mallocz(floor_setup->data.t1.x_list_dim *
sizeof(*floor_setup->data.t1.list));
-
+ if (!floor_setup->data.t1.list)
+ return AVERROR(ENOMEM);
rangebits = get_bits(gb, 4);
rangemax = (1 << rangebits);
}
}
- create_map(vc, i);
+ if ((ret = create_map(vc, i)) < 0)
+ return ret;
/* codebook dim is for padding if codebook dim doesn't *
* divide order+1 then we need to read more data */
vc->residue_count = get_bits(gb, 6)+1;
vc->residues = av_mallocz(vc->residue_count * sizeof(*vc->residues));
+ if (!vc->residues)
+ return AVERROR(ENOMEM);
av_dlog(NULL, " There are %d residues. \n", vc->residue_count);
vc->mapping_count = get_bits(gb, 6)+1;
vc->mappings = av_mallocz(vc->mapping_count * sizeof(*vc->mappings));
+ if (!vc->mappings)
+ return AVERROR(ENOMEM);
av_dlog(NULL, " There are %d mappings. \n", vc->mapping_count);
sizeof(*mapping_setup->magnitude));
mapping_setup->angle = av_mallocz(mapping_setup->coupling_steps *
sizeof(*mapping_setup->angle));
+ if (!mapping_setup->angle || !mapping_setup->magnitude)
+ return AVERROR(ENOMEM);
+
for (j = 0; j < mapping_setup->coupling_steps; ++j) {
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)
if (mapping_setup->submaps>1) {
mapping_setup->mux = av_mallocz(vc->audio_channels *
sizeof(*mapping_setup->mux));
+ if (!mapping_setup->mux)
+ return AVERROR(ENOMEM);
+
for (j = 0; j < vc->audio_channels; ++j)
mapping_setup->mux[j] = get_bits(gb, 4);
}
// Process modes part
-static void create_map(vorbis_context *vc, unsigned floor_number)
+static int create_map(vorbis_context *vc, unsigned floor_number)
{
vorbis_floor *floors = vc->floors;
vorbis_floor0 *vf;
n = vc->blocksize[blockflag] / 2;
floors[floor_number].data.t0.map[blockflag] =
av_malloc((n + 1) * sizeof(int32_t)); // n + sentinel
+ if (!floors[floor_number].data.t0.map[blockflag])
+ return AVERROR(ENOMEM);
map = floors[floor_number].data.t0.map[blockflag];
vf = &floors[floor_number].data.t0;
for (idx = 0; idx <= n; ++idx) {
av_dlog(NULL, "floor0 map: map at pos %d is %d\n", idx, map[idx]);
}
+
+ return 0;
}
static int vorbis_parse_setup_hdr_modes(vorbis_context *vc)
vc->mode_count = get_bits(gb, 6) + 1;
vc->modes = av_mallocz(vc->mode_count * sizeof(*vc->modes));
+ if (!vc->modes)
+ return AVERROR(ENOMEM);
av_dlog(NULL, " There are %d modes.\n", vc->mode_count);
vc->channel_residues = av_malloc((vc->blocksize[1] / 2) * vc->audio_channels * sizeof(*vc->channel_residues));
vc->saved = av_mallocz((vc->blocksize[1] / 4) * vc->audio_channels * sizeof(*vc->saved));
+ if (!vc->channel_residues || !vc->saved)
+ return AVERROR(ENOMEM);
+
vc->previous_window = 0;
ff_mdct_init(&vc->mdct[0], bl0, 1, -1.0);
return 0;
}
+static av_always_inline int setup_classifs(vorbis_context *vc,
+ vorbis_residue *vr,
+ uint8_t *do_not_decode,
+ unsigned ch_used,
+ int partition_count)
+{
+ int p, j, i;
+ unsigned c_p_c = vc->codebooks[vr->classbook].dimensions;
+ unsigned inverse_class = ff_inverse[vr->classifications];
+ unsigned temp, temp2;
+ for (p = 0, j = 0; j < ch_used; ++j) {
+ if (!do_not_decode[j]) {
+ temp = get_vlc2(&vc->gb, vc->codebooks[vr->classbook].vlc.table,
+ vc->codebooks[vr->classbook].nb_bits, 3);
+
+ av_dlog(NULL, "Classword: %u\n", temp);
+
+ if (temp <= 65536) {
+ for (i = partition_count + c_p_c - 1; i >= partition_count; i--) {
+ temp2 = (((uint64_t)temp) * inverse_class) >> 32;
+
+ if (i < vr->ptns_to_read)
+ vr->classifs[p + i] = temp - temp2 * vr->classifications;
+ temp = temp2;
+ }
+ } else {
+ for (i = partition_count + c_p_c - 1; i >= partition_count; i--) {
+ temp2 = temp / vr->classifications;
+
+ if (i < vr->ptns_to_read)
+ vr->classifs[p + i] = temp - temp2 * vr->classifications;
+ temp = temp2;
+ }
+ }
+ }
+ p += vr->ptns_to_read;
+ }
+ return 0;
+}
// Read and decode residue
static av_always_inline int vorbis_residue_decode_internal(vorbis_context *vc,
{
GetBitContext *gb = &vc->gb;
unsigned c_p_c = vc->codebooks[vr->classbook].dimensions;
- unsigned ptns_to_read = vr->ptns_to_read;
uint8_t *classifs = vr->classifs;
unsigned pass, ch_used, i, j, k, l;
unsigned max_output = (ch - 1) * vlen;
+ int ptns_to_read = vr->ptns_to_read;
if (vr_type == 2) {
for (j = 1; j < ch; ++j)
if (max_output > ch_left * vlen) {
av_log(vc->avctx, AV_LOG_ERROR, "Insufficient output buffer\n");
- return -1;
+ return AVERROR_INVALIDDATA;
}
av_dlog(NULL, " residue type 0/1/2 decode begin, ch: %d cpc %d \n", ch, c_p_c);
for (pass = 0; pass <= vr->maxpass; ++pass) { // FIXME OPTIMIZE?
- uint16_t voffset, partition_count, j_times_ptns_to_read;
+ int voffset, partition_count, j_times_ptns_to_read;
voffset = vr->begin;
for (partition_count = 0; partition_count < ptns_to_read;) { // SPEC error
if (!pass) {
- unsigned inverse_class = ff_inverse[vr->classifications];
- for (j_times_ptns_to_read = 0, j = 0; j < ch_used; ++j) {
- if (!do_not_decode[j]) {
- unsigned temp = get_vlc2(gb, vc->codebooks[vr->classbook].vlc.table,
- vc->codebooks[vr->classbook].nb_bits, 3);
-
- av_dlog(NULL, "Classword: %u\n", temp);
-
- assert(vr->classifications > 1 && temp <= 65536); //needed for inverse[]
- for (i = 0; i < c_p_c; ++i) {
- unsigned temp2;
-
- temp2 = (((uint64_t)temp) * inverse_class) >> 32;
- if (partition_count + c_p_c - 1 - i < ptns_to_read)
- classifs[j_times_ptns_to_read + partition_count + c_p_c - 1 - i] = temp - temp2 * vr->classifications;
- temp = temp2;
- }
- }
- j_times_ptns_to_read += ptns_to_read;
- }
+ setup_classifs(vc, vr, do_not_decode, ch_used, partition_count);
}
for (i = 0; (i < c_p_c) && (partition_count < ptns_to_read); ++i) {
for (j_times_ptns_to_read = 0, j = 0; j < ch_used; ++j) {
residue = &vc->residues[mapping->submap_residue[i]];
if (ch_left < ch) {
av_log(vc->avctx, AV_LOG_ERROR, "Too many channels in vorbis_floor_decode.\n");
- return -1;
+ return AVERROR_INVALIDDATA;
}
if (ch) {
ret = vorbis_residue_decode(vc, residue, ch, do_not_decode, ch_res_ptr, vlen, ch_left);
/* get output buffer */
frame->nb_samples = vc->blocksize[1] / 2;
- if ((ret = ff_get_buffer(avctx, frame)) < 0) {
+ if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) {
av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
return ret;
}
if (!vc->first_frame) {
vc->first_frame = 1;
*got_frame_ptr = 0;
+ av_frame_unref(frame);
return buf_size;
}
AVCodec ff_vorbis_decoder = {
.name = "vorbis",
+ .long_name = NULL_IF_CONFIG_SMALL("Vorbis"),
.type = AVMEDIA_TYPE_AUDIO,
.id = AV_CODEC_ID_VORBIS,
.priv_data_size = sizeof(vorbis_context),
.decode = vorbis_decode_frame,
.flush = vorbis_decode_flush,
.capabilities = CODEC_CAP_DR1,
- .long_name = NULL_IF_CONFIG_SMALL("Vorbis"),
.channel_layouts = ff_vorbis_channel_layouts,
.sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },