diff options
Diffstat (limited to 'libavcodec/aacdec.c')
-rw-r--r-- | libavcodec/aacdec.c | 67 |
1 files changed, 49 insertions, 18 deletions
diff --git a/libavcodec/aacdec.c b/libavcodec/aacdec.c index 3038e9a..7c3d43a 100644 --- a/libavcodec/aacdec.c +++ b/libavcodec/aacdec.c @@ -7,20 +7,20 @@ * Copyright (c) 2008-2010 Paul Kendall <paul@kcbbs.gen.nz> * Copyright (c) 2010 Janne Grunau <janne-libav@jannau.net> * - * 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 */ @@ -129,7 +129,7 @@ static int count_channels(uint8_t (*layout)[3], int tags) /** * Check for the channel element in the current channel position configuration. * If it exists, make sure the appropriate element is allocated and map the - * channel order to match the internal Libav channel layout. + * channel order to match the internal FFmpeg channel layout. * * @param che_pos current channel position configuration * @param type channel element type @@ -149,6 +149,10 @@ static av_cold int che_configure(AACContext *ac, ff_aac_sbr_ctx_init(ac, &ac->che[type][id]->sbr); } if (type != TYPE_CCE) { + if (*channels >= MAX_CHANNELS - (type == TYPE_CPE || (type == TYPE_SCE && ac->m4ac.ps == 1))) { + av_log(ac->avctx, AV_LOG_ERROR, "Too many channels\n"); + return AVERROR_INVALIDDATA; + } ac->output_data[(*channels)++] = ac->che[type][id]->ch[0].ret; if (type == TYPE_CPE || (type == TYPE_SCE && ac->m4ac.ps == 1)) { @@ -384,13 +388,30 @@ static av_cold int output_configure(AACContext *ac, } memcpy(ac->tag_che_map, ac->che, 4 * MAX_ELEM_ID * sizeof(ac->che[0][0])); - avctx->channel_layout = layout; + if (layout) avctx->channel_layout = layout; avctx->channels = channels; ac->output_configured = oc_type; return 0; } +static void flush(AVCodecContext *avctx) +{ + AACContext *ac= avctx->priv_data; + int type, i, j; + + for (type = 3; type >= 0; type--) { + for (i = 0; i < MAX_ELEM_ID; i++) { + ChannelElement *che = ac->che[type][i]; + if (che) { + for (j = 0; j <= 1; j++) { + memset(che->ch[j].saved, 0, sizeof(che->ch[j].saved)); + } + } + } + } +} + /** * Set up channel positions based on a default channel configuration * as specified in table 1.17. @@ -541,6 +562,10 @@ static int decode_pce(AVCodecContext *avctx, MPEG4AudioConfig *m4ac, if (get_bits1(gb)) skip_bits(gb, 3); // mixdown_coeff_index and pseudo_surround + if (get_bits_left(gb) < 4 * (num_front + num_side + num_back + num_lfe + num_assoc_data + num_cc)) { + av_log(avctx, AV_LOG_ERROR, overread_err); + return -1; + } decode_channel_map(layout_map , AAC_CHANNEL_FRONT, gb, num_front); tags = num_front; decode_channel_map(layout_map + tags, AAC_CHANNEL_SIDE, gb, num_side); @@ -940,11 +965,11 @@ static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics, if (ics->predictor_present) { if (ac->m4ac.object_type == AOT_AAC_MAIN) { if (decode_prediction(ac, ics, gb)) { - return AVERROR_INVALIDDATA; + goto fail; } } else if (ac->m4ac.object_type == AOT_AAC_LC) { av_log(ac->avctx, AV_LOG_ERROR, "Prediction is not allowed in AAC-LC.\n"); - return AVERROR_INVALIDDATA; + goto fail; } else { if ((ics->ltp.present = get_bits(gb, 1))) decode_ltp(ac, &ics->ltp, gb, ics->max_sfb); @@ -956,10 +981,13 @@ static int decode_ics_info(AACContext *ac, IndividualChannelStream *ics, av_log(ac->avctx, AV_LOG_ERROR, "Number of scalefactor bands in group (%d) exceeds limit (%d).\n", ics->max_sfb, ics->num_swb); - return AVERROR_INVALIDDATA; + goto fail; } return 0; +fail: + ics->max_sfb = 0; + return AVERROR_INVALIDDATA; } /** @@ -2295,13 +2323,14 @@ static int parse_adts_frame_header(AACContext *ac, GetBitContext *gb) } if (!ac->avctx->sample_rate) ac->avctx->sample_rate = hdr_info.sample_rate; - if (hdr_info.num_aac_frames == 1) { - if (!hdr_info.crc_absent) - skip_bits(gb, 16); - } else { + if (!ac->warned_num_aac_frames && hdr_info.num_aac_frames != 1) { + // This is 2 for "VLB " audio in NSV files. + // See samples/nsv/vlb_audio. av_log_missing_feature(ac->avctx, "More than one AAC RDB per ADTS frame is", 0); - return -1; + ac->warned_num_aac_frames = 1; } + if (!hdr_info.crc_absent) + skip_bits(gb, 16); } return size; } @@ -2374,10 +2403,11 @@ static int aac_decode_frame_int(AVCodecContext *avctx, void *data, break; } if (ac->output_configured > OC_TRIAL_PCE) - av_log(avctx, AV_LOG_ERROR, - "Not evaluating a further program_config_element as this construct is dubious at best.\n"); - else - err = output_configure(ac, layout_map, tags, 0, OC_TRIAL_PCE); + av_log(avctx, AV_LOG_INFO, + "Evaluating a further program_config_element.\n"); + err = output_configure(ac, layout_map, tags, 0, OC_TRIAL_PCE); + if (!err) + ac->m4ac.chan_config = 0; break; } @@ -2807,4 +2837,5 @@ AVCodec ff_aac_latm_decoder = { }, .capabilities = CODEC_CAP_CHANNEL_CONF | CODEC_CAP_DR1, .channel_layouts = aac_channel_layout, + .flush = flush, }; |