diff options
Diffstat (limited to 'libavcodec/cook.c')
-rw-r--r-- | libavcodec/cook.c | 150 |
1 files changed, 87 insertions, 63 deletions
diff --git a/libavcodec/cook.c b/libavcodec/cook.c index bd8ad1d..c5f68c9 100644 --- a/libavcodec/cook.c +++ b/libavcodec/cook.c @@ -3,20 +3,20 @@ * Copyright (c) 2003 Sascha Sommer * Copyright (c) 2005 Benjamin Larsson * - * This file is part of Libav. + * This file is part of FFmpeg. * - * Libav is free software; you can redistribute it and/or + * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * - * Libav is distributed in the hope that it will be useful, + * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with Libav; if not, write to the Free Software + * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ @@ -47,12 +47,12 @@ #include "audiodsp.h" #include "avcodec.h" -#include "bitstream.h" +#include "get_bits.h" #include "bytestream.h" #include "fft.h" #include "internal.h" #include "sinewin.h" -#include "vlc.h" +#include "unary.h" #include "cookdata.h" @@ -125,7 +125,7 @@ typedef struct cook { AVCodecContext* avctx; AudioDSPContext adsp; - BitstreamContext bc; + GetBitContext gb; /* stream data */ int num_vectors; int samples_per_channel; @@ -166,10 +166,17 @@ static float rootpow2tab[127]; /* table generator */ static av_cold void init_pow2table(void) { + /* fast way of computing 2^i and 2^(0.5*i) for -63 <= i < 64 */ int i; + static const float exp2_tab[2] = {1, M_SQRT2}; + float exp2_val = powf(2, -63); + float root_val = powf(2, -32); for (i = -63; i < 64; i++) { - pow2tab[63 + i] = pow(2, i); - rootpow2tab[63 + i] = sqrt(pow(2, i)); + if (!(i & 1)) + root_val *= 2; + pow2tab[63 + i] = exp2_val; + rootpow2tab[63 + i] = root_val * exp2_tab[i & 1]; + exp2_val *= 2; } } @@ -220,7 +227,7 @@ static av_cold int init_cook_mlt(COOKContext *q) int j, ret; int mlt_size = q->samples_per_channel; - if ((q->mlt_window = av_malloc(mlt_size * sizeof(*q->mlt_window))) == 0) + if ((q->mlt_window = av_malloc_array(mlt_size, sizeof(*q->mlt_window))) == 0) return AVERROR(ENOMEM); /* Initialize the MLT window: simple sine window. */ @@ -230,7 +237,7 @@ static av_cold int init_cook_mlt(COOKContext *q) /* Initialize the MDCT. */ if ((ret = ff_mdct_init(&q->mdct_ctx, av_log2(mlt_size) + 1, 1, 1.0 / 32768.0))) { - av_free(q->mlt_window); + av_freep(&q->mlt_window); return ret; } av_log(q->avctx, AV_LOG_DEBUG, "MDCT initialized, order = %d.\n", @@ -304,8 +311,8 @@ static av_cold int cook_decode_close(AVCodecContext *avctx) av_log(avctx, AV_LOG_DEBUG, "Deallocating memory.\n"); /* Free allocated memory buffers. */ - av_free(q->mlt_window); - av_free(q->decoded_bytes_buffer); + av_freep(&q->mlt_window); + av_freep(&q->decoded_bytes_buffer); /* Free the transform. */ ff_mdct_end(&q->mdct_ctx); @@ -326,23 +333,19 @@ static av_cold int cook_decode_close(AVCodecContext *avctx) /** * Fill the gain array for the timedomain quantization. * - * @param bc pointer to the BitstreamContext + * @param gb pointer to the GetBitContext * @param gaininfo array[9] of gain indexes */ -static void decode_gain_info(BitstreamContext *bc, int *gaininfo) +static void decode_gain_info(GetBitContext *gb, int *gaininfo) { int i, n; - while (bitstream_read_bit(bc)) { - /* NOTHING */ - } - - n = bitstream_tell(bc) - 1; // amount of elements * 2 to update + n = get_unary(gb, 0, get_bits_left(gb)); // amount of elements*2 to update i = 0; while (n--) { - int index = bitstream_read(bc, 3); - int gain = bitstream_read_bit(bc) ? bitstream_read(bc, 4) - 7 : -1; + int index = get_bits(gb, 3); + int gain = get_bits1(gb) ? get_bits(gb, 4) - 7 : -1; while (i <= index) gaininfo[i++] = gain; @@ -362,7 +365,7 @@ static int decode_envelope(COOKContext *q, COOKSubpacket *p, { int i, j, vlc_index; - quant_index_table[0] = bitstream_read(&q->bc, 6) - 6; // This is used later in categorize + quant_index_table[0] = get_bits(&q->gb, 6) - 6; // This is used later in categorize for (i = 1; i < p->total_subbands; i++) { vlc_index = i; @@ -376,8 +379,8 @@ static int decode_envelope(COOKContext *q, COOKSubpacket *p, if (vlc_index > 13) vlc_index = 13; // the VLC tables >13 are identical to No. 13 - j = bitstream_read_vlc(&q->bc, q->envelope_quant_index[vlc_index - 1].table, - q->envelope_quant_index[vlc_index - 1].bits, 2); + j = get_vlc2(&q->gb, q->envelope_quant_index[vlc_index - 1].table, + q->envelope_quant_index[vlc_index - 1].bits, 2); quant_index_table[i] = quant_index_table[i - 1] + j - 12; // differential encoding if (quant_index_table[i] > 63 || quant_index_table[i] < -63) { av_log(q->avctx, AV_LOG_ERROR, @@ -398,7 +401,7 @@ static int decode_envelope(COOKContext *q, COOKSubpacket *p, * @param category pointer to the category array * @param category_index pointer to the category_index array */ -static void categorize(COOKContext *q, COOKSubpacket *p, int *quant_index_table, +static void categorize(COOKContext *q, COOKSubpacket *p, const int *quant_index_table, int *category, int *category_index) { int exp_idx, bias, tmpbias1, tmpbias2, bits_left, num_bits, index, v, i, j; @@ -409,7 +412,7 @@ static void categorize(COOKContext *q, COOKSubpacket *p, int *quant_index_table, int tmp_categorize_array1_idx = p->numvector_size; int tmp_categorize_array2_idx = p->numvector_size; - bits_left = p->bits_per_subpacket - bitstream_tell(&q->bc); + bits_left = p->bits_per_subpacket - get_bits_count(&q->gb); if (bits_left > q->samples_per_channel) bits_left = q->samples_per_channel + @@ -422,7 +425,7 @@ static void categorize(COOKContext *q, COOKSubpacket *p, int *quant_index_table, num_bits = 0; index = 0; for (j = p->total_subbands; j > 0; j--) { - exp_idx = av_clip((i - quant_index_table[index] + bias) / 2, 0, 7); + exp_idx = av_clip_uintp2((i - quant_index_table[index] + bias) / 2, 3); index++; num_bits += expbits_tab[exp_idx]; } @@ -433,7 +436,7 @@ static void categorize(COOKContext *q, COOKSubpacket *p, int *quant_index_table, /* Calculate total number of bits. */ num_bits = 0; for (i = 0; i < p->total_subbands; i++) { - exp_idx = av_clip((bias - quant_index_table[i]) / 2, 0, 7); + exp_idx = av_clip_uintp2((bias - quant_index_table[i]) / 2, 3); num_bits += expbits_tab[exp_idx]; exp_index1[i] = exp_idx; exp_index2[i] = exp_idx; @@ -555,8 +558,8 @@ static int unpack_SQVH(COOKContext *q, COOKSubpacket *p, int category, vd = vd_tab[category]; result = 0; for (i = 0; i < vpr_tab[category]; i++) { - vlc = bitstream_read_vlc(&q->bc, q->sqvh[category].table, q->sqvh[category].bits, 3); - if (p->bits_per_subpacket < bitstream_tell(&q->bc)) { + vlc = get_vlc2(&q->gb, q->sqvh[category].table, q->sqvh[category].bits, 3); + if (p->bits_per_subpacket < get_bits_count(&q->gb)) { vlc = 0; result = 1; } @@ -567,8 +570,8 @@ static int unpack_SQVH(COOKContext *q, COOKSubpacket *p, int category, } for (j = 0; j < vd; j++) { if (subband_coef_index[i * vd + j]) { - if (bitstream_tell(&q->bc) < p->bits_per_subpacket) { - subband_coef_sign[i * vd + j] = bitstream_read_bit(&q->bc); + if (get_bits_count(&q->gb) < p->bits_per_subpacket) { + subband_coef_sign[i * vd + j] = get_bits1(&q->gb); } else { result = 1; subband_coef_sign[i * vd + j] = 0; @@ -631,13 +634,17 @@ static int mono_decode(COOKContext *q, COOKSubpacket *p, float *mlt_buffer) int category_index[128] = { 0 }; int category[128] = { 0 }; int quant_index_table[102]; - int res; + int res, i; if ((res = decode_envelope(q, p, quant_index_table)) < 0) return res; - q->num_vectors = bitstream_read(&q->bc, p->log2_numvector_size); + q->num_vectors = get_bits(&q->gb, p->log2_numvector_size); categorize(q, p, quant_index_table, category, category_index); expand_category(q, category, category_index); + for (i=0; i<p->total_subbands; i++) { + if (category[i] > 7) + return AVERROR_INVALIDDATA; + } decode_vectors(q, p, category, quant_index_table, mlt_buffer); return 0; @@ -737,29 +744,35 @@ static void imlt_gain(COOKContext *q, float *inbuffer, * @param q pointer to the COOKContext * @param decouple_tab decoupling array */ -static void decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab) +static int decouple_info(COOKContext *q, COOKSubpacket *p, int *decouple_tab) { int i; - int vlc = bitstream_read_bit(&q->bc); + int vlc = get_bits1(&q->gb); int start = cplband[p->js_subband_start]; int end = cplband[p->subbands - 1]; int length = end - start + 1; if (start > end) - return; + return 0; if (vlc) for (i = 0; i < length; i++) - decouple_tab[start + i] = - bitstream_read_vlc(&q->bc, - p->channel_coupling.table, - p->channel_coupling.bits, 2); + decouple_tab[start + i] = get_vlc2(&q->gb, + p->channel_coupling.table, + p->channel_coupling.bits, 2); else - for (i = 0; i < length; i++) - decouple_tab[start + i] = bitstream_read(&q->bc, p->js_vlc_bits); + for (i = 0; i < length; i++) { + int v = get_bits(&q->gb, p->js_vlc_bits); + if (v == (1<<p->js_vlc_bits)-1) { + av_log(q->avctx, AV_LOG_ERROR, "decouple value too large\n"); + return AVERROR_INVALIDDATA; + } + decouple_tab[start + i] = v; + } + return 0; } -/* +/** * function decouples a pair of signals from a single signal via multiplication. * * @param q pointer to the COOKContext @@ -807,10 +820,10 @@ static int joint_decode(COOKContext *q, COOKSubpacket *p, /* Make sure the buffers are zeroed out. */ memset(mlt_buffer_left, 0, 1024 * sizeof(*mlt_buffer_left)); memset(mlt_buffer_right, 0, 1024 * sizeof(*mlt_buffer_right)); - decouple_info(q, p, decouple_tab); + if ((res = decouple_info(q, p, decouple_tab)) < 0) + return res; if ((res = mono_decode(q, p, decode_buffer)) < 0) return res; - /* The two channels are stored interleaved in decode_buffer. */ for (i = 0; i < p->js_subband_start; i++) { for (j = 0; j < SUBBAND_SIZE; j++) { @@ -852,9 +865,9 @@ static inline void decode_bytes_and_gain(COOKContext *q, COOKSubpacket *p, offset = decode_bytes(inbuffer, q->decoded_bytes_buffer, p->bits_per_subpacket / 8); - bitstream_init(&q->bc, q->decoded_bytes_buffer + offset, - p->bits_per_subpacket); - decode_gain_info(&q->bc, gains_ptr->now); + init_get_bits(&q->gb, q->decoded_bytes_buffer + offset, + p->bits_per_subpacket); + decode_gain_info(&q->gb, gains_ptr->now); /* Swap current and previous gains */ FFSWAP(int *, gains_ptr->now, gains_ptr->previous); @@ -929,7 +942,7 @@ static int decode_subpacket(COOKContext *q, COOKSubpacket *p, p->mono_previous_buffer1, outbuffer ? outbuffer[p->ch_idx] : NULL); - if (p->num_channels == 2) + if (p->num_channels == 2) { if (p->joint_stereo) mlt_compensate_output(q, q->decode_buffer_2, &p->gains1, p->mono_previous_buffer2, @@ -938,6 +951,7 @@ static int decode_subpacket(COOKContext *q, COOKSubpacket *p, mlt_compensate_output(q, q->decode_buffer_2, &p->gains2, p->mono_previous_buffer2, outbuffer ? outbuffer[p->ch_idx + 1] : NULL); + } return 0; } @@ -961,10 +975,8 @@ static int cook_decode_frame(AVCodecContext *avctx, void *data, /* get output buffer */ if (q->discarded_packets >= 2) { frame->nb_samples = q->samples_per_channel; - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) { - av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) return ret; - } samples = (float **)frame->extended_data; } @@ -996,7 +1008,7 @@ static int cook_decode_frame(AVCodecContext *avctx, void *data, offset += q->subpacket[i].size; chidx += q->subpacket[i].num_channels; av_log(avctx, AV_LOG_DEBUG, "subpacket[%i] %i %i\n", - i, q->subpacket[i].size * 8, bitstream_tell(&q->bc)); + i, q->subpacket[i].size * 8, get_bits_count(&q->gb)); } /* Discard the first two frames: no valid audio. */ @@ -1011,7 +1023,6 @@ static int cook_decode_frame(AVCodecContext *avctx, void *data, return avctx->block_align; } -#ifdef DEBUG static void dump_cook_context(COOKContext *q) { //int i=0; @@ -1024,7 +1035,7 @@ static void dump_cook_context(COOKContext *q) } ff_dlog(q->avctx, "COOKContext\n"); PRINT("nb_channels", q->avctx->channels); - PRINT("bit_rate", q->avctx->bit_rate); + PRINT("bit_rate", (int)q->avctx->bit_rate); PRINT("sample_rate", q->avctx->sample_rate); PRINT("samples_per_channel", q->subpacket[0].samples_per_channel); PRINT("subbands", q->subpacket[0].subbands); @@ -1033,7 +1044,6 @@ static void dump_cook_context(COOKContext *q) PRINT("numvector_size", q->subpacket[0].numvector_size); PRINT("total_subbands", q->subpacket[0].total_subbands); } -#endif /** * Cook initialization @@ -1046,7 +1056,7 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) GetByteContext gb; int s = 0; unsigned int channel_mask = 0; - int samples_per_frame; + int samples_per_frame = 0; int ret; q->avctx = avctx; @@ -1078,6 +1088,10 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) q->subpacket[s].subbands = bytestream2_get_be16(&gb); bytestream2_get_be32(&gb); // Unknown unused q->subpacket[s].js_subband_start = bytestream2_get_be16(&gb); + if (q->subpacket[s].js_subband_start >= 51) { + av_log(avctx, AV_LOG_ERROR, "js_subband_start %d is too large\n", q->subpacket[s].js_subband_start); + return AVERROR_INVALIDDATA; + } q->subpacket[s].js_vlc_bits = bytestream2_get_be16(&gb); /* Initialize extradata related variables. */ @@ -1182,15 +1196,24 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) avpriv_request_sample(avctx, "subbands > 50"); return AVERROR_PATCHWELCOME; } + if (q->subpacket[s].subbands == 0) { + avpriv_request_sample(avctx, "subbands = 0"); + return AVERROR_PATCHWELCOME; + } q->subpacket[s].gains1.now = q->subpacket[s].gain_1; q->subpacket[s].gains1.previous = q->subpacket[s].gain_2; q->subpacket[s].gains2.now = q->subpacket[s].gain_3; q->subpacket[s].gains2.previous = q->subpacket[s].gain_4; + if (q->num_subpackets + q->subpacket[s].num_channels > q->avctx->channels) { + av_log(avctx, AV_LOG_ERROR, "Too many subpackets %d for channels %d\n", q->num_subpackets, q->avctx->channels); + return AVERROR_INVALIDDATA; + } + q->num_subpackets++; s++; - if (s > MAX_SUBPACKETS) { - avpriv_request_sample(avctx, "subpackets > %d", MAX_SUBPACKETS); + if (s > FFMIN(MAX_SUBPACKETS, avctx->block_align)) { + avpriv_request_sample(avctx, "subpackets > %d", FFMIN(MAX_SUBPACKETS, avctx->block_align)); return AVERROR_PATCHWELCOME; } } @@ -1243,9 +1266,9 @@ static av_cold int cook_decode_init(AVCodecContext *avctx) else avctx->channel_layout = (avctx->channels == 2) ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; -#ifdef DEBUG + dump_cook_context(q); -#endif + return 0; } @@ -1259,6 +1282,7 @@ AVCodec ff_cook_decoder = { .close = cook_decode_close, .decode = cook_decode_frame, .capabilities = AV_CODEC_CAP_DR1, + .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_NONE }, }; |