diff options
Diffstat (limited to 'libavcodec/mlpdec.c')
-rw-r--r-- | libavcodec/mlpdec.c | 84 |
1 files changed, 70 insertions, 14 deletions
diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index afd8f887ec..423872cede 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -2,20 +2,20 @@ * MLP decoder * Copyright (c) 2007-2008 Ian Caulfield * - * 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 */ @@ -128,6 +128,9 @@ typedef struct MLPDecodeContext { /// Index of the last substream to decode - further substreams are skipped. uint8_t max_decoded_substream; + /// Stream needs channel reordering to comply with FFmpeg's channel order + uint8_t needs_reordering; + /// number of PCM samples contained in each frame int access_unit_size; /// next power of two above the number of samples in each frame @@ -324,6 +327,26 @@ static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) for (substr = 0; substr < MAX_SUBSTREAMS; substr++) m->substream[substr].restart_seen = 0; + if (mh.stream_type == 0xbb) { + /* MLP stream */ + m->avctx->channel_layout = ff_mlp_layout[mh.channels_mlp]; + } else { /* mh.stream_type == 0xba */ + /* TrueHD stream */ + if (mh.channels_thd_stream2) { + m->avctx->channel_layout = ff_truehd_layout(mh.channels_thd_stream2); + } else { + m->avctx->channel_layout = ff_truehd_layout(mh.channels_thd_stream1); + } + if (m->avctx->channels && + !m->avctx->request_channels && !m->avctx->request_channel_layout && + av_get_channel_layout_nb_channels(m->avctx->channel_layout) != m->avctx->channels) { + m->avctx->channel_layout = 0; + av_log_ask_for_sample(m->avctx, "Unknown channel layout."); + } + } + + m->needs_reordering = mh.channels_mlp >= 18 && mh.channels_mlp <= 20; + return 0; } @@ -343,6 +366,7 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, const int max_matrix_channel = m->avctx->codec_id == AV_CODEC_ID_MLP ? MAX_MATRIX_CHANNEL_MLP : MAX_MATRIX_CHANNEL_TRUEHD; + int max_channel, min_channel, matrix_channel; sync_word = get_bits(gbp, 13); @@ -361,18 +385,18 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, skip_bits(gbp, 16); /* Output timestamp */ - s->min_channel = get_bits(gbp, 4); - s->max_channel = get_bits(gbp, 4); - s->max_matrix_channel = get_bits(gbp, 4); + min_channel = get_bits(gbp, 4); + max_channel = get_bits(gbp, 4); + matrix_channel = get_bits(gbp, 4); - if (s->max_matrix_channel > max_matrix_channel) { + if (matrix_channel > max_matrix_channel) { av_log(m->avctx, AV_LOG_ERROR, "Max matrix channel cannot be greater than %d.\n", max_matrix_channel); return AVERROR_INVALIDDATA; } - if (s->max_channel != s->max_matrix_channel) { + if (max_channel != matrix_channel) { av_log(m->avctx, AV_LOG_ERROR, "Max channel must be equal max matrix channel.\n"); return AVERROR_INVALIDDATA; @@ -380,19 +404,23 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, /* This should happen for TrueHD streams with >6 channels and MLP's noise * type. It is not yet known if this is allowed. */ - if (s->max_channel > MAX_MATRIX_CHANNEL_MLP && !s->noise_type) { + if (max_channel > MAX_MATRIX_CHANNEL_MLP && !s->noise_type) { av_log_ask_for_sample(m->avctx, "Number of channels %d is larger than the maximum supported " - "by the decoder.\n", s->max_channel + 2); + "by the decoder.\n", max_channel + 2); return AVERROR_PATCHWELCOME; } - if (s->min_channel > s->max_channel) { + if (min_channel > max_channel) { av_log(m->avctx, AV_LOG_ERROR, "Substream min channel cannot be greater than max channel.\n"); return AVERROR_INVALIDDATA; } + s->min_channel = min_channel; + s->max_channel = max_channel; + s->max_matrix_channel = matrix_channel; + if (m->avctx->request_channels > 0 && s->max_channel + 1 >= m->avctx->request_channels && substr < m->max_decoded_substream) { @@ -434,6 +462,33 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, s->ch_assign[ch_assign] = ch; } + if (m->avctx->codec_id == AV_CODEC_ID_MLP && m->needs_reordering) { + if (m->avctx->channel_layout == (AV_CH_LAYOUT_QUAD|AV_CH_LOW_FREQUENCY) || + m->avctx->channel_layout == AV_CH_LAYOUT_5POINT0_BACK) { + int i = s->ch_assign[4]; + s->ch_assign[4] = s->ch_assign[3]; + s->ch_assign[3] = s->ch_assign[2]; + s->ch_assign[2] = i; + } else if (m->avctx->channel_layout == AV_CH_LAYOUT_5POINT1_BACK) { + FFSWAP(int, s->ch_assign[2], s->ch_assign[4]); + FFSWAP(int, s->ch_assign[3], s->ch_assign[5]); + } + } + if (m->avctx->codec_id == AV_CODEC_ID_TRUEHD && + (m->avctx->channel_layout == AV_CH_LAYOUT_7POINT1 || + m->avctx->channel_layout == AV_CH_LAYOUT_7POINT1_WIDE)) { + FFSWAP(int, s->ch_assign[4], s->ch_assign[6]); + FFSWAP(int, s->ch_assign[5], s->ch_assign[7]); + } else if (m->avctx->codec_id == AV_CODEC_ID_TRUEHD && + (m->avctx->channel_layout == AV_CH_LAYOUT_6POINT1 || + m->avctx->channel_layout == (AV_CH_LAYOUT_6POINT1 | AV_CH_TOP_CENTER) || + m->avctx->channel_layout == (AV_CH_LAYOUT_6POINT1 | AV_CH_TOP_FRONT_CENTER))) { + int i = s->ch_assign[6]; + s->ch_assign[6] = s->ch_assign[5]; + s->ch_assign[5] = s->ch_assign[4]; + s->ch_assign[4] = i; + } + checksum = ff_mlp_restart_checksum(buf, get_bits_count(gbp) - start_count); if (checksum != get_bits(gbp, 8)) @@ -481,7 +536,7 @@ static int read_filter_params(MLPDecodeContext *m, GetBitContext *gbp, int i, order; // Filter is 0 for FIR, 1 for IIR. - assert(filter < 2); + av_assert0(filter < 2); if (m->filter_changed[channel][filter]++ > 1) { av_log(m->avctx, AV_LOG_ERROR, "Filters may change only once per access unit.\n"); @@ -1144,6 +1199,7 @@ error: return AVERROR_INVALIDDATA; } +#if CONFIG_MLP_DECODER AVCodec ff_mlp_decoder = { .name = "mlp", .type = AVMEDIA_TYPE_AUDIO, @@ -1154,7 +1210,7 @@ AVCodec ff_mlp_decoder = { .capabilities = CODEC_CAP_DR1, .long_name = NULL_IF_CONFIG_SMALL("MLP (Meridian Lossless Packing)"), }; - +#endif #if CONFIG_TRUEHD_DECODER AVCodec ff_truehd_decoder = { .name = "truehd", |