New: Added support for DTS-HD MA and TrueHD Atmos in MediaInfo AudioCodec.

This commit is contained in:
Matt Evans 2019-02-03 16:52:37 +11:00
parent e5632019db
commit 1606ea19a8
6 changed files with 92 additions and 20 deletions

View File

@ -91,6 +91,11 @@ namespace NzbDrone.Common.Extensions
return text.StartsWith(startsWith, StringComparison.InvariantCultureIgnoreCase);
}
public static bool EndsWithIgnoreCase(this string text, string startsWith)
{
return text.EndsWith(startsWith, StringComparison.InvariantCultureIgnoreCase);
}
public static bool EqualsIgnoreCase(this string text, string equals)
{
return text.Equals(equals, StringComparison.InvariantCultureIgnoreCase);
@ -140,5 +145,10 @@ namespace NzbDrone.Common.Extensions
{
return CamelCaseRegex.Replace(input, match => " " + match.Value);
}
public static bool ContainsIgnoreCase(this IEnumerable<string> source, string value)
{
return source.Contains(value, StringComparer.InvariantCultureIgnoreCase);
}
}
}

View File

@ -24,14 +24,26 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
MediaInfoFormatter.FormatAudioCodec(mediaInfoModel, sceneName).Should().Be(expectedFormat);
}
[TestCase("MPEG Audio, A_MPEG/L2, , ", "droned.s01e03.swedish.720p.hdtv.x264-prince", "MP2")]
[TestCase("Vorbis, A_VORBIS, , Xiph.Org libVorbis I 20101101 (Schaufenugget)", "DB Super HDTV", "Vorbis")]
[TestCase("PCM, 1, , ", "DW DVDRip XviD-idTV", "PCM")] // Dubbed most likely
[TestCase("TrueHD, A_TRUEHD, , ", "", "TrueHD")]
[TestCase("WMA, 161, , ", "Droned.wmv", "WMA")]
[TestCase("WMA, 162, Pro, ", "B.N.S04E18.720p.WEB-DL", "WMA")]
[TestCase("Opus, A_OPUS, , ", "Roadkill Ep3x11 - YouTube.webm", "Opus")]
[TestCase("mp3 , 0, , ", "climbing.mp4", "MP3")]
[TestCase("MPEG Audio, A_MPEG/L2, , , ", "droned.s01e03.swedish.720p.hdtv.x264-prince", "MP2")]
[TestCase("Vorbis, A_VORBIS, , Xiph.Org libVorbis I 20101101 (Schaufenugget), ", "DB Super HDTV", "Vorbis")]
[TestCase("PCM, 1, , , ", "DW DVDRip XviD-idTV, ", "PCM")] // Dubbed most likely
[TestCase("TrueHD, A_TRUEHD, , , ", "", "TrueHD")]
[TestCase("MLP FBA, A_TRUEHD, , , ", "TrueHD", "TrueHD")]
[TestCase("MLP FBA, A_TRUEHD, , , 16-ch", "Atmos", "TrueHD Atmos")]
[TestCase("WMA, 161, , , ", "Droned.wmv", "WMA")]
[TestCase("WMA, 162, Pro, , ", "B.N.S04E18.720p.WEB-DL", "WMA")]
[TestCase("Opus, A_OPUS, , , ", "Roadkill Ep3x11 - YouTube.webm", "Opus")]
[TestCase("mp3 , 0, , , ", "climbing.mp4", "MP3")]
[TestCase("DTS, A_DTS, , , XLL", "DTS-HD.MA", "DTS-HD MA")]
[TestCase("DTS, A_DTS, , , XLL X", "DTS-X", "DTS-X")]
[TestCase("DTS, A_DTS, , , ES XLL", "DTS-HD.MA", "DTS-HD MA")]
[TestCase("DTS, A_DTS, , , ES", "DTS-ES", "DTS-ES")]
[TestCase("DTS, A_DTS, , , ES XXCH", "DTS", "DTS-ES")]
[TestCase("DTS, A_DTS, , , XBR", "DTSHD-HRA", "DTS-HD HRA")]
[TestCase("DTS, A_DTS, , , DTS", "DTS", "DTS")]
[TestCase("E-AC-3, A_EAC3, , , JOC", "EAC3", "EAC3")]
[TestCase("E-AC-3, A_EAC3, , , ", "DD5.1", "EAC3")]
[TestCase("AC-3, A_AC3, , , ", "DD5.1", "AC3")]
public void should_format_audio_format(string audioFormatPack, string sceneName, string expectedFormat)
{
var split = audioFormatPack.Split(new string[] { ", " }, System.StringSplitOptions.None);
@ -40,7 +52,8 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
AudioFormat = split[0],
AudioCodecID = split[1],
AudioProfile = split[2],
AudioCodecLibrary = split[3]
AudioCodecLibrary = split[3],
AudioAdditionalFeatures = split[4]
};
MediaInfoFormatter.FormatAudioCodec(mediaInfoModel, sceneName).Should().Be(expectedFormat);

