From 786c0fe7bfa8fa18c8c5efddd962329d445fbd58 Mon Sep 17 00:00:00 2001 From: UniqProject <3046095+UniqProject@users.noreply.github.com> Date: Sun, 22 Jan 2023 02:22:48 +0100 Subject: [PATCH] Add support for AAC audio streams implements #25 --- BDInfo/BDInfo.csproj | 1 + BDInfo/BDROM/TSCodecAAC.cs | 121 +++++++++++++++++++++++++++++++ BDInfo/BDROM/TSPlaylistFile.cs | 14 +++- BDInfo/BDROM/TSStream.cs | 14 ++++ BDInfo/BDROM/TSStreamClipFile.cs | 4 +- BDInfo/BDROM/TSStreamFile.cs | 8 ++ 6 files changed, 157 insertions(+), 5 deletions(-) create mode 100644 BDInfo/BDROM/TSCodecAAC.cs diff --git a/BDInfo/BDInfo.csproj b/BDInfo/BDInfo.csproj index 2686c62661..8e5c96f0e4 100644 --- a/BDInfo/BDInfo.csproj +++ b/BDInfo/BDInfo.csproj @@ -76,6 +76,7 @@ + diff --git a/BDInfo/BDROM/TSCodecAAC.cs b/BDInfo/BDROM/TSCodecAAC.cs new file mode 100644 index 0000000000..5d6581c84c --- /dev/null +++ b/BDInfo/BDROM/TSCodecAAC.cs @@ -0,0 +1,121 @@ +//============================================================================ +// BDInfo - Blu-ray Video and Audio Analysis Tool +// Copyright © 2010 Cinema Squid +// +// This library 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. +// +// This library 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 this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +//============================================================================= + +#undef DEBUG + +namespace BDInfo +{ + public abstract class TSCodecAAC + { + private static readonly string[] AACID = + { + "MPEG-4", + "MPEG-2", + }; + + private static string GetAACProfile(int profileType) + { + switch (profileType) + { + case 0: return "AAC Main"; + case 1: return "AAC LC"; + case 2: return "AAC SSR"; + case 3: return "AAC LTP"; + case 16: return "ER AAC LC"; + case 18: return "ER AAC LTP"; + case 36: return "SLS"; + default: return ""; + } + } + + public static int[] AACSampleRates = + { + 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, + 16000, 12000, 11025, 8000, 7350, 0, 0, 57600, + 51200, 40000, 38400, 34150, 28800, 25600, 20000, 19200, + 17075, 14400, 12800, 9600, 0, 0, 0 + }; + + private const int AACChannelsSize = 8; + + public static int[] AACChannels = { 0, 1, 2, 3, 4, 5, 6, 8 }; + + private static readonly byte[] AACChannelModes = + { + (byte)TSAudioMode.Unknown, + (byte)TSAudioMode.Mono, + (byte)TSAudioMode.Stereo, + (byte)TSAudioMode.Extended, + (byte)TSAudioMode.Surround, + (byte)TSAudioMode.Surround, + (byte)TSAudioMode.Surround, + (byte)TSAudioMode.Surround, + }; + + public static void Scan(TSAudioStream stream, TSStreamBuffer buffer, ref string tag) + { + if (stream.IsInitialized) return; + + int syncWord = buffer.ReadBits2(12); + if (syncWord != 0b1111_1111_1111) return; + + // fixed header + int audioVersionID = buffer.ReadBits2(1); + int layerIndex = buffer.ReadBits2(2); + bool protectionAbsent = buffer.ReadBool(); + int profileObjectType = buffer.ReadBits2(2); + int samplingRateIndex = buffer.ReadBits2(4); + bool privateBit = buffer.ReadBool(); + int channelMode = buffer.ReadBits2(3); + bool originalBit = buffer.ReadBool(); + bool home = buffer.ReadBool(); + + + if (samplingRateIndex <= 13) + stream.SampleRate = AACSampleRates[samplingRateIndex]; + else + stream.SampleRate = 0; + + + if (channelMode <= AACChannelsSize) + { + stream.AudioMode = (TSAudioMode)AACChannelModes[channelMode]; + stream.ChannelCount = AACChannels[channelMode]; + } + else + { + stream.ChannelCount = 0; + stream.AudioMode = TSAudioMode.Unknown; + } + + if (channelMode >=7 && channelMode <= 8) + { + stream.ChannelCount--; + stream.LFE = 1; + } + else + stream.LFE = 0; + + stream.ExtendedData = $"{AACID[audioVersionID]} {GetAACProfile(profileObjectType)}"; + + stream.IsVBR = true; + stream.IsInitialized = true; + } + } +} diff --git a/BDInfo/BDROM/TSPlaylistFile.cs b/BDInfo/BDROM/TSPlaylistFile.cs index 5ea87b8c90..b0d1c70089 100644 --- a/BDInfo/BDROM/TSPlaylistFile.cs +++ b/BDInfo/BDROM/TSPlaylistFile.cs @@ -694,6 +694,8 @@ protected TSStream CreatePlaylistStream(byte[] data, ref int pos) case TSStreamType.LPCM_AUDIO: case TSStreamType.MPEG1_AUDIO: case TSStreamType.MPEG2_AUDIO: + case TSStreamType.MPEG2_AAC_AUDIO: + case TSStreamType.MPEG4_AAC_AUDIO: int audioFormat = ReadByte(data, ref pos); @@ -1313,14 +1315,18 @@ private static int GetStreamTypeSortIndex(TSStreamType streamType) return 6; case TSStreamType.AC3_PLUS_AUDIO: return 7; - case TSStreamType.DTS_HD_AUDIO: + case TSStreamType.MPEG2_AAC_AUDIO: return 8; - case TSStreamType.AC3_TRUE_HD_AUDIO: + case TSStreamType.MPEG4_AAC_AUDIO: return 9; - case TSStreamType.DTS_HD_MASTER_AUDIO: + case TSStreamType.DTS_HD_AUDIO: return 10; - case TSStreamType.LPCM_AUDIO: + case TSStreamType.AC3_TRUE_HD_AUDIO: return 11; + case TSStreamType.DTS_HD_MASTER_AUDIO: + return 12; + case TSStreamType.LPCM_AUDIO: + return 13; case TSStreamType.SUBTITLE: return 1; diff --git a/BDInfo/BDROM/TSStream.cs b/BDInfo/BDROM/TSStream.cs index a8d8d88262..4ee6696cd7 100644 --- a/BDInfo/BDROM/TSStream.cs +++ b/BDInfo/BDROM/TSStream.cs @@ -34,6 +34,8 @@ public enum TSStreamType : byte VC1_VIDEO = 0xea, MPEG1_AUDIO = 0x03, MPEG2_AUDIO = 0x04, + MPEG2_AAC_AUDIO = 0x0F, + MPEG4_AAC_AUDIO = 0x11, LPCM_AUDIO = 0x80, AC3_AUDIO = 0x81, AC3_PLUS_AUDIO = 0x84, @@ -191,6 +193,8 @@ public bool IsAudioStream { case TSStreamType.MPEG1_AUDIO: case TSStreamType.MPEG2_AUDIO: + case TSStreamType.MPEG2_AAC_AUDIO: + case TSStreamType.MPEG4_AAC_AUDIO: case TSStreamType.LPCM_AUDIO: case TSStreamType.AC3_AUDIO: case TSStreamType.AC3_PLUS_AUDIO: @@ -259,6 +263,8 @@ public string CodecName return "VC-1 Video"; case TSStreamType.MPEG1_AUDIO: case TSStreamType.MPEG2_AUDIO: + case TSStreamType.MPEG2_AAC_AUDIO: + case TSStreamType.MPEG4_AAC_AUDIO: return (string)((TSAudioStream)this).ExtendedData; case TSStreamType.LPCM_AUDIO: return "LPCM Audio"; @@ -330,6 +336,10 @@ public string CodecAltName return "MP1"; case TSStreamType.MPEG2_AUDIO: return "MP2"; + case TSStreamType.MPEG2_AAC_AUDIO: + return "MPEG-2 AAC"; + case TSStreamType.MPEG4_AAC_AUDIO: + return "MPEG-4 AAC"; case TSStreamType.LPCM_AUDIO: return "LPCM"; case TSStreamType.AC3_AUDIO: @@ -390,6 +400,10 @@ public string CodecShortName return "MP1"; case TSStreamType.MPEG2_AUDIO: return "MP2"; + case TSStreamType.MPEG2_AAC_AUDIO: + return "MPEG-2 AAC"; + case TSStreamType.MPEG4_AAC_AUDIO: + return "MPEG-4 AAC"; case TSStreamType.LPCM_AUDIO: return "LPCM"; case TSStreamType.AC3_AUDIO: diff --git a/BDInfo/BDROM/TSStreamClipFile.cs b/BDInfo/BDROM/TSStreamClipFile.cs index b4f13c4f34..f26c587e2f 100644 --- a/BDInfo/BDROM/TSStreamClipFile.cs +++ b/BDInfo/BDROM/TSStreamClipFile.cs @@ -186,7 +186,9 @@ public void Scan() case TSStreamType.LPCM_AUDIO: case TSStreamType.MPEG1_AUDIO: case TSStreamType.MPEG2_AUDIO: - { + case TSStreamType.MPEG2_AAC_AUDIO: + case TSStreamType.MPEG4_AAC_AUDIO: + { byte[] languageBytes = new byte[3]; Array.Copy(clipData, streamOffset + 3, languageBytes, 0, languageBytes.Length); diff --git a/BDInfo/BDROM/TSStreamFile.cs b/BDInfo/BDROM/TSStreamFile.cs index 144e60122f..cec120ed55 100644 --- a/BDInfo/BDROM/TSStreamFile.cs +++ b/BDInfo/BDROM/TSStreamFile.cs @@ -275,6 +275,12 @@ private bool ScanStream( (TSAudioStream)stream, buffer, ref streamState.StreamTag); break; + case TSStreamType.MPEG2_AAC_AUDIO: + case TSStreamType.MPEG4_AAC_AUDIO: + TSCodecAAC.Scan( + (TSAudioStream)stream, buffer, ref streamState.StreamTag); + break; + case TSStreamType.AC3_AUDIO: TSCodecAC3.Scan( (TSAudioStream)stream, buffer, ref streamState.StreamTag); @@ -1562,6 +1568,8 @@ private TSStream CreateStream( case TSStreamType.LPCM_AUDIO: case TSStreamType.MPEG1_AUDIO: case TSStreamType.MPEG2_AUDIO: + case TSStreamType.MPEG2_AAC_AUDIO: + case TSStreamType.MPEG4_AAC_AUDIO: { stream = new TSAudioStream(); }