diff options
Diffstat (limited to 'libavcodec/alsdec.c')
-rw-r--r-- | libavcodec/alsdec.c | 98 |
1 files changed, 59 insertions, 39 deletions
diff --git a/libavcodec/alsdec.c b/libavcodec/alsdec.c index d4f103b..7b99d86 100644 --- a/libavcodec/alsdec.c +++ b/libavcodec/alsdec.c @@ -1,28 +1,28 @@ /* * MPEG-4 ALS decoder - * Copyright (c) 2009 Thilo Borgmann <thilo.borgmann _at_ googlemail.com> + * Copyright (c) 2009 Thilo Borgmann <thilo.borgmann _at_ mail.de> * - * 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 */ /** * @file * MPEG-4 ALS decoder - * @author Thilo Borgmann <thilo.borgmann _at_ googlemail.com> + * @author Thilo Borgmann <thilo.borgmann _at_ mail.de> */ #include "avcodec.h" @@ -197,6 +197,7 @@ typedef struct { unsigned int cur_frame_length; ///< length of the current frame to decode unsigned int frame_id; ///< the frame ID / number of the current frame unsigned int js_switch; ///< if true, joint-stereo decoding is enforced + unsigned int cs_switch; ///< if true, channel rearrangement is done unsigned int num_blocks; ///< number of blocks used in the current frame unsigned int s_max; ///< maximum Rice parameter allowed in entropy coding uint8_t *bgmc_lut; ///< pointer at lookup tables used for BGMC @@ -283,8 +284,10 @@ static av_cold int read_specific_config(ALSDecContext *ctx) ALSSpecificConfig *sconf = &ctx->sconf; AVCodecContext *avctx = ctx->avctx; uint32_t als_id, header_size, trailer_size; + int ret; - init_get_bits(&gb, avctx->extradata, avctx->extradata_size * 8); + if ((ret = init_get_bits8(&gb, avctx->extradata, avctx->extradata_size)) < 0) + return ret; config_offset = avpriv_mpeg4audio_get_config(&m4ac, avctx->extradata, avctx->extradata_size * 8, 1); @@ -303,7 +306,7 @@ static av_cold int read_specific_config(ALSDecContext *ctx) skip_bits_long(&gb, 32); // sample rate already known sconf->samples = get_bits_long(&gb, 32); avctx->channels = m4ac.channels; - skip_bits(&gb, 16); // number of channels already knwon + skip_bits(&gb, 16); // number of channels already known skip_bits(&gb, 3); // skip file_type sconf->resolution = get_bits(&gb, 3); sconf->floating = get_bits1(&gb); @@ -350,13 +353,21 @@ static av_cold int read_specific_config(ALSDecContext *ctx) if (!(sconf->chan_pos = av_malloc(avctx->channels * sizeof(*sconf->chan_pos)))) return AVERROR(ENOMEM); - for (i = 0; i < avctx->channels; i++) - sconf->chan_pos[i] = get_bits(&gb, chan_pos_bits); + ctx->cs_switch = 1; + + for (i = 0; i < avctx->channels; i++) { + int idx; + + idx = get_bits(&gb, chan_pos_bits); + if (idx >= avctx->channels) { + av_log(avctx, AV_LOG_WARNING, "Invalid channel reordering.\n"); + ctx->cs_switch = 0; + break; + } + sconf->chan_pos[idx] = i; + } align_get_bits(&gb); - // TODO: use this to actually do channel sorting - } else { - sconf->chan_sort = 0; } @@ -390,7 +401,7 @@ static av_cold int read_specific_config(ALSDecContext *ctx) if (get_bits_left(&gb) < 32) return AVERROR_INVALIDDATA; - if (avctx->err_recognition & AV_EF_CRCCHECK) { + if (avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_CAREFUL)) { ctx->crc_table = av_crc_get_table(AV_CRC_32_IEEE_LE); ctx->crc = 0xFFFFFFFF; ctx->crc_org = ~get_bits_long(&gb, 32); @@ -426,7 +437,6 @@ static int check_specific_config(ALSDecContext *ctx) MISSING_ERR(sconf->floating, "Floating point decoding", AVERROR_PATCHWELCOME); MISSING_ERR(sconf->rlslms, "Adaptive RLS-LMS prediction", AVERROR_PATCHWELCOME); - MISSING_ERR(sconf->chan_sort, "Channel sorting", 0); return error; } @@ -549,12 +559,15 @@ static void get_block_sizes(ALSDecContext *ctx, unsigned int *div_blocks, /** Read the block data for a constant block */ -static void read_const_block_data(ALSDecContext *ctx, ALSBlockData *bd) +static int read_const_block_data(ALSDecContext *ctx, ALSBlockData *bd) { ALSSpecificConfig *sconf = &ctx->sconf; AVCodecContext *avctx = ctx->avctx; GetBitContext *gb = &ctx->gb; + if (bd->block_length <= 0) + return AVERROR_INVALIDDATA; + *bd->raw_samples = 0; *bd->const_block = get_bits1(gb); // 1 = constant value, 0 = zero block (silence) bd->js_blocks = get_bits1(gb); @@ -569,6 +582,8 @@ static void read_const_block_data(ALSDecContext *ctx, ALSBlockData *bd) // ensure constant block decoding by reusing this field *bd->const_block = 1; + + return 0; } @@ -667,7 +682,7 @@ static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd) *bd->opt_order = get_bits(gb, opt_order_length); if (*bd->opt_order > sconf->max_order) { *bd->opt_order = sconf->max_order; - av_log(avctx, AV_LOG_ERROR, "Predictor order too large!\n"); + av_log(avctx, AV_LOG_ERROR, "Predictor order too large.\n"); return AVERROR_INVALIDDATA; } } else { @@ -703,7 +718,7 @@ static int read_var_block_data(ALSDecContext *ctx, ALSBlockData *bd) int offset = parcor_rice_table[sconf->coef_table][k][0]; quant_cof[k] = decode_rice(gb, rice_param) + offset; if (quant_cof[k] < -64 || quant_cof[k] > 63) { - av_log(avctx, AV_LOG_ERROR, "quant_cof %d is out of range\n", quant_cof[k]); + av_log(avctx, AV_LOG_ERROR, "quant_cof %d is out of range.\n", quant_cof[k]); return AVERROR_INVALIDDATA; } } @@ -960,7 +975,7 @@ static int decode_var_block_data(ALSDecContext *ctx, ALSBlockData *bd) */ static int read_block(ALSDecContext *ctx, ALSBlockData *bd) { - int ret = 0; + int ret; GetBitContext *gb = &ctx->gb; *bd->shift_lsbs = 0; @@ -968,7 +983,7 @@ static int read_block(ALSDecContext *ctx, ALSBlockData *bd) if (get_bits1(gb)) { ret = read_var_block_data(ctx, bd); } else { - read_const_block_data(ctx, bd); + ret = read_const_block_data(ctx, bd); } return ret; @@ -1022,8 +1037,8 @@ static void zero_remaining(unsigned int b, unsigned int b_max, { unsigned int count = 0; - for (; b < b_max; b++) - count += div_blocks[b]; + while (b < b_max) + count += div_blocks[b++]; if (count) memset(buf, 0, sizeof(*buf) * count); @@ -1128,7 +1143,7 @@ static int decode_blocks(ALSDecContext *ctx, unsigned int ra_frame, // reconstruct joint-stereo blocks if (bd[0].js_blocks) { if (bd[1].js_blocks) - av_log(ctx->avctx, AV_LOG_WARNING, "Invalid channel pair!\n"); + av_log(ctx->avctx, AV_LOG_WARNING, "Invalid channel pair.\n"); for (s = 0; s < div_blocks[b]; s++) bd[0].raw_samples[s] = bd[1].raw_samples[s] - bd[0].raw_samples[s]; @@ -1176,7 +1191,7 @@ static int read_channel_data(ALSDecContext *ctx, ALSChannelData *cd, int c) current->master_channel = get_bits_long(gb, av_ceil_log2(channels)); if (current->master_channel >= channels) { - av_log(ctx->avctx, AV_LOG_ERROR, "Invalid master channel!\n"); + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid master channel.\n"); return AVERROR_INVALIDDATA; } @@ -1201,7 +1216,7 @@ static int read_channel_data(ALSDecContext *ctx, ALSChannelData *cd, int c) } if (entries == channels) { - av_log(ctx->avctx, AV_LOG_ERROR, "Damaged channel data!\n"); + av_log(ctx->avctx, AV_LOG_ERROR, "Damaged channel data.\n"); return AVERROR_INVALIDDATA; } @@ -1233,7 +1248,7 @@ static int revert_channel_correlation(ALSDecContext *ctx, ALSBlockData *bd, } if (dep == channels) { - av_log(ctx->avctx, AV_LOG_WARNING, "Invalid channel correlation!\n"); + av_log(ctx->avctx, AV_LOG_WARNING, "Invalid channel correlation.\n"); return AVERROR_INVALIDDATA; } @@ -1363,7 +1378,7 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) for (c = 0; c < avctx->channels; c++) if (ctx->chan_data[c] < ctx->chan_data_buffer) { - av_log(ctx->avctx, AV_LOG_ERROR, "Invalid channel data!\n"); + av_log(ctx->avctx, AV_LOG_ERROR, "Invalid channel data.\n"); return AVERROR_INVALIDDATA; } @@ -1413,6 +1428,7 @@ static int read_frame_data(ALSDecContext *ctx, unsigned int ra_frame) bd.lpc_cof = ctx->lpc_cof[c]; bd.quant_cof = ctx->quant_cof[c]; bd.raw_samples = ctx->raw_samples[c] + offset; + if ((ret = decode_block(ctx, &bd)) < 0) return ret; } @@ -1472,19 +1488,23 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, /* get output buffer */ frame->nb_samples = ctx->cur_frame_length; - 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; - } // transform decoded frame into output format - #define INTERLEAVE_OUTPUT(bps) \ - { \ - int##bps##_t *dest = (int##bps##_t*)frame->data[0]; \ - shift = bps - ctx->avctx->bits_per_raw_sample; \ - for (sample = 0; sample < ctx->cur_frame_length; sample++) \ - for (c = 0; c < avctx->channels; c++) \ - *dest++ = ctx->raw_samples[c][sample] << shift; \ + #define INTERLEAVE_OUTPUT(bps) \ + { \ + int##bps##_t *dest = (int##bps##_t*)frame->data[0]; \ + shift = bps - ctx->avctx->bits_per_raw_sample; \ + if (!ctx->cs_switch) { \ + for (sample = 0; sample < ctx->cur_frame_length; sample++) \ + for (c = 0; c < avctx->channels; c++) \ + *dest++ = ctx->raw_samples[c][sample] << shift; \ + } else { \ + for (sample = 0; sample < ctx->cur_frame_length; sample++) \ + for (c = 0; c < avctx->channels; c++) \ + *dest++ = ctx->raw_samples[sconf->chan_pos[c]][sample] << shift; \ + } \ } if (ctx->avctx->bits_per_raw_sample <= 16) { @@ -1494,7 +1514,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame_ptr, } // update CRC - if (sconf->crc_enabled && (avctx->err_recognition & AV_EF_CRCCHECK)) { + if (sconf->crc_enabled && (avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_CAREFUL))) { int swap = HAVE_BIGENDIAN != sconf->msb_first; if (ctx->avctx->bits_per_raw_sample == 24) { @@ -1732,7 +1752,7 @@ static av_cold int decode_init(AVCodecContext *avctx) // allocate crc buffer if (HAVE_BIGENDIAN != sconf->msb_first && sconf->crc_enabled && - (avctx->err_recognition & AV_EF_CRCCHECK)) { + (avctx->err_recognition & (AV_EF_CRCCHECK|AV_EF_CAREFUL))) { ctx->crc_buffer = av_malloc(sizeof(*ctx->crc_buffer) * ctx->cur_frame_length * avctx->channels * |