summaryrefslogtreecommitdiffstats
path: root/libavcodec/cook.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/cook.c')
-rw-r--r--libavcodec/cook.c149
1 files changed, 86 insertions, 63 deletions
diff --git a/libavcodec/cook.c b/libavcodec/cook.c
index bd8ad1d..53cb8385 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;
}
OpenPOWER on IntegriCloud