X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fac3dec.c;h=ea7e052f8b538d27e79f7746dbe7f8b5109de733;hb=4a657acaefd599f3971e88419516a7f4ece00e53;hp=ac5c6d636a855a0905a566ad01c7488350ce8985;hpb=20608261f7818fc034f96034a089e755f095716e;p=ffmpeg diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c index ac5c6d636a8..ea7e052f8b5 100644 --- a/libavcodec/ac3dec.c +++ b/libavcodec/ac3dec.c @@ -1488,7 +1488,7 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int blk, ch, err, offset, ret; int got_independent_frame = 0; const uint8_t *channel_map; - uint8_t extended_channel_map[AC3_MAX_CHANNELS * 2]; + uint8_t extended_channel_map[EAC3_MAX_CHANNELS]; const SHORTFLOAT *output[AC3_MAX_CHANNELS]; enum AVMatrixEncoding matrix_encoding; AVDownmixInfo *downmix_info; @@ -1685,11 +1685,12 @@ dependent_frame: avctx->bit_rate = s->bit_rate + s->prev_bit_rate; } - for (ch = 0; ch < 16; ch++) + for (ch = 0; ch < EAC3_MAX_CHANNELS; ch++) extended_channel_map[ch] = ch; if (s->frame_type == EAC3_FRAME_TYPE_DEPENDENT) { uint64_t ich_layout = avpriv_ac3_channel_layout_tab[s->prev_output_mode & ~AC3_OUTPUT_LFEON]; + int channel_map_size = ff_ac3_channels_tab[s->output_mode & ~AC3_OUTPUT_LFEON] + s->lfe_on; uint64_t channel_layout; int extend = 0; @@ -1698,21 +1699,29 @@ dependent_frame: channel_layout = ich_layout; for (ch = 0; ch < 16; ch++) { - if (s->channel_map & (1 << (15 - ch))) { + if (s->channel_map & (1 << (EAC3_MAX_CHANNELS - ch - 1))) { channel_layout |= custom_channel_map_locations[ch][1]; } } + if (av_get_channel_layout_nb_channels(channel_layout) > EAC3_MAX_CHANNELS) { + av_log(avctx, AV_LOG_ERROR, "Too many channels (%d) coded\n", + av_get_channel_layout_nb_channels(channel_layout)); + return AVERROR_INVALIDDATA; + } avctx->channel_layout = channel_layout; avctx->channels = av_get_channel_layout_nb_channels(channel_layout); - for (ch = 0; ch < 16; ch++) { - if (s->channel_map & (1 << (15 - ch))) { + for (ch = 0; ch < EAC3_MAX_CHANNELS; ch++) { + if (s->channel_map & (1 << (EAC3_MAX_CHANNELS - ch - 1))) { if (custom_channel_map_locations[ch][0]) { int index = av_get_channel_layout_channel_index(channel_layout, custom_channel_map_locations[ch][1]); if (index < 0) return AVERROR_INVALIDDATA; + if (extend >= channel_map_size) + return AVERROR_INVALIDDATA; + extended_channel_map[index] = offset + channel_map[extend++]; } else { int i; @@ -1723,6 +1732,9 @@ dependent_frame: 1LL << i); if (index < 0) return AVERROR_INVALIDDATA; + if (extend >= channel_map_size) + return AVERROR_INVALIDDATA; + extended_channel_map[index] = offset + channel_map[extend++]; } } @@ -1738,7 +1750,9 @@ dependent_frame: for (ch = 0; ch < avctx->channels; ch++) { int map = extended_channel_map[ch]; - memcpy((SHORTFLOAT *)frame->data[ch], s->output_buffer[map], + av_assert0(ch>=AV_NUM_DATA_POINTERS || frame->extended_data[ch] == frame->data[ch]); + memcpy((SHORTFLOAT *)frame->extended_data[ch], + s->output_buffer[map], s->num_blocks * AC3_BLOCK_SIZE * sizeof(SHORTFLOAT)); } @@ -1800,6 +1814,9 @@ dependent_frame: *got_frame_ptr = 1; + if (!s->superframe_size) + return FFMIN(full_buf_size, s->frame_size); + return FFMIN(full_buf_size, s->superframe_size); }