From 27dca830cc09fcc796b30bc488b844fbc5e5e70e Mon Sep 17 00:00:00 2001 From: Taloth Saldono Date: Sun, 30 Jul 2017 21:30:34 +0200 Subject: [PATCH] Updated MediaInfo schema and revised logic that Formats it. Also added logic to log events to Sentry. --- .../Extensions/StringExtensions.cs | 12 +- ...gressExtensions.cs => LoggerExtensions.cs} | 1 + .../Extensions/SentryLoggerExtensions.cs | 58 ++++++ .../Instrumentation/NzbDroneLogger.cs | 6 +- .../Instrumentation/Sentry/SentryTarget.cs | 35 +++- src/NzbDrone.Common/NzbDrone.Common.csproj | 3 +- .../FormatAudioCodecFixture.cs | 5 +- .../FormatVideoCodecFixture.cs | 8 +- .../UpdateMediaInfoServiceFixture.cs | 28 ++- .../MediaInfo/MediaInfoFormatter.cs | 194 +++++++++++++++--- .../MediaFiles/MediaInfo/MediaInfoModel.cs | 8 + .../MediaInfo/UnknownCodecException.cs | 20 -- .../MediaInfo/UpdateMediaInfoService.cs | 5 +- .../MediaInfo/VideoFileInfoReader.cs | 34 ++- src/NzbDrone.Core/NzbDrone.Core.csproj | 1 - 15 files changed, 338 insertions(+), 80 deletions(-) rename src/NzbDrone.Common/Instrumentation/Extensions/{LoggerProgressExtensions.cs => LoggerExtensions.cs} (98%) create mode 100644 src/NzbDrone.Common/Instrumentation/Extensions/SentryLoggerExtensions.cs delete mode 100644 src/NzbDrone.Core/MediaFiles/MediaInfo/UnknownCodecException.cs diff --git a/src/NzbDrone.Common/Extensions/StringExtensions.cs b/src/NzbDrone.Common/Extensions/StringExtensions.cs index 247274e29..9fffd6858 100644 --- a/src/NzbDrone.Common/Extensions/StringExtensions.cs +++ b/src/NzbDrone.Common/Extensions/StringExtensions.cs @@ -78,6 +78,16 @@ namespace NzbDrone.Common.Extensions return !string.IsNullOrWhiteSpace(text); } + public static bool StartsWithIgnoreCase(this string text, string startsWith) + { + return text.StartsWith(startsWith, StringComparison.InvariantCultureIgnoreCase); + } + + public static bool EqualsIgnoreCase(this string text, string equals) + { + return text.Equals(equals, StringComparison.InvariantCultureIgnoreCase); + } + public static bool ContainsIgnoreCase(this string text, string contains) { return text.IndexOf(contains, StringComparison.InvariantCultureIgnoreCase) > -1; @@ -118,4 +128,4 @@ namespace NzbDrone.Common.Extensions return Encoding.ASCII.GetString(new [] { byteResult }); } } -} \ No newline at end of file +} diff --git a/src/NzbDrone.Common/Instrumentation/Extensions/LoggerProgressExtensions.cs b/src/NzbDrone.Common/Instrumentation/Extensions/LoggerExtensions.cs similarity index 98% rename from src/NzbDrone.Common/Instrumentation/Extensions/LoggerProgressExtensions.cs rename to src/NzbDrone.Common/Instrumentation/Extensions/LoggerExtensions.cs index 5abeeb6ba..ca377e8f4 100644 --- a/src/NzbDrone.Common/Instrumentation/Extensions/LoggerProgressExtensions.cs +++ b/src/NzbDrone.Common/Instrumentation/Extensions/LoggerExtensions.cs @@ -1,4 +1,5 @@ using NLog; +using NLog.Fluent; namespace NzbDrone.Common.Instrumentation.Extensions { diff --git a/src/NzbDrone.Common/Instrumentation/Extensions/SentryLoggerExtensions.cs b/src/NzbDrone.Common/Instrumentation/Extensions/SentryLoggerExtensions.cs new file mode 100644 index 000000000..063a01439 --- /dev/null +++ b/src/NzbDrone.Common/Instrumentation/Extensions/SentryLoggerExtensions.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NLog; +using NLog.Fluent; + +namespace NzbDrone.Common.Instrumentation.Extensions +{ + public static class SentryLoggerExtensions + { + public static readonly Logger SentryLogger = LogManager.GetLogger("Sentry"); + + public static LogBuilder SentryFingerprint(this LogBuilder logBuilder, params string[] fingerprint) + { + return logBuilder.Property("Sentry", fingerprint); + } + + public static LogBuilder WriteSentryDebug(this LogBuilder logBuilder, params string[] fingerprint) + { + return LogSentryMessage(logBuilder, LogLevel.Debug, fingerprint); + } + + public static LogBuilder WriteSentryInfo(this LogBuilder logBuilder, params string[] fingerprint) + { + return LogSentryMessage(logBuilder, LogLevel.Info, fingerprint); + } + + public static LogBuilder WriteSentryWarn(this LogBuilder logBuilder, params string[] fingerprint) + { + return LogSentryMessage(logBuilder, LogLevel.Warn, fingerprint); + } + + public static LogBuilder WriteSentryError(this LogBuilder logBuilder, params string[] fingerprint) + { + return LogSentryMessage(logBuilder, LogLevel.Error, fingerprint); + } + + private static LogBuilder LogSentryMessage(LogBuilder logBuilder, LogLevel level, string[] fingerprint) + { + SentryLogger.Log(level) + .CopyLogEvent(logBuilder.LogEventInfo) + .SentryFingerprint(fingerprint) + .Write(); + + return logBuilder.Property("Sentry", null); + } + + private static LogBuilder CopyLogEvent(this LogBuilder logBuilder, LogEventInfo logEvent) + { + return logBuilder.LoggerName(logEvent.LoggerName) + .TimeStamp(logEvent.TimeStamp) + .Message(logEvent.Message, logEvent.Parameters) + .Properties((Dictionary)logEvent.Properties) + .Exception(logEvent.Exception); + } + } +} diff --git a/src/NzbDrone.Common/Instrumentation/NzbDroneLogger.cs b/src/NzbDrone.Common/Instrumentation/NzbDroneLogger.cs index 60373b991..b2ae7537b 100644 --- a/src/NzbDrone.Common/Instrumentation/NzbDroneLogger.cs +++ b/src/NzbDrone.Common/Instrumentation/NzbDroneLogger.cs @@ -109,9 +109,13 @@ namespace NzbDrone.Common.Instrumentation Layout = "${message}" }; - var loggingRule = new LoggingRule("*", updateClient ? LogLevel.Trace : LogLevel.Error, target); + var loggingRule = new LoggingRule("*", updateClient ? LogLevel.Trace : LogLevel.Warn, target); LogManager.Configuration.AddTarget("sentryTarget", target); LogManager.Configuration.LoggingRules.Add(loggingRule); + + // Events logged to Sentry go only to Sentry. + var loggingRuleSentry = new LoggingRule("Sentry", LogLevel.Debug, target) { Final = true }; + LogManager.Configuration.LoggingRules.Insert(0, loggingRuleSentry); } private static void RegisterDebugger() diff --git a/src/NzbDrone.Common/Instrumentation/Sentry/SentryTarget.cs b/src/NzbDrone.Common/Instrumentation/Sentry/SentryTarget.cs index 176884a31..6b3997612 100644 --- a/src/NzbDrone.Common/Instrumentation/Sentry/SentryTarget.cs +++ b/src/NzbDrone.Common/Instrumentation/Sentry/SentryTarget.cs @@ -71,6 +71,11 @@ namespace NzbDrone.Common.Instrumentation.Sentry private static List GetFingerPrint(LogEventInfo logEvent) { + if (logEvent.Properties.ContainsKey("Sentry")) + { + return ((string[])logEvent.Properties["Sentry"]).ToList(); + } + var fingerPrint = new List { logEvent.Level.Ordinal.ToString(), @@ -94,13 +99,33 @@ namespace NzbDrone.Common.Instrumentation.Sentry return fingerPrint; } + private bool IsSentryMessage(LogEventInfo logEvent) + { + if (logEvent.Properties.ContainsKey("Sentry")) + { + return logEvent.Properties["Sentry"] != null; + } + + if (logEvent.Level >= LogLevel.Error && logEvent.Exception != null) + { + return true; + } + + return false; + } + protected override void Write(LogEventInfo logEvent) { + if (_unauthorized) + { + return; + } + try { // don't report non-critical events without exceptions - if (logEvent.Exception == null || _unauthorized) + if (!IsSentryMessage(logEvent)) { return; } @@ -112,6 +137,7 @@ namespace NzbDrone.Common.Instrumentation.Sentry } var extras = logEvent.Properties.ToDictionary(x => x.Key.ToString(), x => x.Value.ToString()); + extras.Remove("Sentry"); _client.Logger = logEvent.LoggerName; var sentryMessage = new SentryMessage(logEvent.Message, logEvent.Parameters); @@ -134,11 +160,16 @@ namespace NzbDrone.Common.Instrumentation.Sentry sentryEvent.Fingerprint.Add(logEvent.Exception.GetType().FullName); } + if (logEvent.Properties.ContainsKey("Sentry")) + { + sentryEvent.Fingerprint.Clear(); + Array.ForEach((string[])logEvent.Properties["Sentry"], sentryEvent.Fingerprint.Add); + } + var osName = Environment.GetEnvironmentVariable("OS_NAME"); var osVersion = Environment.GetEnvironmentVariable("OS_VERSION"); var runTimeVersion = Environment.GetEnvironmentVariable("RUNTIME_VERSION"); - sentryEvent.Tags.Add("os_name", osName); sentryEvent.Tags.Add("os_version", $"{osName} {osVersion}"); sentryEvent.Tags.Add("runtime_version", $"{PlatformInfo.PlatformName} {runTimeVersion}"); diff --git a/src/NzbDrone.Common/NzbDrone.Common.csproj b/src/NzbDrone.Common/NzbDrone.Common.csproj index 2e2197f52..088272149 100644 --- a/src/NzbDrone.Common/NzbDrone.Common.csproj +++ b/src/NzbDrone.Common/NzbDrone.Common.csproj @@ -177,7 +177,8 @@ - + + diff --git a/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatAudioCodecFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatAudioCodecFixture.cs index a4e72c538..5168115df 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatAudioCodecFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatAudioCodecFixture.cs @@ -41,11 +41,12 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests { var mediaInfoModel = new MediaInfoModel { - AudioFormat = "Other Audio Format" + AudioFormat = "Other Audio Format", + AudioCodecID = "Other Audio Codec" }; MediaInfoFormatter.FormatAudioCodec(mediaInfoModel, sceneName).Should().Be(mediaInfoModel.AudioFormat); - ExceptionVerification.ExpectedErrors(1); + ExceptionVerification.ExpectedWarns(1); } } } diff --git a/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatVideoCodecFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatVideoCodecFixture.cs index d4345b026..aa18c1df9 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatVideoCodecFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatVideoCodecFixture.cs @@ -26,15 +26,15 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests } [Test] - public void should_return_VideoCodec_by_default() + public void should_return_VideoFormat_by_default() { var mediaInfoModel = new MediaInfoModel { - VideoCodec = "VideoCodec" + VideoFormat = "VideoCodec" }; - MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, null).Should().Be(mediaInfoModel.VideoCodec); - ExceptionVerification.ExpectedErrors(1); + MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, null).Should().Be(mediaInfoModel.VideoFormat); + ExceptionVerification.ExpectedWarns(1); } } } diff --git a/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/UpdateMediaInfoServiceFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/UpdateMediaInfoServiceFixture.cs index 4ea9af0f2..eae30f9c6 100644 --- a/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/UpdateMediaInfoServiceFixture.cs +++ b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/UpdateMediaInfoServiceFixture.cs @@ -60,7 +60,33 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo .All() .With(v => v.RelativePath = "media.mkv") .TheFirst(1) - .With(v => v.MediaInfo = new MediaInfoModel { SchemaRevision = 3 }) + .With(v => v.MediaInfo = new MediaInfoModel { SchemaRevision = UpdateMediaInfoService.CURRENT_MEDIA_INFO_SCHEMA_REVISION }) + .BuildList(); + + Mocker.GetMock() + .Setup(v => v.GetFilesBySeries(1)) + .Returns(episodeFiles); + + GivenFileExists(); + GivenSuccessfulScan(); + + Subject.Handle(new SeriesScannedEvent(_series)); + + Mocker.GetMock() + .Verify(v => v.GetMediaInfo(Path.Combine(_series.Path, "media.mkv")), Times.Exactly(2)); + + Mocker.GetMock() + .Verify(v => v.Update(It.IsAny()), Times.Exactly(2)); + } + + [Test] + public void should_skip_not_yet_date_media_info() + { + var episodeFiles = Builder.CreateListOfSize(3) + .All() + .With(v => v.RelativePath = "media.mkv") + .TheFirst(1) + .With(v => v.MediaInfo = new MediaInfoModel { SchemaRevision = UpdateMediaInfoService.MINIMUM_MEDIA_INFO_SCHEMA_REVISION }) .BuildList(); Mocker.GetMock() diff --git a/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoFormatter.cs b/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoFormatter.cs index 5282b1040..506fe392f 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoFormatter.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoFormatter.cs @@ -3,8 +3,10 @@ using System.Globalization; using System.IO; using System.Linq; using NLog; +using NLog.Fluent; using NzbDrone.Common.Extensions; using NzbDrone.Common.Instrumentation; +using NzbDrone.Common.Instrumentation.Extensions; namespace NzbDrone.Core.MediaFiles.MediaInfo { @@ -41,6 +43,74 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo } public static string FormatAudioCodec(MediaInfoModel mediaInfo, string sceneName) + { + if (mediaInfo.AudioCodecID == null) + { + return FormatAudioCodecLegacy(mediaInfo, sceneName); + } + + var audioFormat = mediaInfo.AudioFormat; + var audioCodecID = mediaInfo.AudioCodecID ?? string.Empty; + var audioProfile = mediaInfo.AudioProfile ?? string.Empty; + var audioCodecLibrary = mediaInfo.AudioCodecLibrary ?? string.Empty; + + if (audioFormat.IsNullOrWhiteSpace()) + { + return string.Empty; + } + + if (audioFormat.EqualsIgnoreCase("AC-3")) + { + return "AC3"; + } + + if (audioFormat.EqualsIgnoreCase("E-AC-3")) + { + return "EAC3"; + } + + if (audioFormat.EqualsIgnoreCase("AAC")) + { + if (audioCodecID == "A_AAC/MPEG4/LC/SBR") + { + return "HE-AAC"; + } + + return "AAC"; + } + + if (audioFormat.EqualsIgnoreCase("DTS")) + { + return "DTS"; + } + + if (audioFormat.EqualsIgnoreCase("FLAC")) + { + return "FLAC"; + } + + if (audioFormat.EqualsIgnoreCase("MPEG Audio")) + { + if (mediaInfo.AudioCodecID == "55" || mediaInfo.AudioCodecID == "A_MPEG/L3" || mediaInfo.AudioProfile == "Layer 3") + { + return "MP3"; + } + + if (mediaInfo.AudioProfile == "Layer 2") + { + return "MP2"; + } + } + + Logger.Debug() + .Message("Unknown audio format: '{0}' in '{1}'.", string.Join(", ", audioFormat, audioCodecID, audioProfile, audioCodecLibrary), sceneName) + .WriteSentryWarn("UnknownAudioFormat", mediaInfo.ContainerFormat, audioFormat, audioCodecID) + .Write(); + + return audioFormat; + } + + public static string FormatAudioCodecLegacy(MediaInfoModel mediaInfo, string sceneName) { var audioFormat = mediaInfo.AudioFormat; @@ -49,51 +119,120 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo return audioFormat; } - if (audioFormat == "AC-3") + if (audioFormat.EqualsIgnoreCase("AC-3")) { return "AC3"; } - if (audioFormat == "E-AC-3") + if (audioFormat.EqualsIgnoreCase("E-AC-3")) { return "EAC3"; } - if (audioFormat == "AAC") + if (audioFormat.EqualsIgnoreCase("AAC")) { return "AAC"; } - if (audioFormat == "MPEG Audio") + if (audioFormat.EqualsIgnoreCase("MPEG Audio") && mediaInfo.AudioProfile == "Layer 3") { - return mediaInfo.AudioProfile == "Layer 3" ? "MP3" : audioFormat; + return "MP3"; } - if (audioFormat == "DTS") + if (audioFormat.EqualsIgnoreCase("DTS")) { return "DTS"; } - if (audioFormat.Equals("FLAC", StringComparison.OrdinalIgnoreCase)) + if (audioFormat.EqualsIgnoreCase("TrueHD")) + { + return "TrueHD"; + } + + if (audioFormat.EqualsIgnoreCase("FLAC")) { return "FLAC"; } - if (audioFormat.Equals("Vorbis", StringComparison.OrdinalIgnoreCase)) + if (audioFormat.EqualsIgnoreCase("Vorbis")) { return "Vorbis"; } - if (audioFormat.Equals("Opus", StringComparison.OrdinalIgnoreCase)) + if (audioFormat.EqualsIgnoreCase("Opus")) { return "Opus"; } - Logger.Error(new UnknownCodecException(audioFormat, sceneName), "Unknown audio format: {0} in '{1}'. Please notify Sonarr developers.", audioFormat, sceneName); return audioFormat; } public static string FormatVideoCodec(MediaInfoModel mediaInfo, string sceneName) + { + if (mediaInfo.VideoFormat == null) + { + return FormatVideoCodecLegacy(mediaInfo, sceneName); + } + + var videoFormat = mediaInfo.VideoFormat; + var videoCodecID = mediaInfo.VideoCodecID ?? string.Empty; + var videoProfile = mediaInfo.VideoProfile ?? string.Empty; + var videoCodecLibrary = mediaInfo.VideoCodecLibrary ?? string.Empty; + + if (videoFormat.IsNullOrWhiteSpace()) + { + return videoFormat; + } + + if (videoFormat == "AVC") + { + if (videoCodecLibrary.StartsWithIgnoreCase("x264")) + { + return "x264"; + } + + return GetSceneNameMatch(sceneName, "AVC", "h264"); + } + + if (videoFormat == "HEVC") + { + if (videoCodecLibrary.StartsWithIgnoreCase("x265")) + { + return "x265"; + } + + return GetSceneNameMatch(sceneName, "HEVC", "h265"); + } + + if (videoFormat == "MPEG-2 Video") + { + return "MPEG2"; + } + + if (videoFormat == "MPEG-4 Visual") + { + if (videoCodecID.ContainsIgnoreCase("XVID")) + { + return "XviD"; + } + + if (videoCodecID.ContainsIgnoreCase("DIV3") || + videoCodecID.ContainsIgnoreCase("DIVX") || + videoCodecID.ContainsIgnoreCase("DX50")) + { + return "DivX"; + } + } + + Logger.Debug() + .Message("Unknown video format: '{0}' in '{1}'.", string.Join(", ", videoFormat, videoCodecID, videoProfile, videoCodecLibrary), sceneName) + .WriteSentryWarn("UnknownVideoFormat", mediaInfo.ContainerFormat, videoFormat, videoCodecID) + .Write(); + + return videoFormat; + } + + public static string FormatVideoCodecLegacy(MediaInfoModel mediaInfo, string sceneName) { var videoCodec = mediaInfo.VideoCodec; @@ -104,16 +243,12 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo if (videoCodec == "AVC") { - return sceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(sceneName).Contains("h264") - ? "h264" - : "x264"; + return GetSceneNameMatch(sceneName, "AVC", "h264", "x264"); } if (videoCodec == "V_MPEGH/ISO/HEVC" || videoCodec == "HEVC") { - return sceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(sceneName).ContainsIgnoreCase("h265") - ? "h265" - : "x265"; + return GetSceneNameMatch(sceneName, "HEVC", "h265", "x265"); } if (videoCodec == "MPEG-2 Video") @@ -123,28 +258,41 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo if (videoCodec == "MPEG-4 Visual") { - return sceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(sceneName).ContainsIgnoreCase("DivX") - ? "DivX" - : "XviD"; + return GetSceneNameMatch(sceneName, "DivX", "XviD"); } - if (videoCodec.StartsWith("XviD", StringComparison.OrdinalIgnoreCase)) + if (videoCodec.StartsWithIgnoreCase("XviD")) { return "XviD"; } - if (videoCodec.StartsWith("DivX", StringComparison.OrdinalIgnoreCase)) + if (videoCodec.StartsWithIgnoreCase("DivX")) { return "DivX"; } - if (videoCodec.Equals("VC-1", StringComparison.OrdinalIgnoreCase)) + if (videoCodec.EqualsIgnoreCase("VC-1")) { return "VC1"; } - Logger.Error(new UnknownCodecException(videoCodec, sceneName), "Unknown video codec: {0} in '{1}'. Please notify Sonarr developers.", videoCodec, sceneName); return videoCodec; } + + private static string GetSceneNameMatch(string sceneName, params string[] tokens) + { + sceneName = sceneName.IsNotNullOrWhiteSpace() ? Path.GetFileNameWithoutExtension(sceneName) : string.Empty; + + foreach (var token in tokens) + { + if (sceneName.ContainsIgnoreCase(token)) + { + return token; + } + } + + // Last token is the default. + return tokens.Last(); + } } } diff --git a/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoModel.cs b/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoModel.cs index 26a2e7235..03f4ef3c5 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoModel.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoModel.cs @@ -9,12 +9,20 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo { public class MediaInfoModel : IEmbeddedDocument { + public string ContainerFormat { get; set; } + // Deprecated according to MediaInfo public string VideoCodec { get; set; } + public string VideoFormat { get; set; } + public string VideoCodecID { get; set; } + public string VideoProfile { get; set; } + public string VideoCodecLibrary { get; set; } public int VideoBitrate { get; set; } public int VideoBitDepth { 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 int AudioBitrate { get; set; } public TimeSpan RunTime { get; set; } public int AudioStreamCount { get; set; } diff --git a/src/NzbDrone.Core/MediaFiles/MediaInfo/UnknownCodecException.cs b/src/NzbDrone.Core/MediaFiles/MediaInfo/UnknownCodecException.cs deleted file mode 100644 index 402235a39..000000000 --- a/src/NzbDrone.Core/MediaFiles/MediaInfo/UnknownCodecException.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace NzbDrone.Core.MediaFiles.MediaInfo -{ - public class UnknownCodecException : Exception - { - public string Codec { get; set; } - public string SceneName { get; set; } - - public UnknownCodecException(string codec, string sceneName) - : base($"Unknown codec {codec}") - { - Codec = codec; - SceneName = sceneName; - } - } -} diff --git a/src/NzbDrone.Core/MediaFiles/MediaInfo/UpdateMediaInfoService.cs b/src/NzbDrone.Core/MediaFiles/MediaInfo/UpdateMediaInfoService.cs index fb232f2f9..4630ea592 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaInfo/UpdateMediaInfoService.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaInfo/UpdateMediaInfoService.cs @@ -18,7 +18,8 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo private readonly IConfigService _configService; private readonly Logger _logger; - private const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 3; + public const int MINIMUM_MEDIA_INFO_SCHEMA_REVISION = 3; + public const int CURRENT_MEDIA_INFO_SCHEMA_REVISION = 4; public UpdateMediaInfoService(IDiskProvider diskProvider, IMediaFileService mediaFileService, @@ -65,7 +66,7 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo } var allMediaFiles = _mediaFileService.GetFilesBySeries(message.Series.Id); - var filteredMediaFiles = allMediaFiles.Where(c => c.MediaInfo == null || c.MediaInfo.SchemaRevision < CURRENT_MEDIA_INFO_SCHEMA_REVISION).ToList(); + var filteredMediaFiles = allMediaFiles.Where(c => c.MediaInfo == null || c.MediaInfo.SchemaRevision < MINIMUM_MEDIA_INFO_SCHEMA_REVISION).ToList(); UpdateMediaInfo(message.Series, filteredMediaFiles); } diff --git a/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs b/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs index d4c2df482..b86e0e973 100644 --- a/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs +++ b/src/NzbDrone.Core/MediaFiles/MediaInfo/VideoFileInfoReader.cs @@ -104,54 +104,44 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo int.TryParse(mediaInfo.Get(StreamKind.Audio, 0, "PlayTime"), out audioRuntime); int.TryParse(mediaInfo.Get(StreamKind.General, 0, "PlayTime"), out generalRuntime); - string aBitRate = mediaInfo.Get(StreamKind.Audio, 0, "BitRate"); - int aBindex = aBitRate.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase); - if (aBindex > 0) - { - aBitRate = aBitRate.Remove(aBindex); - } + string aBitRate = mediaInfo.Get(StreamKind.Audio, 0, "BitRate").Split(new string[] { " /" }, StringSplitOptions.None)[0].Trim(); int.TryParse(aBitRate, out audioBitRate); int.TryParse(mediaInfo.Get(StreamKind.Audio, 0, "StreamCount"), out streamCount); - string audioChannelsStr = mediaInfo.Get(StreamKind.Audio, 0, "Channel(s)"); - int aCindex = audioChannelsStr.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase); - - if (aCindex > 0) - { - audioChannelsStr = audioChannelsStr.Remove(aCindex); - } + string audioChannelsStr = mediaInfo.Get(StreamKind.Audio, 0, "Channel(s)").Split(new string[] { " /" }, StringSplitOptions.None)[0].Trim(); var audioChannelPositions = mediaInfo.Get(StreamKind.Audio, 0, "ChannelPositions/String2"); var audioChannelPositionsText = mediaInfo.Get(StreamKind.Audio, 0, "ChannelPositions"); string audioLanguages = mediaInfo.Get(StreamKind.General, 0, "Audio_Language_List"); - string audioProfile = mediaInfo.Get(StreamKind.Audio, 0, "Format_Profile"); - int aPindex = audioProfile.IndexOf(" /", StringComparison.InvariantCultureIgnoreCase); - - if (aPindex > 0) - { - audioProfile = audioProfile.Remove(aPindex); - } + string videoProfile = mediaInfo.Get(StreamKind.Video, 0, "Format_Profile").Split(new string[] { " /" }, StringSplitOptions.None)[0].Trim(); + string audioProfile = mediaInfo.Get(StreamKind.Audio, 0, "Format_Profile").Split(new string[] { " /" }, StringSplitOptions.None)[0].Trim(); int.TryParse(audioChannelsStr, out audioChannels); var mediaInfoModel = new MediaInfoModel { - VideoCodec = mediaInfo.Get(StreamKind.Video, 0, "Codec/String"), + ContainerFormat = mediaInfo.Get(StreamKind.General, 0, "Format"), + VideoFormat = mediaInfo.Get(StreamKind.Video, 0, "Format"), + VideoCodecID = mediaInfo.Get(StreamKind.Video, 0, "CodecID"), + VideoProfile = videoProfile, + VideoCodecLibrary = mediaInfo.Get(StreamKind.Video, 0, "Encoded_Library"), VideoBitrate = videoBitRate, VideoBitDepth = videoBitDepth, 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"), AudioBitrate = audioBitRate, RunTime = GetBestRuntime(audioRuntime, videoRuntime, generalRuntime), AudioStreamCount = streamCount, AudioChannels = audioChannels, AudioChannelPositions = audioChannelPositions, AudioChannelPositionsText = audioChannelPositionsText, - AudioProfile = audioProfile.Trim(), VideoFps = videoFrameRate, AudioLanguages = audioLanguages, Subtitles = subtitles, diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 7eec311cd..afdbf7791 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -807,7 +807,6 @@ -