X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmlp_parser.c;h=075227f302dbbdb1ec9e0294006617bc2109f7fc;hb=369380e1c4c6fc9b0d9ff04ec23d46b252ba7110;hp=716e9e9b2a1da77bb2105a065f0550346a7b225a;hpb=8790961d7eda786f624317312c6ecc51945865e3;p=ffmpeg diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index 716e9e9b2a1..075227f302d 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -2,31 +2,33 @@ * MLP parser * Copyright (c) 2007 Ian Caulfield * - * This file is part of FFmpeg. + * This file is part of Libav. * - * FFmpeg is free software; you can redistribute it and/or + * Libav 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. * - * FFmpeg is distributed in the hope that it will be useful, + * Libav 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 FFmpeg; if not, write to the Free Software + * License along with Libav; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** - * @file libavcodec/mlp_parser.c + * @file * MLP parser */ #include +#include "libavutil/channel_layout.h" #include "libavutil/crc.h" +#include "libavutil/internal.h" #include "get_bits.h" #include "parser.h" #include "mlp_parser.h" @@ -42,11 +44,52 @@ static const uint8_t mlp_channels[32] = { 5, 6, 5, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; +static const uint64_t mlp_layout[32] = { + AV_CH_LAYOUT_MONO, + AV_CH_LAYOUT_STEREO, + AV_CH_LAYOUT_2_1, + AV_CH_LAYOUT_2_2, + AV_CH_LAYOUT_STEREO|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_2_1|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_2_2|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_SURROUND, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_5POINT1, + AV_CH_LAYOUT_4POINT0, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_SURROUND|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_4POINT0|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_5POINT1, + AV_CH_LAYOUT_2_2|AV_CH_LOW_FREQUENCY, + AV_CH_LAYOUT_5POINT0, + AV_CH_LAYOUT_5POINT1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + static const uint8_t thd_chancount[13] = { // LR C LFE LRs LRvh LRc LRrs Cs Ts LRsd LRw Cvh LFE2 2, 1, 1, 2, 2, 2, 2, 1, 1, 2, 2, 1, 1 }; +static const uint64_t thd_layout[13] = { + AV_CH_FRONT_LEFT|AV_CH_FRONT_RIGHT, // LR + AV_CH_FRONT_CENTER, // C + AV_CH_LOW_FREQUENCY, // LFE + AV_CH_SIDE_LEFT|AV_CH_SIDE_RIGHT, // LRs + AV_CH_TOP_FRONT_LEFT|AV_CH_TOP_FRONT_RIGHT, // LRvh + AV_CH_FRONT_LEFT_OF_CENTER|AV_CH_FRONT_RIGHT_OF_CENTER, // LRc + AV_CH_BACK_LEFT|AV_CH_BACK_RIGHT, // LRrs + AV_CH_BACK_CENTER, // Cs + AV_CH_TOP_CENTER, // Ts + AV_CH_SURROUND_DIRECT_LEFT|AV_CH_SURROUND_DIRECT_RIGHT, // LRsd + AV_CH_WIDE_LEFT|AV_CH_WIDE_RIGHT, // LRw + AV_CH_TOP_FRONT_CENTER, // Cvh + AV_CH_LOW_FREQUENCY_2, // LFE2 +}; + static int mlp_samplerate(int in) { if (in == 0xF) @@ -65,6 +108,17 @@ static int truehd_channels(int chanmap) return channels; } +static uint64_t truehd_layout(int chanmap) +{ + int i; + uint64_t layout = 0; + + for (i = 0; i < 13; i++) + layout |= thd_layout[i] * ((chanmap >> i) & 1); + + return layout; +} + /** Read a major sync info header - contains high level information about * the stream - sample rate, channel arrangement etc. Most of this * information is not actually necessary for decoding, only for playback. @@ -73,7 +127,7 @@ static int truehd_channels(int chanmap) int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) { - int ratebits; + int ratebits, channel_arrangement; uint16_t checksum; assert(get_bits_count(gb) == 0); @@ -86,11 +140,11 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) checksum = ff_mlp_checksum16(gb->buffer, 26); if (checksum != AV_RL16(gb->buffer+26)) { av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n"); - return -1; + return AVERROR_INVALIDDATA; } if (get_bits_long(gb, 24) != 0xf8726f) /* Sync words */ - return -1; + return AVERROR_INVALIDDATA; mh->stream_type = get_bits(gb, 8); @@ -104,7 +158,9 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) skip_bits(gb, 11); - mh->channels_mlp = get_bits(gb, 5); + channel_arrangement = get_bits(gb, 5); + mh->channels_mlp = mlp_channels[channel_arrangement]; + mh->channel_layout_mlp = mlp_layout[channel_arrangement]; } else if (mh->stream_type == 0xba) { mh->group1_bits = 24; // TODO: Is this information actually conveyed anywhere? mh->group2_bits = 0; @@ -113,15 +169,22 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) mh->group1_samplerate = mlp_samplerate(ratebits); mh->group2_samplerate = 0; - skip_bits(gb, 8); + skip_bits(gb, 4); - mh->channels_thd_stream1 = get_bits(gb, 5); + mh->channel_modifier_thd_stream0 = get_bits(gb, 2); + mh->channel_modifier_thd_stream1 = get_bits(gb, 2); - skip_bits(gb, 2); + channel_arrangement = get_bits(gb, 5); + mh->channels_thd_stream1 = truehd_channels(channel_arrangement); + mh->channel_layout_thd_stream1 = truehd_layout(channel_arrangement); - mh->channels_thd_stream2 = get_bits(gb, 13); + mh->channel_modifier_thd_stream2 = get_bits(gb, 2); + + channel_arrangement = get_bits(gb, 13); + mh->channels_thd_stream2 = truehd_channels(channel_arrangement); + mh->channel_layout_thd_stream2 = truehd_layout(channel_arrangement); } else - return -1; + return AVERROR_INVALIDDATA; mh->access_unit_size = 40 << (ratebits & 7); mh->access_unit_size_pow2 = 64 << (ratebits & 7); @@ -255,21 +318,64 @@ static int mlp_parse(AVCodecParserContext *s, avctx->bits_per_raw_sample = mh.group1_bits; if (avctx->bits_per_raw_sample > 16) - avctx->sample_fmt = SAMPLE_FMT_S32; + avctx->sample_fmt = AV_SAMPLE_FMT_S32; else - avctx->sample_fmt = SAMPLE_FMT_S16; + avctx->sample_fmt = AV_SAMPLE_FMT_S16; avctx->sample_rate = mh.group1_samplerate; - avctx->frame_size = mh.access_unit_size; + s->duration = mh.access_unit_size; if (mh.stream_type == 0xbb) { /* MLP stream */ - avctx->channels = mlp_channels[mh.channels_mlp]; +#if FF_API_REQUEST_CHANNELS +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->request_channels > 0 && avctx->request_channels <= 2 && + mh.num_substreams > 1) { + avctx->channels = 2; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + } else +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (avctx->request_channel_layout && + (avctx->request_channel_layout & AV_CH_LAYOUT_STEREO) == + avctx->request_channel_layout && + mh.num_substreams > 1) { + avctx->channels = 2; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + } else { + avctx->channels = mh.channels_mlp; + avctx->channel_layout = mh.channel_layout_mlp; + } } else { /* mh.stream_type == 0xba */ /* TrueHD stream */ - if (mh.channels_thd_stream2) - avctx->channels = truehd_channels(mh.channels_thd_stream2); - else - avctx->channels = truehd_channels(mh.channels_thd_stream1); +#if FF_API_REQUEST_CHANNELS +FF_DISABLE_DEPRECATION_WARNINGS + if (avctx->request_channels > 0 && avctx->request_channels <= 2 && + mh.num_substreams > 1) { + avctx->channels = 2; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + } else if (avctx->request_channels > 0 && + avctx->request_channels <= mh.channels_thd_stream1) { + avctx->channels = mh.channels_thd_stream1; + avctx->channel_layout = mh.channel_layout_thd_stream1; + } else +FF_ENABLE_DEPRECATION_WARNINGS +#endif + if (avctx->request_channel_layout && + (avctx->request_channel_layout & AV_CH_LAYOUT_STEREO) == + avctx->request_channel_layout && + mh.num_substreams > 1) { + avctx->channels = 2; + avctx->channel_layout = AV_CH_LAYOUT_STEREO; + } else if (!mh.channels_thd_stream2 || + (avctx->request_channel_layout && + (avctx->request_channel_layout & mh.channel_layout_thd_stream1) == + avctx->request_channel_layout)) { + avctx->channels = mh.channels_thd_stream1; + avctx->channel_layout = mh.channel_layout_thd_stream1; + } else { + avctx->channels = mh.channels_thd_stream2; + avctx->channel_layout = mh.channel_layout_thd_stream2; + } } if (!mh.is_vbr) /* Stream is CBR */ @@ -288,10 +394,10 @@ lost_sync: return 1; } -AVCodecParser mlp_parser = { - { CODEC_ID_MLP, CODEC_ID_TRUEHD }, - sizeof(MLPParseContext), - mlp_init, - mlp_parse, - ff_parse_close, +AVCodecParser ff_mlp_parser = { + .codec_ids = { AV_CODEC_ID_MLP, AV_CODEC_ID_TRUEHD }, + .priv_data_size = sizeof(MLPParseContext), + .parser_init = mlp_init, + .parser_parse = mlp_parse, + .parser_close = ff_parse_close, };