diff --git a/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/FormattedAudioChannelsFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatAudioChannelsFixture.cs
similarity index 78%
rename from src/NzbDrone.Core.Test/MediaFiles/MediaInfo/FormattedAudioChannelsFixture.cs
rename to src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatAudioChannelsFixture.cs
index c344c0906..4c565585f 100644
--- a/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/FormattedAudioChannelsFixture.cs
+++ b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatAudioChannelsFixture.cs
@@ -1,11 +1,12 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MediaFiles.MediaInfo;
+using NzbDrone.Test.Common;
-namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
+namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
{
[TestFixture]
- public class FormattedAudioChannelsFixture
+ public class FormatAudioChannelsFixture : TestBase
{
[Test]
public void should_subtract_one_from_AudioChannels_as_total_channels_if_LFE_in_AudioChannelPositionsText()
@@ -17,7 +18,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
AudioChannelPositionsText = "Front: L C R, Side: L R, LFE"
};
- mediaInfoModel.FormattedAudioChannels.Should().Be(5.1m);
+ MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(5.1m);
}
[Test]
@@ -30,7 +31,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
AudioChannelPositionsText = "Front: L R"
};
- mediaInfoModel.FormattedAudioChannels.Should().Be(2);
+ MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(2);
}
[Test]
@@ -44,7 +45,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
SchemaRevision = 2
};
- mediaInfoModel.FormattedAudioChannels.Should().Be(0);
+ MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(0);
}
[Test]
@@ -58,7 +59,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
SchemaRevision = 3
};
- mediaInfoModel.FormattedAudioChannels.Should().Be(2);
+ MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(2);
}
[Test]
@@ -72,7 +73,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
SchemaRevision = 3
};
- mediaInfoModel.FormattedAudioChannels.Should().Be(2);
+ MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(2);
}
[Test]
@@ -86,7 +87,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
SchemaRevision = 3
};
- mediaInfoModel.FormattedAudioChannels.Should().Be(5.1m);
+ MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(5.1m);
}
[Test]
@@ -100,7 +101,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
SchemaRevision = 3
};
- mediaInfoModel.FormattedAudioChannels.Should().Be(7.1m);
+ MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(7.1m);
}
[Test]
@@ -114,7 +115,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
SchemaRevision = 3
};
- mediaInfoModel.FormattedAudioChannels.Should().Be(7.1m);
+ MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(7.1m);
}
}
}
diff --git a/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatAudioCodecFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatAudioCodecFixture.cs
new file mode 100644
index 000000000..fd4949c60
--- /dev/null
+++ b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatAudioCodecFixture.cs
@@ -0,0 +1,49 @@
+using FluentAssertions;
+using NUnit.Framework;
+using NzbDrone.Core.MediaFiles.MediaInfo;
+using NzbDrone.Test.Common;
+
+namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
+{
+ [TestFixture]
+ public class FormatAudioCodecFixture : TestBase
+ {
+ [TestCase("AC-3", "AC3")]
+ [TestCase("E-AC-3", "EAC3")]
+ [TestCase("MPEG Audio", "MPEG Audio")]
+ [TestCase("DTS", "DTS")]
+ public void should_format_audio_format(string audioFormat, string expectedFormat)
+ {
+ var mediaInfoModel = new MediaInfoModel
+ {
+ AudioFormat = audioFormat
+ };
+
+ MediaInfoFormatter.FormatAudioCodec(mediaInfoModel).Should().Be(expectedFormat);
+ }
+
+ [Test]
+ public void should_return_MP3_for_MPEG_Audio_with_Layer_3_for_the_profile()
+ {
+ var mediaInfoModel = new MediaInfoModel
+ {
+ AudioFormat = "MPEG Audio",
+ AudioProfile = "Layer 3"
+ };
+
+ MediaInfoFormatter.FormatAudioCodec(mediaInfoModel).Should().Be("MP3");
+ }
+
+ [Test]
+ public void should_return_AudioFormat_by_default()
+ {
+ var mediaInfoModel = new MediaInfoModel
+ {
+ AudioFormat = "Other Audio Format"
+ };
+
+ MediaInfoFormatter.FormatAudioCodec(mediaInfoModel).Should().Be(mediaInfoModel.AudioFormat);
+ ExceptionVerification.ExpectedErrors(1);
+ }
+ }
+}
diff --git a/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatVideoCodecFixture.cs b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatVideoCodecFixture.cs
new file mode 100644
index 000000000..d4345b026
--- /dev/null
+++ b/src/NzbDrone.Core.Test/MediaFiles/MediaInfo/MediaInfoFormatterTests/FormatVideoCodecFixture.cs
@@ -0,0 +1,40 @@
+using FluentAssertions;
+using NUnit.Framework;
+using NzbDrone.Core.MediaFiles.MediaInfo;
+using NzbDrone.Test.Common;
+
+namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
+{
+ [TestFixture]
+ public class FormatVideoCodecFixture : TestBase
+ {
+ [TestCase("AVC", null, "x264")]
+ [TestCase("AVC", "source.title.x264.720p-Sonarr", "x264")]
+ [TestCase("AVC", "source.title.h264.720p-Sonarr", "h264")]
+ [TestCase("V_MPEGH/ISO/HEVC", null, "x265")]
+ [TestCase("V_MPEGH/ISO/HEVC", "source.title.x265.720p-Sonarr", "x265")]
+ [TestCase("V_MPEGH/ISO/HEVC", "source.title.h265.720p-Sonarr", "h265")]
+ [TestCase("MPEG-2 Video", null, "MPEG2")]
+ public void should_format_video_codec_with_source_title(string videoCodec, string sceneName, string expectedFormat)
+ {
+ var mediaInfoModel = new MediaInfoModel
+ {
+ VideoCodec = videoCodec
+ };
+
+ MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, sceneName).Should().Be(expectedFormat);
+ }
+
+ [Test]
+ public void should_return_VideoCodec_by_default()
+ {
+ var mediaInfoModel = new MediaInfoModel
+ {
+ VideoCodec = "VideoCodec"
+ };
+
+ MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, null).Should().Be(mediaInfoModel.VideoCodec);
+ ExceptionVerification.ExpectedErrors(1);
+ }
+ }
+}
diff --git a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
index 9b325cfb8..c5254bc2f 100644
--- a/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
+++ b/src/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj
@@ -291,7 +291,9 @@
-
+
+
+
diff --git a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs
index 75a80225f..85485bc87 100644
--- a/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs
+++ b/src/NzbDrone.Core/Extras/Metadata/Consumers/Xbmc/XbmcMetadata.cs
@@ -11,6 +11,7 @@ using NzbDrone.Common.Extensions;
using NzbDrone.Core.Extras.Metadata.Files;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MediaFiles;
+using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
@@ -247,7 +248,7 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
var video = new XElement("video");
video.Add(new XElement("aspect", (float)episodeFile.MediaInfo.Width / (float)episodeFile.MediaInfo.Height));
video.Add(new XElement("bitrate", episodeFile.MediaInfo.VideoBitrate));
- video.Add(new XElement("codec", episodeFile.MediaInfo.VideoCodec));
+ video.Add(new XElement("codec", MediaInfoFormatter.FormatVideoCodec(episodeFile.MediaInfo, episodeFile.SceneName)));
video.Add(new XElement("framerate", episodeFile.MediaInfo.VideoFps));
video.Add(new XElement("height", episodeFile.MediaInfo.Height));
video.Add(new XElement("scantype", episodeFile.MediaInfo.ScanType));
@@ -264,11 +265,11 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
var audio = new XElement("audio");
audio.Add(new XElement("bitrate", episodeFile.MediaInfo.AudioBitrate));
audio.Add(new XElement("channels", episodeFile.MediaInfo.AudioChannels));
- audio.Add(new XElement("codec", GetAudioCodec(episodeFile.MediaInfo.AudioFormat)));
+ audio.Add(new XElement("codec", MediaInfoFormatter.FormatAudioCodec(episodeFile.MediaInfo)));
audio.Add(new XElement("language", episodeFile.MediaInfo.AudioLanguages));
streamDetails.Add(audio);
- if (episodeFile.MediaInfo.Subtitles != null && episodeFile.MediaInfo.Subtitles.Length > 0)
+ if (episodeFile.MediaInfo.Subtitles.IsNotNullOrWhiteSpace())
{
var subtitle = new XElement("subtitle");
subtitle.Add(new XElement("language", episodeFile.MediaInfo.Subtitles));
@@ -379,15 +380,5 @@ namespace NzbDrone.Core.Extras.Metadata.Consumers.Xbmc
{
return Path.ChangeExtension(episodeFilePath, "").Trim('.') + "-thumb.jpg";
}
-
- private string GetAudioCodec(string audioCodec)
- {
- if (audioCodec == "AC-3")
- {
- return "AC3";
- }
-
- return audioCodec;
- }
}
}
diff --git a/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoFormatter.cs b/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoFormatter.cs
new file mode 100644
index 000000000..f7ebcb0ae
--- /dev/null
+++ b/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoFormatter.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using NLog;
+using NzbDrone.Common.Extensions;
+using NzbDrone.Common.Instrumentation;
+
+namespace NzbDrone.Core.MediaFiles.MediaInfo
+{
+ public static class MediaInfoFormatter
+ {
+ private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(MediaInfoFormatter));
+
+ public static decimal FormatAudioChannels(MediaInfoModel mediaInfo)
+ {
+ var audioChannelPositions = mediaInfo.AudioChannelPositions;
+ var audioChannelPositionsText = mediaInfo.AudioChannelPositionsText;
+ var audioChannels = mediaInfo.AudioChannels;
+
+ if (audioChannelPositions.IsNullOrWhiteSpace())
+ {
+ if (audioChannelPositionsText.IsNullOrWhiteSpace())
+ {
+ if (mediaInfo.SchemaRevision >= 3)
+ {
+ return audioChannels;
+ }
+
+ return 0;
+ }
+
+ return mediaInfo.AudioChannelPositionsText.ContainsIgnoreCase("LFE") ? audioChannels - 1 + 0.1m : audioChannels;
+ }
+
+ return audioChannelPositions.Replace("Object Based / ", "")
+ .Split(new string[] { " / " }, StringSplitOptions.None)
+ .First()
+ .Split('/')
+ .Sum(s => decimal.Parse(s, CultureInfo.InvariantCulture));
+ }
+
+ public static string FormatAudioCodec(MediaInfoModel mediaInfo)
+ {
+ var audioFormat = mediaInfo.AudioFormat;
+
+ if (audioFormat == "AC-3")
+ {
+ return "AC3";
+ }
+
+ if (audioFormat == "E-AC-3")
+ {
+ return "EAC3";
+ }
+
+ if (audioFormat == "MPEG Audio")
+ {
+ return mediaInfo.AudioProfile == "Layer 3" ? "MP3" : audioFormat;
+ }
+
+ if (audioFormat == "DTS")
+ {
+ return "DTS";
+ }
+
+ Logger.Error("Unknown audio format: {0}", audioFormat);
+ return audioFormat;
+ }
+
+ public static string FormatVideoCodec(MediaInfoModel mediaInfo, string sceneName)
+ {
+ var videoCodec = mediaInfo.VideoCodec;
+
+ if (videoCodec == "AVC")
+ {
+ return sceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(sceneName).Contains("h264")
+ ? "h264"
+ : "x264";
+ }
+
+ if (videoCodec == "V_MPEGH/ISO/HEVC")
+ {
+ return sceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(sceneName).Contains("h265")
+ ? "h265"
+ : "x265";
+ }
+
+ if (videoCodec == "MPEG-2 Video")
+ {
+ return "MPEG2";
+ }
+
+ Logger.Error("Unknown video codec: {0}", videoCodec);
+ return videoCodec;
+ }
+ }
+}
diff --git a/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoModel.cs b/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoModel.cs
index af02288e8..26a2e7235 100644
--- a/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoModel.cs
+++ b/src/NzbDrone.Core/MediaFiles/MediaInfo/MediaInfoModel.cs
@@ -27,33 +27,5 @@ namespace NzbDrone.Core.MediaFiles.MediaInfo
public string Subtitles { get; set; }
public string ScanType { get; set; }
public int SchemaRevision { get; set; }
-
- [JsonIgnore]
- public decimal FormattedAudioChannels
- {
- get
- {
- if (AudioChannelPositions.IsNullOrWhiteSpace())
- {
- if (AudioChannelPositionsText.IsNullOrWhiteSpace())
- {
- if (SchemaRevision >= 3)
- {
- return AudioChannels;
- }
-
- return 0;
- }
-
- return AudioChannelPositionsText.ContainsIgnoreCase("LFE") ? AudioChannels - 1 + 0.1m : AudioChannels;
- }
-
- return AudioChannelPositions.Replace("Object Based / ", "")
- .Split(new string[] { " / " }, StringSplitOptions.None)
- .First()
- .Split('/')
- .Sum(s => decimal.Parse(s, CultureInfo.InvariantCulture));
- }
- }
}
}
diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj
index 62f7edd61..22106bc73 100644
--- a/src/NzbDrone.Core/NzbDrone.Core.csproj
+++ b/src/NzbDrone.Core/NzbDrone.Core.csproj
@@ -783,6 +783,7 @@
Code
+
diff --git a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
index 31cbd53ef..890c067b1 100644
--- a/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
+++ b/src/NzbDrone.Core/Organizer/FileNameBuilder.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
@@ -9,6 +9,7 @@ using NzbDrone.Common.Cache;
using NzbDrone.Common.EnsureThat;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.MediaFiles;
+using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;
@@ -445,75 +446,14 @@ namespace NzbDrone.Core.Organizer
{
if (episodeFile.MediaInfo == null) return;
- string videoCodec;
- switch (episodeFile.MediaInfo.VideoCodec)
- {
- case "AVC":
- if (episodeFile.SceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(episodeFile.SceneName).Contains("h264"))
- {
- videoCodec = "h264";
- }
- else
- {
- videoCodec = "x264";
- }
- break;
-
- case "V_MPEGH/ISO/HEVC":
- if (episodeFile.SceneName.IsNotNullOrWhiteSpace() && Path.GetFileNameWithoutExtension(episodeFile.SceneName).Contains("h265"))
- {
- videoCodec = "h265";
- }
- else
- {
- videoCodec = "x265";
- }
- break;
-
- case "MPEG-2 Video":
- videoCodec = "MPEG2";
- break;
-
- default:
- videoCodec = episodeFile.MediaInfo.VideoCodec;
- break;
- }
-
- string audioCodec;
- switch (episodeFile.MediaInfo.AudioFormat)
- {
- case "AC-3":
- audioCodec = "AC3";
- break;
-
- case "E-AC-3":
- audioCodec = "EAC3";
- break;
-
- case "MPEG Audio":
- if (episodeFile.MediaInfo.AudioProfile == "Layer 3")
- {
- audioCodec = "MP3";
- }
- else
- {
- audioCodec = episodeFile.MediaInfo.AudioFormat;
- }
- break;
-
- case "DTS":
- audioCodec = episodeFile.MediaInfo.AudioFormat;
- break;
-
- default:
- audioCodec = episodeFile.MediaInfo.AudioFormat;
- break;
- }
+ var videoCodec = MediaInfoFormatter.FormatVideoCodec(episodeFile.MediaInfo, episodeFile.SceneName);
+ var audioCodec = MediaInfoFormatter.FormatAudioCodec(episodeFile.MediaInfo);
+ var audioChannels = MediaInfoFormatter.FormatAudioChannels(episodeFile.MediaInfo);
var mediaInfoAudioLanguages = GetLanguagesToken(episodeFile.MediaInfo.AudioLanguages);
if (!mediaInfoAudioLanguages.IsNullOrWhiteSpace())
{
- mediaInfoAudioLanguages = string.Format("[{0}]", mediaInfoAudioLanguages);
+ mediaInfoAudioLanguages = $"[{mediaInfoAudioLanguages}]";
}
if (mediaInfoAudioLanguages == "[EN]")
@@ -524,12 +464,12 @@ namespace NzbDrone.Core.Organizer
var mediaInfoSubtitleLanguages = GetLanguagesToken(episodeFile.MediaInfo.Subtitles);
if (!mediaInfoSubtitleLanguages.IsNullOrWhiteSpace())
{
- mediaInfoSubtitleLanguages = string.Format("[{0}]", mediaInfoSubtitleLanguages);
+ mediaInfoSubtitleLanguages = $"[{mediaInfoSubtitleLanguages}]";
}
var videoBitDepth = episodeFile.MediaInfo.VideoBitDepth > 0 ? episodeFile.MediaInfo.VideoBitDepth.ToString() : string.Empty;
- var audioChannels = episodeFile.MediaInfo.FormattedAudioChannels > 0 ?
- episodeFile.MediaInfo.FormattedAudioChannels.ToString("F1", CultureInfo.InvariantCulture) :
+ var audioChannelsFormatted = audioChannels > 0 ?
+ audioChannels.ToString("F1", CultureInfo.InvariantCulture) :
string.Empty;
tokenHandlers["{MediaInfo Video}"] = m => videoCodec;
@@ -538,11 +478,11 @@ namespace NzbDrone.Core.Organizer
tokenHandlers["{MediaInfo Audio}"] = m => audioCodec;
tokenHandlers["{MediaInfo AudioCodec}"] = m => audioCodec;
- tokenHandlers["{MediaInfo AudioChannels}"] = m => audioChannels;
+ tokenHandlers["{MediaInfo AudioChannels}"] = m => audioChannelsFormatted;
- tokenHandlers["{MediaInfo Simple}"] = m => string.Format("{0} {1}", videoCodec, audioCodec);
+ tokenHandlers["{MediaInfo Simple}"] = m => $"{videoCodec} {audioCodec}";
- tokenHandlers["{MediaInfo Full}"] = m => string.Format("{0} {1}{2} {3}", videoCodec, audioCodec, mediaInfoAudioLanguages, mediaInfoSubtitleLanguages);
+ tokenHandlers["{MediaInfo Full}"] = m => $"{videoCodec} {audioCodec}{mediaInfoAudioLanguages} {mediaInfoSubtitleLanguages}";
}
private string GetLanguagesToken(string mediaInfoLanguages)