1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2026-04-27 23:06:29 -04:00

New: MediaInfo -> FFProbe

Co-Authored-By: ta264 <ta264@users.noreply.github.com>
This commit is contained in:
Qstick
2022-01-22 12:44:22 -06:00
committed by Mark McDowall
parent a4232549cb
commit fa0fc3158b
31 changed files with 1532 additions and 1795 deletions
@@ -1,321 +0,0 @@
using System.Globalization;
using System.Threading;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
{
[TestFixture]
public class FormatAudioChannelsFixture : TestBase
{
[Test]
public void should_subtract_one_from_AudioChannels_as_total_channels_if_LFE_in_AudioChannelPositionsText()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 6,
AudioChannelPositions = null,
AudioChannelPositionsTextContainer = "Front: L C R, Side: L R, LFE"
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(5.1m);
}
[Test]
public void should_use_AudioChannels_as_total_channels_if_LFE_not_in_AudioChannelPositionsText()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = null,
AudioChannelPositionsTextContainer = "Front: L R"
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(2);
}
[Test]
public void should_return_0_if_schema_revision_is_less_than_3_and_other_properties_are_null()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = null,
AudioChannelPositionsTextContainer = null,
SchemaRevision = 2
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(0);
}
[Test]
public void should_use_AudioChannels_if_schema_revision_is_3_and_other_properties_are_null()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = null,
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(2);
}
[Test]
public void should_use_AudioChannels_if_schema_revision_is_3_and_AudioChannelPositions_is_0()
{
var mediaInfoModel = new MediaInfoModel
{
AudioFormat = "FLAC",
AudioChannelsContainer = 6,
AudioChannelPositions = "0/0/0",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(5.1m);
}
[Test]
public void should_sum_AudioChannelPositions()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = "2/0/0",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(2);
}
[Test]
public void should_sum_AudioChannelPositions_including_decimal()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = "3/2/0.1",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(5.1m);
}
[Test]
public void should_format_8_channel_object_based_as_71_if_dtsx()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 8,
AudioChannelsStream = 0,
AudioFormat = "DTS",
AudioAdditionalFeatures = "XLL X",
AudioChannelPositions = "Object Based",
AudioChannelPositionsTextContainer = "Object Based",
AudioChannelPositionsTextStream = "Object Based",
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(7.1m);
}
[Test]
public void should_format_8_channel_blank_as_71_if_dtsx()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 8,
AudioChannelsStream = 0,
AudioFormat = "DTS",
AudioAdditionalFeatures = "XLL X",
AudioChannelPositions = "",
AudioChannelPositionsTextContainer = "",
AudioChannelPositionsTextStream = "Object Based",
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(7.1m);
}
[Test]
public void should_format_6_channel_zero_as_51_if_flac()
{
var mediaInfoModel = new MediaInfoModel
{
AudioFormat = "FLAC",
AudioChannelsContainer = 6,
AudioChannelPositions = "0/0/0",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(5.1m);
}
[Test]
public void should_ignore_culture_on_channel_summary()
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = "3/2/0.1",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(5.1m);
}
[Test]
public void should_handle_AudioChannelPositions_three_digits()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = "3/2/0.2.1",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(7.1m);
}
[Test]
public void should_cleanup_extraneous_text_from_AudioChannelPositions()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = "Object Based / 3/2/2.1",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(7.1m);
}
[Test]
public void should_skip_empty_groups_in_AudioChannelPositions()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = " / 2/0/0.0",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(2);
}
[Test]
public void should_sum_first_series_of_numbers_from_AudioChannelPositions()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = "3/2/2.1 / 3/2/2.1",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(7.1m);
}
[Test]
public void should_sum_first_series_of_numbers_from_AudioChannelPositions_with_three_digits()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = "3/2/0.2.1 / 3/2/0.1",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(7.1m);
}
[Test]
public void should_sum_dual_mono_representation_AudioChannelPositions()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = "1+1",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(2.0m);
}
[Test]
public void should_use_AudioChannelPositionText_when_AudioChannelChannelPosition_is_invalid()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 6,
AudioChannelPositions = "15 objects",
AudioChannelPositionsTextContainer = "15 objects / Front: L C R, Side: L R, LFE",
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(5.1m);
}
[Test]
public void should_remove_atmos_objects_from_AudioChannelPostions()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 2,
AudioChannelPositions = "15 objects / 3/2.1",
AudioChannelPositionsTextContainer = null,
SchemaRevision = 3
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(5.1m);
}
[Test]
public void should_use_audio_stream_text_when_exists()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 6,
AudioChannelsStream = 8,
AudioChannelPositions = null,
AudioChannelPositionsTextContainer = null,
AudioChannelPositionsTextStream = "Front: L C R, Side: L R, Back: L R, LFE",
SchemaRevision = 6
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(7.1m);
}
[Test]
public void should_use_audio_stream_channels_when_exists()
{
var mediaInfoModel = new MediaInfoModel
{
AudioChannelsContainer = 6,
AudioChannelsStream = 8,
AudioChannelPositions = null,
AudioChannelPositionsTextContainer = null,
AudioChannelPositionsTextStream = null,
SchemaRevision = 6
};
MediaInfoFormatter.FormatAudioChannels(mediaInfoModel).Should().Be(8m);
}
}
}
@@ -10,45 +10,30 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
{
private static string sceneName = "My.Series.S01E01-Sonarr";
[TestCase("AC-3", "AC3")]
[TestCase("E-AC-3", "EAC3")]
[TestCase("MPEG Audio", "MPEG Audio")]
[TestCase("DTS", "DTS")]
public void should_format_audio_format_legacy(string audioFormat, string expectedFormat)
{
var mediaInfoModel = new MediaInfoModel
{
AudioFormat = audioFormat
};
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("MLP FBA, A_TRUEHD, , , ", "TrueHD", "TrueHD")]
[TestCase("MLP FBA, A_TRUEHD, , , 16-ch", "Atmos", "TrueHD Atmos")]
[TestCase("Atmos / TrueHD, A_TRUEHD, , , ", "TrueHD.Atmos.7.1", "TrueHD Atmos")]
[TestCase("Atmos / TrueHD / AC-3, 131, , , ", "", "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", "Carbon.Copy.S02E01.The.Phreak.Lady.1080p.NF.Webrip.x265.10bit.EAC3.5.1.Atmos-RGP", "EAC3 Atmos")]
[TestCase("E-AC-3, A_EAC3, , , ", "DD5.1", "EAC3")]
[TestCase("AC-3, A_AC3, , , ", "DD5.1", "AC3")]
[TestCase("A_QUICKTIME, A_QUICKTIME, , , ", "", "")]
[TestCase("ADPCM, 2, , , ", "Custom?", "PCM")]
[TestCase("ADPCM, ima4, , , ", "Custom", "PCM")]
[TestCase("mp2, , ", "droned.s01e03.swedish.720p.hdtv.x264-prince", "MP2")]
[TestCase("vorbis, , ", "DB Super HDTV", "Vorbis")]
[TestCase("pcm_s16le, , ", "DW DVDRip XviD-idTV, ", "PCM")]
[TestCase("truehd, , ", "", "TrueHD")]
[TestCase("truehd, , ", "TrueHD", "TrueHD")]
[TestCase("truehd, thd+, ", "Atmos", "TrueHD Atmos")]
[TestCase("truehd, thd+, ", "TrueHD.Atmos.7.1", "TrueHD Atmos")]
[TestCase("truehd, thd+, ", "", "TrueHD Atmos")]
[TestCase("wmav1, , ", "Droned.wmv", "WMA")]
[TestCase("wmav2, , ", "B.N.S04E18.720p.WEB-DL", "WMA")]
[TestCase("opus, , ", "Roadkill Ep3x11 - YouTube.webm", "Opus")]
[TestCase("mp3, , ", "climbing.mp4", "MP3")]
[TestCase("dts, , DTS-HD MA", "DTS-HD.MA", "DTS-HD MA")]
[TestCase("dts, , DTS:X", "DTS-X", "DTS-X")]
[TestCase("dts, , DTS-HD MA", "DTS-HD.MA", "DTS-HD MA")]
[TestCase("dts, , DTS-ES", "DTS-ES", "DTS-ES")]
[TestCase("dts, , DTS-ES", "DTS", "DTS-ES")]
[TestCase("dts, , DTS-HD HRA", "DTSHD-HRA", "DTS-HD HRA")]
[TestCase("dts, , DTS", "DTS", "DTS")]
[TestCase("eac3, ec+3, ", "EAC3.Atmos", "EAC3 Atmos")]
[TestCase("eac3, , ", "DDP5.1", "EAC3")]
[TestCase("ac3, , ", "DD5.1", "AC3")]
[TestCase("adpcm_ima_qt, , ", "Custom?", "PCM")]
[TestCase("adpcm_ms, , ", "Custom", "PCM")]
public void should_format_audio_format(string audioFormatPack, string sceneName, string expectedFormat)
{
var split = audioFormatPack.Split(new string[] { ", " }, System.StringSplitOptions.None);
@@ -56,26 +41,12 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
{
AudioFormat = split[0],
AudioCodecID = split[1],
AudioProfile = split[2],
AudioCodecLibrary = split[3],
AudioAdditionalFeatures = split[4]
AudioProfile = split[2]
};
MediaInfoFormatter.FormatAudioCodec(mediaInfoModel, sceneName).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, sceneName).Should().Be("MP3");
}
[Test]
public void should_return_AudioFormat_by_default()
{
@@ -1,4 +1,4 @@
using FluentAssertions;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Test.Common;
@@ -8,94 +8,60 @@ 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_legacy(string videoCodec, string sceneName, string expectedFormat)
{
var mediaInfoModel = new MediaInfoModel
{
VideoCodec = videoCodec
};
MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, sceneName).Should().Be(expectedFormat);
}
[TestCase("MPEG Video, 2, Main@High, ", "Droned.S01E02.1080i.HDTV.DD5.1.MPEG2-NTb", "MPEG2")]
[TestCase("MPEG Video, V_MPEG2, Main@High, ", "", "MPEG2")]
[TestCase("MPEG Video, , , ", "The.Simpsons.S13E04.INTERNAL-ANiVCD.mpg", "MPEG")]
[TestCase("VC-1, WVC1, Advanced@L4, ", "B.N.S04E18.720p.WEB-DL", "VC1")]
[TestCase("VC-1, V_MS/VFW/FOURCC / WVC1, Advanced@L3, ", "", "VC1")]
[TestCase("VC-1, WMV3, MP@LL, ", "It's Always Sunny S07E13 The Gang's RevengeHDTV.XviD-2HD.avi", "VC1")]
[TestCase("V.MPEG4/ISO/AVC, V.MPEG4/ISO/AVC, , ", "pd.2015.S03E08.720p.iP.WEBRip.AAC2.0.H264-BTW", "h264")]
[TestCase("AVC / AVC, V_MPEG4/ISO/AVC, High@L4, ", "Resistance.2019.S01E03.1080p.RTE.WEB-DL.AAC2.0.x264-RTN", "x264")]
[TestCase("WMV1, WMV1, , ", "Droned.wmv", "WMV")]
[TestCase("WMV2, WMV2, , ", "Droned.wmv", "WMV")]
[TestCase("xvid, xvid, , ", "", "XviD")]
[TestCase("div3, div3, , ", "spsm.dvdrip.divx.avi'.", "DivX")]
[TestCase("VP6, 4, , ", "Top Gear - S12E01 - Lorries - SD TV.flv", "VP6")]
[TestCase("VP7, VP70, General, ", "Sweet Seymour.avi", "VP7")]
[TestCase("VP8, V_VP8, , ", "Dick.mkv", "VP8")]
[TestCase("VP9, V_VP9, , ", "Roadkill Ep3x11 - YouTube.webm", "VP9")]
[TestCase("x264, x264, , ", "Ghost Advent - S04E05 - Stanley Hotel SDTV.avi", "x264")]
[TestCase("V_MPEGH/ISO/HEVC, V_MPEGH/ISO/HEVC, , ", "The BBT S11E12 The Matrimonial Metric 1080p 10bit AMZN WEB-DL", "h265")]
[TestCase("MPEG-4 Visual, 20, Simple@L1, Lavc52.29.0", "Will.And.Grace.S08E14.WS.DVDrip.XviD.I.Love.L.Gay-Obfuscated", "XviD")]
[TestCase("MPEG-4 Visual, 20, Advanced Simple@L5, XviD0046", "", "XviD")]
[TestCase("MPEG-4 Visual, 20, , ", "", "")]
[TestCase("MPEG-4 Visual, mp4v-20, Simple@L1, Lavc57.48.101", "", "")]
[TestCase("mp4v, mp4v, , ", "American.Chopper.S06E07.Mountain.Creek.Bike.DSR.XviD-KRS", "XviD")]
[TestCase("V_QUICKTIME, V_QUICKTIME, , ", "Custom", "")]
[TestCase("MPEG-4 Visual, FMP4, , ", "", "")]
[TestCase("MPEG-4 Visual, MP42, , ", "", "")]
[TestCase("mp43, V_MS/VFW/FOURCC / mp43, , ", "Bubble.Guppies.S01E13.480p.WEB-DL.H.264-BTN-Custom", "")]
[TestCase("mpeg2video, ", "Droned.S01E02.1080i.HDTV.DD5.1.MPEG2-NTb", "MPEG2")]
[TestCase("mpeg2video, ", "", "MPEG2")]
[TestCase("mpeg1video, ", "The.Simpsons.S13E04.INTERNAL-ANiVCD.mpg", "MPEG")]
[TestCase("vc1, WVC1", "B.N.S04E18.720p.WEB-DL", "VC1")]
[TestCase("vc1, V_MS/VFW/FOURCC/WVC1", "", "VC1")]
[TestCase("vc1, WMV3", "It's Always Sunny S07E13 The Gang's RevengeHDTV.XviD-2HD.avi", "VC1")]
[TestCase("h264, V.MPEG4/ISO/AVC", "pd.2015.S03E08.720p.iP.WEBRip.AAC2.0.H264-BTW", "h264")]
[TestCase("h264, V_MPEG4/ISO/AVC", "Resistance.2019.S01E03.1080p.RTE.WEB-DL.AAC2.0.x264-RTN", "x264")]
[TestCase("wmv1, WMV1", "Droned.wmv", "WMV")]
[TestCase("wmv2, WMV2", "Droned.wmv", "WMV")]
[TestCase("mpeg4, XVID", "", "XviD")]
[TestCase("mpeg4, DIVX", "", "DivX")]
[TestCase("mpeg4, divx", "", "DivX")]
[TestCase("mpeg4, DIV3", "spsm.dvdrip.divx.avi'.", "DivX")]
[TestCase("msmpeg4, DIV3", "Exit the Dragon, Enter the Tiger (1976) 360p MPEG Audio.avi", "DivX")]
[TestCase("msmpeg4v2, DIV3", "Exit the Dragon, Enter the Tiger (1976) 360p MPEG Audio.avi", "DivX")]
[TestCase("msmpeg4v3, DIV3", "Exit the Dragon, Enter the Tiger (1976) 360p MPEG Audio.avi", "DivX")]
[TestCase("vp6, 4", "Top Gear - S12E01 - Lorries - SD TV.flv", "VP6")]
[TestCase("vp7, VP70", "Sweet Seymour.avi", "VP7")]
[TestCase("vp8, V_VP8", "Dick.mkv", "VP8")]
[TestCase("vp9, V_VP9", "Roadkill Ep3x11 - YouTube.webm", "VP9")]
[TestCase("h264, x264", "Ghost Advent - S04E05 - Stanley Hotel SDTV.avi", "x264")]
[TestCase("hevc, V_MPEGH/ISO/HEVC", "The BBT S11E12 The Matrimonial Metric 1080p 10bit AMZN WEB-DL", "h265")]
[TestCase("mpeg4, mp4v-20", "", "")]
[TestCase("mpeg4, XVID", "American.Chopper.S06E07.Mountain.Creek.Bike.DSR.XviD-KRS", "XviD")]
[TestCase("rpza, V_QUICKTIME", "Custom", "")]
[TestCase("mpeg4, FMP4", "", "")]
[TestCase("mpeg4, MP42", "", "")]
[TestCase("mpeg4, mp43", "Bubble.Guppies.S01E13.480p.WEB-DL.H.264-BTN-Custom", "")]
public void should_format_video_format(string videoFormatPack, string sceneName, string expectedFormat)
{
var split = videoFormatPack.Split(new string[] { ", " }, System.StringSplitOptions.None);
var mediaInfoModel = new MediaInfoModel
{
VideoFormat = split[0],
VideoCodecID = split[1],
VideoProfile = split[2],
VideoCodecLibrary = split[3]
VideoCodecID = split[1]
};
MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, sceneName).Should().Be(expectedFormat);
}
[TestCase("AVC, AVC, , x264", "Some.Video.S01E01.h264", "x264")] // Force mediainfo tag
[TestCase("HEVC, HEVC, , x265", "Some.Video.S01E01.h265", "x265")] // Force mediainfo tag
[TestCase("AVC, AVC, , ", "Some.Video.S01E01.x264", "x264")] // Not seen in practice, but honor tag if otherwise unknown
[TestCase("HEVC, HEVC, , ", "Some.Video.S01E01.x265", "x265")] // Not seen in practice, but honor tag if otherwise unknown
[TestCase("AVC, AVC, , ", "Some.Video.S01E01", "h264")] // Default value
[TestCase("HEVC, HEVC, , ", "Some.Video.S01E01", "h265")] // Default value
[TestCase("h264, x264", "Some.Video.S01E01.h264", "x264")] // Force mediainfo tag
[TestCase("hevc, x265", "Some.Video.S01E01.h265", "x265")] // Force mediainfo tag
[TestCase("h264, ", "Some.Video.S01E01.x264", "x264")] // Not seen in practice, but honor tag if otherwise unknown
[TestCase("hevc, ", "Some.Video.S01E01.x265", "x265")] // Not seen in practice, but honor tag if otherwise unknown
[TestCase("h264, ", "Some.Video.S01E01", "h264")] // Default value
[TestCase("hevc, ", "Some.Video.S01E01", "h265")] // Default value
public void should_format_video_format_fallbacks(string videoFormatPack, string sceneName, string expectedFormat)
{
var split = videoFormatPack.Split(new string[] { ", " }, System.StringSplitOptions.None);
var mediaInfoModel = new MediaInfoModel
{
VideoFormat = split[0],
VideoCodecID = split[1],
VideoProfile = split[2],
VideoCodecLibrary = split[3]
};
MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, sceneName).Should().Be(expectedFormat);
}
[TestCase("MPEG-4 Visual, 20, , Intel(R) MPEG-4 encoder based on Intel(R) IPP 6.1 build 137.20[6.1.137.763]", "", "")]
public void should_warn_on_unknown_video_format(string videoFormatPack, string sceneName, string expectedFormat)
{
var split = videoFormatPack.Split(new string[] { ", " }, System.StringSplitOptions.None);
var mediaInfoModel = new MediaInfoModel
{
VideoFormat = split[0],
VideoCodecID = split[1],
VideoProfile = split[2],
VideoCodecLibrary = split[3]
VideoCodecID = split[1]
};
MediaInfoFormatter.FormatVideoCodec(mediaInfoModel, sceneName).Should().Be(expectedFormat);
@@ -1,4 +1,4 @@
using FluentAssertions;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Test.Common;
@@ -8,63 +8,21 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
[TestFixture]
public class FormatVideoDynamicRangeFixture : TestBase
{
[TestCase(8, "", "", "", "", "")]
[TestCase(8, "BT.601 NTSC", "BT.709", "", "", "")]
[TestCase(10, "BT.2020", "PQ", "", "", "HDR")]
[TestCase(8, "BT.2020", "PQ", "", "", "")]
[TestCase(10, "BT.601 NTSC", "PQ", "", "", "")]
[TestCase(10, "BT.2020", "BT.709", "", "", "")]
[TestCase(10, "BT.2020", "HLG", "", "", "HDR")]
[TestCase(10, "", "", "Dolby Vision", "", "HDR")]
[TestCase(10, "", "", "SMPTE ST 2086", "HDR10", "HDR")]
[TestCase(8, "", "", "Dolby Vision", "", "")]
[TestCase(8, "", "", "SMPTE ST 2086", "HDR10", "")]
[TestCase(10, "BT.2020", "PQ", "Dolby Vision / SMPTE ST 2086", "Blu-ray / HDR10", "HDR")]
public void should_format_video_dynamic_range(int bitDepth, string colourPrimaries, string transferCharacteristics, string hdrFormat, string hdrFormatCompatibility, string expectedVideoDynamicRange)
[TestCase(HdrFormat.None, "")]
[TestCase(HdrFormat.Hlg10, "HDR")]
[TestCase(HdrFormat.Pq10, "HDR")]
[TestCase(HdrFormat.Hdr10, "HDR")]
[TestCase(HdrFormat.Hdr10Plus, "HDR")]
[TestCase(HdrFormat.DolbyVision, "HDR")]
public void should_format_video_dynamic_range(HdrFormat format, string expectedVideoDynamicRange)
{
var mediaInfo = new MediaInfoModel
{
VideoBitDepth = bitDepth,
VideoColourPrimaries = colourPrimaries,
VideoTransferCharacteristics = transferCharacteristics,
VideoHdrFormat = hdrFormat,
VideoHdrFormatCompatibility = hdrFormatCompatibility,
SchemaRevision = 7
VideoHdrFormat = format,
SchemaRevision = 8
};
MediaInfoFormatter.FormatVideoDynamicRange(mediaInfo).Should().Be(expectedVideoDynamicRange);
}
[TestCase(8, "", "", "", "")]
[TestCase(8, "BT.601 NTSC", "BT.709", "", "")]
[TestCase(8, "BT.2020", "PQ", "", "")]
[TestCase(8, "", "", "Dolby Vision", "")]
[TestCase(8, "", "", "SMPTE ST 2086", "")]
[TestCase(10, "BT.601 NTSC", "PQ", "", "")]
[TestCase(10, "BT.2020", "BT.709", "", "")]
[TestCase(10, "BT.2020", "PQ", "", "PQ")]
[TestCase(10, "BT.2020", "HLG", "", "HLG")]
[TestCase(10, "", "", "SMPTE ST 2086", "HDR10")]
[TestCase(10, "", "", "HDR10", "HDR10")]
[TestCase(10, "", "", "SMPTE ST 2094 App 4", "HDR10Plus")]
[TestCase(10, "", "", "Dolby Vision", "DV")]
[TestCase(10, "BT.2020", "PQ", "Dolby Vision / SMPTE ST 2086", "DV HDR10")]
[TestCase(10, "", "", "SL-HDR1", "HDR")]
[TestCase(10, "", "", "SL-HDR2", "HDR")]
[TestCase(10, "", "", "SL-HDR3", "HDR")]
[TestCase(10, "", "", "Technicolor Advanced HDR", "HDR")]
public void should_format_video_dynamic_range_type(int bitDepth, string colourPrimaries, string transferCharacteristics, string hdrFormat, string expectedVideoDynamicRange)
{
var mediaInfo = new MediaInfoModel
{
VideoBitDepth = bitDepth,
VideoColourPrimaries = colourPrimaries,
VideoTransferCharacteristics = transferCharacteristics,
VideoHdrFormat = hdrFormat,
SchemaRevision = 7
};
MediaInfoFormatter.FormatVideoDynamicRangeType(mediaInfo).Should().Be(expectedVideoDynamicRange);
}
}
}
@@ -0,0 +1,31 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.MediaFiles.MediaInfo.MediaInfoFormatterTests
{
[TestFixture]
public class FormatVideoDynamicRangeTypeFixture : TestBase
{
[TestCase(HdrFormat.None, "")]
[TestCase(HdrFormat.Hlg10, "HLG")]
[TestCase(HdrFormat.Pq10, "PQ")]
[TestCase(HdrFormat.Hdr10, "HDR10")]
[TestCase(HdrFormat.Hdr10Plus, "HDR10Plus")]
[TestCase(HdrFormat.DolbyVision, "DV")]
[TestCase(HdrFormat.DolbyVisionHdr10, "DV HDR10")]
[TestCase(HdrFormat.DolbyVisionHlg, "DV HLG")]
[TestCase(HdrFormat.DolbyVisionSdr, "DV SDR")]
public void should_format_video_dynamic_range_type(HdrFormat format, string expectedVideoDynamicRangeType)
{
var mediaInfo = new MediaInfoModel
{
VideoHdrFormat = format,
SchemaRevision = 9
};
MediaInfoFormatter.FormatVideoDynamicRangeType(mediaInfo).Should().Be(expectedVideoDynamicRangeType);
}
}
}
@@ -1,43 +0,0 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
{
[TestFixture]
public class MediaInfoModelExtensionsFixture : TestBase
{
[TestCase(8, "", "", "", HdrFormat.None)]
[TestCase(8, "BT.601 NTSC", "BT.709", "", HdrFormat.None)]
[TestCase(8, "BT.2020", "PQ", "", HdrFormat.None)]
[TestCase(8, "", "", "Dolby Vision", HdrFormat.None)]
[TestCase(8, "", "", "SMPTE ST 2086", HdrFormat.None)]
[TestCase(10, "BT.601 NTSC", "PQ", "", HdrFormat.None)]
[TestCase(10, "BT.2020", "BT.709", "", HdrFormat.None)]
[TestCase(10, "BT.2020", "PQ", "", HdrFormat.Pq10)]
[TestCase(10, "BT.2020", "HLG", "", HdrFormat.Hlg10)]
[TestCase(10, "", "", "SMPTE ST 2086", HdrFormat.Hdr10)]
[TestCase(10, "", "", "HDR10", HdrFormat.Hdr10)]
[TestCase(10, "", "", "SMPTE ST 2094 App 4", HdrFormat.Hdr10Plus)]
[TestCase(10, "", "", "Dolby Vision", HdrFormat.DolbyVision)]
[TestCase(10, "BT.2020", "PQ", "Dolby Vision / SMPTE ST 2086", HdrFormat.DolbyVisionHdr10)]
[TestCase(10, "", "", "SL-HDR1", HdrFormat.UnknownHdr)]
[TestCase(10, "", "", "SL-HDR2", HdrFormat.UnknownHdr)]
[TestCase(10, "", "", "SL-HDR3", HdrFormat.UnknownHdr)]
[TestCase(10, "", "", "Technicolor Advanced HDR", HdrFormat.UnknownHdr)]
public void should_get_hdr_format(int bitDepth, string colourPrimaries, string transferCharacteristics, string hdrFormat, HdrFormat expectedVideoDynamicRange)
{
var mediaInfo = new MediaInfoModel
{
VideoBitDepth = bitDepth,
VideoColourPrimaries = colourPrimaries,
VideoTransferCharacteristics = transferCharacteristics,
VideoHdrFormat = hdrFormat,
SchemaRevision = 7
};
MediaInfoModelExtensions.GetHdrFormat(mediaInfo).Should().Be(expectedVideoDynamicRange);
}
}
}
@@ -1,8 +1,13 @@
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using FFMpegCore;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Disk;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.MediaFiles.MediaInfo;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common.Categories;
@@ -40,33 +45,26 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
var info = Subject.GetMediaInfo(path);
info.VideoCodec.Should().BeNull();
info.VideoFormat.Should().Be("AVC");
info.VideoFormat.Should().Be("h264");
info.VideoCodecID.Should().Be("avc1");
info.VideoProfile.Should().Be("Baseline@L2.1");
info.VideoCodecLibrary.Should().Be("");
info.AudioFormat.Should().Be("AAC");
info.AudioCodecID.Should().BeOneOf("40", "mp4a-40-2");
info.AudioProfile.Should().BeOneOf("", "LC");
info.AudioCodecLibrary.Should().Be("");
info.AudioBitrate.Should().Be(128000);
info.AudioChannelsContainer.Should().Be(2);
info.AudioChannelsStream.Should().Be(0);
info.AudioChannelPositionsTextContainer.Should().Be("Front: L R");
info.AudioChannelPositionsTextStream.Should().Be("");
info.AudioLanguages.Should().Be("English");
info.VideoProfile.Should().Be("Constrained Baseline");
info.AudioFormat.Should().Be("aac");
info.AudioCodecID.Should().Be("mp4a");
info.AudioProfile.Should().Be("LC");
info.AudioBitrate.Should().Be(125488);
info.AudioChannels.Should().Be(2);
info.AudioChannelPositions.Should().Be("stereo");
info.AudioLanguages.Should().BeEquivalentTo("eng");
info.Height.Should().Be(320);
info.RunTime.Seconds.Should().Be(10);
info.ScanType.Should().Be("Progressive");
info.Subtitles.Should().Be("");
info.VideoBitrate.Should().Be(193329);
info.Subtitles.Should().BeEmpty();
info.VideoBitrate.Should().Be(193328);
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().BeOneOf("", "LC");
info.VideoHdrFormat.Should().BeEmpty();
info.VideoHdrFormatCompatibility.Should().BeEmpty();
info.VideoBitDepth.Should().Be(8);
info.VideoColourPrimaries.Should().Be("smpte170m");
info.VideoTransferCharacteristics.Should().Be("bt709");
}
[Test]
@@ -83,45 +81,62 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaInfo
var info = Subject.GetMediaInfo(path);
info.VideoCodec.Should().BeNull();
info.VideoFormat.Should().Be("AVC");
info.VideoFormat.Should().Be("h264");
info.VideoCodecID.Should().Be("avc1");
info.VideoProfile.Should().Be("Baseline@L2.1");
info.VideoCodecLibrary.Should().Be("");
info.AudioFormat.Should().Be("AAC");
info.AudioCodecID.Should().BeOneOf("40", "mp4a-40-2");
info.AudioProfile.Should().BeOneOf("", "LC");
info.AudioCodecLibrary.Should().Be("");
info.AudioBitrate.Should().Be(128000);
info.AudioChannelsContainer.Should().Be(2);
info.AudioChannelsStream.Should().Be(0);
info.AudioChannelPositionsTextContainer.Should().Be("Front: L R");
info.AudioChannelPositionsTextStream.Should().Be("");
info.AudioLanguages.Should().Be("English");
info.VideoProfile.Should().Be("Constrained Baseline");
info.AudioFormat.Should().Be("aac");
info.AudioCodecID.Should().Be("mp4a");
info.AudioProfile.Should().Be("LC");
info.AudioBitrate.Should().Be(125488);
info.AudioChannels.Should().Be(2);
info.AudioChannelPositions.Should().Be("stereo");
info.AudioLanguages.Should().BeEquivalentTo("eng");
info.Height.Should().Be(320);
info.RunTime.Seconds.Should().Be(10);
info.ScanType.Should().Be("Progressive");
info.Subtitles.Should().Be("");
info.VideoBitrate.Should().Be(193329);
info.Subtitles.Should().BeEmpty();
info.VideoBitrate.Should().Be(193328);
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().BeOneOf("", "LC");
info.VideoHdrFormat.Should().BeEmpty();
info.VideoHdrFormatCompatibility.Should().BeEmpty();
info.VideoColourPrimaries.Should().Be("smpte170m");
info.VideoTransferCharacteristics.Should().Be("bt709");
}
[Test]
public void should_dispose_file_after_scanning_mediainfo()
[TestCase(8, "", "", "", null, HdrFormat.None)]
[TestCase(10, "", "", "", null, HdrFormat.None)]
[TestCase(10, "bt709", "bt709", "", null, HdrFormat.None)]
[TestCase(8, "bt2020", "smpte2084", "", null, HdrFormat.None)]
[TestCase(10, "bt2020", "bt2020-10", "", null, HdrFormat.Hlg10)]
[TestCase(10, "bt2020", "arib-std-b67", "", null, HdrFormat.Hlg10)]
[TestCase(10, "bt2020", "smpte2084", "", null, HdrFormat.Pq10)]
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.SideData", null, HdrFormat.Pq10)]
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.MasteringDisplayMetadata", null, HdrFormat.Hdr10)]
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.ContentLightLevelMetadata", null, HdrFormat.Hdr10)]
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.HdrDynamicMetadataSpmte2094", null, HdrFormat.Hdr10Plus)]
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.DoviConfigurationRecordSideData", null, HdrFormat.DolbyVision)]
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.DoviConfigurationRecordSideData", 1, HdrFormat.DolbyVisionHdr10)]
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.DoviConfigurationRecordSideData", 2, HdrFormat.DolbyVisionSdr)]
[TestCase(10, "bt2020", "smpte2084", "FFMpegCore.DoviConfigurationRecordSideData", 4, HdrFormat.DolbyVisionHlg)]
public void should_detect_hdr_correctly(int bitDepth, string colourPrimaries, string transferFunction, string sideDataTypes, int? doviConfigId, HdrFormat expected)
{
var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "Files", "Media", "H264_sample.mp4");
var assembly = Assembly.GetAssembly(typeof(FFProbe));
var types = sideDataTypes.Split(",").Select(x => x.Trim()).ToList();
var sideData = types.Where(x => x.IsNotNullOrWhiteSpace()).Select(x => assembly.CreateInstance(x)).Cast<SideData>().ToList();
var info = Subject.GetMediaInfo(path);
if (doviConfigId.HasValue)
{
sideData.ForEach(x =>
{
if (x.GetType().Name == "DoviConfigurationRecordSideData")
{
((DoviConfigurationRecordSideData)x).DvBlSignalCompatibilityId = doviConfigId.Value;
}
});
}
var stream = new FileStream(path, FileMode.Open, FileAccess.Write);
var result = VideoFileInfoReader.GetHdrFormat(bitDepth, colourPrimaries, transferFunction, sideData);
stream.Close();
result.Should().Be(expected);
}
}
}