View File

@ -59,6 +59,9 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
info.VideoBitrate.Should().Be(193329);
info.VideoFps.Should().Be(24);
info.Width.Should().Be(480);
info.VideoColourPrimaries.Should().Be("BT.601 NTSC");
info.VideoTransferCharacteristics.Should().Be("BT.709");
info.AudioAdditionalFeatures.Should().Be("");
}
@ -95,6 +98,9 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
info.VideoBitrate.Should().Be(193329);
info.VideoFps.Should().Be(24);
info.Width.Should().Be(480);
info.VideoColourPrimaries.Should().Be("BT.601 NTSC");
info.VideoTransferCharacteristics.Should().Be("BT.709");
info.AudioAdditionalFeatures.Should().Be("");
}
[Test]

View File

@ -43,6 +43,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
var audioCodecID = mediaInfo.AudioCodecID ?? string.Empty;
var audioProfile = mediaInfo.AudioProfile ?? string.Empty;
var audioCodecLibrary = mediaInfo.AudioCodecLibrary ?? string.Empty;
var splitAdditionalFeatures = (mediaInfo.AudioAdditionalFeatures ?? string.Empty).Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries);
if (audioFormat.IsNullOrWhiteSpace())
{
@ -71,6 +72,25 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
if (audioFormat.EqualsIgnoreCase("DTS"))
{
if (splitAdditionalFeatures.ContainsIgnoreCase("XLL"))
{
if (splitAdditionalFeatures.ContainsIgnoreCase("X"))
{
return "DTS-X";
}
return "DTS-HD MA";
}
if (splitAdditionalFeatures.ContainsIgnoreCase("ES"))
{
return "DTS-ES";
}
if (splitAdditionalFeatures.ContainsIgnoreCase("XBR"))
{
return "DTS-HD HRA";
}
return "DTS";
}
@ -112,6 +132,16 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
return "TrueHD";
}
if (audioFormat.EqualsIgnoreCase("MLP FBA"))
{
if (splitAdditionalFeatures.ContainsIgnoreCase("16-ch"))
{
return "TrueHD Atmos";
}
return "TrueHD";
}
if (audioFormat.EqualsIgnoreCase("Vorbis"))
{
return "Vorbis";
@ -373,13 +403,16 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
.Sum(s => decimal.Parse(s.Trim(), CultureInfo.InvariantCulture));
}
return Regex.Replace(audioChannelPositions, @"^\d+\sobjects", "", RegexOptions.Compiled | RegexOptions.IgnoreCase)
.Replace("Object Based / ", "")
.Split(new string[] { " / " }, StringSplitOptions.RemoveEmptyEntries)
.FirstOrDefault()
?.Split('/')
.Sum(s => decimal.Parse(s, CultureInfo.InvariantCulture));
if (audioChannelPositions.Contains("/"))
{
return Regex.Replace(audioChannelPositions, @"^\d+\sobjects", "",
RegexOptions.Compiled | RegexOptions.IgnoreCase)
.Replace("Object Based / ", "")
.Split(new string[] {" / "}, StringSplitOptions.RemoveEmptyEntries)
.FirstOrDefault()
?.Split('/')
.Sum(s => decimal.Parse(s, CultureInfo.InvariantCulture));
}
}
catch (Exception e)
{
@ -401,7 +434,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
try
{
return mediaInfo.AudioChannelPositionsText.ContainsIgnoreCase("LFE") ? audioChannels - 1 + 0.1m : audioChannels;
return audioChannelPositionsText.ContainsIgnoreCase("LFE") ? audioChannels - 1 + 0.1m : audioChannels;
}
catch (Exception e)
{

View File

@ -18,11 +18,15 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
public string VideoCodecLibrary { get; set; }
public int VideoBitrate { get; set; }
public int VideoBitDepth { get; set; }
public int VideoMultiViewCount { get; set; }
public string VideoColourPrimaries { get; set; }
public string VideoTransferCharacteristics { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public string AudioFormat { get; set; }
public string AudioCodecID { get; set; }
public string AudioCodecLibrary { get; set; }
public string AudioAdditionalFeatures { get; set; }
public int AudioBitrate { get; set; }
public TimeSpan RunTime { get; set; }
public int AudioStreamCount { get; set; }

View File

@ -18,7 +18,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
private readonly Logger _logger;
public const int MINIMUM_MEDIA_INFO_SCHEMA_REVISION = 3;
public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 4;
public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 5;
public VideoFileInfoReader(IDiskProvider diskProvider, Logger logger)
{
@ -94,18 +94,20 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
int audioChannels;
int videoBitDepth;
decimal videoFrameRate;
int videoMultiViewCount;
string subtitles = mediaInfo.Get(StreamKind.General, 0, "Text_Language_List");
string scanType = mediaInfo.Get(StreamKind.Video, 0, "ScanType");
int.TryParse(mediaInfo.Get(StreamKind.Video, 0, "Width"), out width);
int.TryParse(mediaInfo.Get(StreamKind.Video, 0, "Height"), out height);
int.TryParse(mediaInfo.Get(StreamKind.Video, 0, "BitRate_Nominal"), out videoBitRate);
int.TryParse(mediaInfo.Get(StreamKind.Video, 0, "BitRate"), out videoBitRate);
if (videoBitRate <= 0)
{
int.TryParse(mediaInfo.Get(StreamKind.Video, 0, "BitRate"), out videoBitRate);
int.TryParse(mediaInfo.Get(StreamKind.Video, 0, "BitRate_Nominal"), out videoBitRate);
}
decimal.TryParse(mediaInfo.Get(StreamKind.Video, 0, "FrameRate"), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out videoFrameRate);
int.TryParse(mediaInfo.Get(StreamKind.Video, 0, "BitDepth"), out videoBitDepth);
int.TryParse(mediaInfo.Get(StreamKind.Video, 0, "MultiView_Count"), out videoMultiViewCount);
//Runtime
int.TryParse(mediaInfo.Get(StreamKind.Video, 0, "PlayTime"), out videoRuntime);
@ -138,12 +140,16 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
VideoCodecLibrary = mediaInfo.Get(StreamKind.Video, 0, "Encoded_Library"),
VideoBitrate = videoBitRate,
VideoBitDepth = videoBitDepth,
VideoMultiViewCount = videoMultiViewCount,
VideoColourPrimaries = mediaInfo.Get(StreamKind.Video, 0, "colour_primaries"),
VideoTransferCharacteristics = mediaInfo.Get(StreamKind.Video, 0, "transfer_characteristics"),
Height = height,
Width = width,
AudioFormat = mediaInfo.Get(StreamKind.Audio, 0, "Format"),
AudioCodecID = mediaInfo.Get(StreamKind.Audio, 0, "CodecID"),
AudioProfile = audioProfile,
AudioCodecLibrary = mediaInfo.Get(StreamKind.Audio, 0, "Encoded_Library"),
AudioAdditionalFeatures = mediaInfo.Get(StreamKind.Audio, 0, "Format_AdditionalFeatures"),
AudioBitrate = audioBitRate,
RunTime = GetBestRuntime(audioRuntime, videoRuntime, generalRuntime),
AudioStreamCount = streamCount,