diff options
| author | JPVenson <github@jpb.email> | 2024-10-08 09:34:34 +0000 |
|---|---|---|
| committer | JPVenson <github@jpb.email> | 2024-10-08 09:34:34 +0000 |
| commit | d3a3d9fce3b891eb0be274a0cdc45a989e557652 (patch) | |
| tree | bd232ef477c259f1fafa204016f6efd4dcb8691f /tests | |
| parent | ee1bdf4e222125ed7382165fd7e09599ca4bd4aa (diff) | |
| parent | aaf20592bb0bbdf4f0f0d99fed091758e68ae850 (diff) | |
Merge remote-tracking branch 'jellyfinorigin/master' into feature/EFUserData
Diffstat (limited to 'tests')
24 files changed, 1907 insertions, 822 deletions
diff --git a/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs b/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs index f3ada59db..6171f12e4 100644 --- a/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs +++ b/tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs @@ -1,4 +1,7 @@ using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.MediaInfo; +using Moq; using Xunit; namespace Jellyfin.Controller.Tests.Entities; @@ -14,4 +17,30 @@ public class BaseItemTests [InlineData("1test 2", "0000000001test 0000000002")] public void BaseItem_ModifySortChunks_Valid(string input, string expected) => Assert.Equal(expected, BaseItem.ModifySortChunks(input)); + + [Theory] + [InlineData("/Movies/Ted/Ted.mp4", "/Movies/Ted/Ted - Unrated Edition.mp4", "Ted", "Unrated Edition")] + [InlineData("/Movies/Deadpool 2 (2018)/Deadpool 2 (2018).mkv", "/Movies/Deadpool 2 (2018)/Deadpool 2 (2018) - Super Duper Cut.mkv", "Deadpool 2 (2018)", "Super Duper Cut")] + public void GetMediaSourceName_Valid(string primaryPath, string altPath, string name, string altName) + { + var mediaSourceManager = new Mock<IMediaSourceManager>(); + mediaSourceManager.Setup(x => x.GetPathProtocol(It.IsAny<string>())) + .Returns((string x) => MediaProtocol.File); + BaseItem.MediaSourceManager = mediaSourceManager.Object; + + var video = new Video() + { + Path = primaryPath + }; + + var videoAlt = new Video() + { + Path = altPath, + }; + + video.LocalAlternateVersions = [videoAlt.Path]; + + Assert.Equal(name, video.GetMediaSourceName(video)); + Assert.Equal(altName, video.GetMediaSourceName(videoAlt)); + } } diff --git a/tests/Jellyfin.Extensions.Tests/FormattingStreamWriterTests.cs b/tests/Jellyfin.Extensions.Tests/FormattingStreamWriterTests.cs new file mode 100644 index 000000000..06e3c2721 --- /dev/null +++ b/tests/Jellyfin.Extensions.Tests/FormattingStreamWriterTests.cs @@ -0,0 +1,23 @@ +using System.Globalization; +using System.IO; +using System.Text; +using System.Threading; +using Xunit; + +namespace Jellyfin.Extensions.Tests; + +public static class FormattingStreamWriterTests +{ + [Fact] + public static void Shuffle_Valid_Correct() + { + Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE", false); + using (var ms = new MemoryStream()) + using (var txt = new FormattingStreamWriter(ms, CultureInfo.InvariantCulture)) + { + txt.Write("{0}", 3.14159); + txt.Close(); + Assert.Equal("3.14159", Encoding.UTF8.GetString(ms.ToArray())); + } + } +} diff --git a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs index 61105b42b..9fc015823 100644 --- a/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs +++ b/tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs @@ -41,7 +41,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<string> { - Value = new[] { "a", "b", "c" } + Value = ["a", "b", "c"] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a,b,c"" }", _jsonOptions); @@ -53,7 +53,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<string> { - Value = new[] { "a", "b", "c" } + Value = ["a", "b", "c"] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": ""a, b, c"" }", _jsonOptions); @@ -65,7 +65,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<GeneralCommandType> { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,MoveDown"" }", _jsonOptions); @@ -77,7 +77,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<GeneralCommandType> { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,,MoveDown"" }", _jsonOptions); @@ -89,7 +89,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<GeneralCommandType> { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp,TotallyNotAVallidCommand,MoveDown"" }", _jsonOptions); @@ -101,7 +101,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<GeneralCommandType> { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": ""MoveUp, MoveDown"" }", _jsonOptions); @@ -113,7 +113,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<string> { - Value = new[] { "a", "b", "c" } + Value = ["a", "b", "c"] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<string>>(@"{ ""Value"": [""a"",""b"",""c""] }", _jsonOptions); @@ -125,7 +125,7 @@ namespace Jellyfin.Extensions.Tests.Json.Converters { var desiredValue = new GenericBodyArrayModel<GeneralCommandType> { - Value = new[] { GeneralCommandType.MoveUp, GeneralCommandType.MoveDown } + Value = [GeneralCommandType.MoveUp, GeneralCommandType.MoveDown] }; var value = JsonSerializer.Deserialize<GenericBodyArrayModel<GeneralCommandType>>(@"{ ""Value"": [""MoveUp"", ""MoveDown""] }", _jsonOptions); diff --git a/tests/Jellyfin.Model.Tests/Dlna/ContainerHelperTests.cs b/tests/Jellyfin.Model.Tests/Dlna/ContainerHelperTests.cs new file mode 100644 index 000000000..1ad4bed56 --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Dlna/ContainerHelperTests.cs @@ -0,0 +1,83 @@ +using System; +using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Extensions; +using Xunit; + +namespace Jellyfin.Model.Tests.Dlna; + +public class ContainerHelperTests +{ + private readonly ContainerProfile _emptyContainerProfile = new ContainerProfile(); + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData("mp4")] + public void ContainsContainer_EmptyContainerProfile_ReturnsTrue(string? containers) + { + Assert.True(_emptyContainerProfile.ContainsContainer(containers)); + } + + [Theory] + [InlineData("mp3,mpeg", "mp3")] + [InlineData("mp3,mpeg,avi", "mp3,avi")] + [InlineData("-mp3,mpeg", "avi")] + [InlineData("-mp3,mpeg,avi", "mp4,jpg")] + public void ContainsContainer_InList_ReturnsTrue(string container, string? extension) + { + Assert.True(ContainerHelper.ContainsContainer(container, extension)); + } + + [Theory] + [InlineData("mp3,mpeg", "avi")] + [InlineData("mp3,mpeg,avi", "mp4,jpg")] + [InlineData("mp3,mpeg", null)] + [InlineData("mp3,mpeg", "")] + [InlineData("-mp3,mpeg", "mp3")] + [InlineData("-mp3,mpeg,avi", "mpeg,avi")] + [InlineData(",mp3,", ",avi,")] // Empty values should be discarded + [InlineData("-,mp3,", ",mp3,")] // Empty values should be discarded + public void ContainsContainer_NotInList_ReturnsFalse(string container, string? extension) + { + Assert.False(ContainerHelper.ContainsContainer(container, extension)); + + if (extension is not null) + { + Assert.False(ContainerHelper.ContainsContainer(container, extension.AsSpan())); + } + } + + [Theory] + [InlineData("mp3,mpeg", "mp3")] + [InlineData("mp3,mpeg,avi", "mp3,avi")] + [InlineData("-mp3,mpeg", "avi")] + [InlineData("-mp3,mpeg,avi", "mp4,jpg")] + public void ContainsContainer_InList_ReturnsTrue_SpanVersion(string container, string? extension) + { + Assert.True(ContainerHelper.ContainsContainer(container, extension.AsSpan())); + } + + [Theory] + [InlineData(new string[] { "mp3", "mpeg" }, false, "mpeg")] + [InlineData(new string[] { "mp3", "mpeg", "avi" }, false, "avi")] + [InlineData(new string[] { "mp3", "", "avi" }, false, "mp3")] + [InlineData(new string[] { "mp3", "mpeg" }, true, "avi")] + [InlineData(new string[] { "mp3", "mpeg", "avi" }, true, "mkv")] + [InlineData(new string[] { "mp3", "", "avi" }, true, "")] + public void ContainsContainer_ThreeArgs_InList_ReturnsTrue(string[] containers, bool isNegativeList, string inputContainer) + { + Assert.True(ContainerHelper.ContainsContainer(containers, isNegativeList, inputContainer)); + } + + [Theory] + [InlineData(new string[] { "mp3", "mpeg" }, false, "avi")] + [InlineData(new string[] { "mp3", "mpeg", "avi" }, false, "mkv")] + [InlineData(new string[] { "mp3", "", "avi" }, false, "")] + [InlineData(new string[] { "mp3", "mpeg" }, true, "mpeg")] + [InlineData(new string[] { "mp3", "mpeg", "avi" }, true, "mp3")] + [InlineData(new string[] { "mp3", "", "avi" }, true, "avi")] + public void ContainsContainer_ThreeArgs_InList_ReturnsFalse(string[] containers, bool isNegativeList, string inputContainer) + { + Assert.False(ContainerHelper.ContainsContainer(containers, isNegativeList, inputContainer)); + } +} diff --git a/tests/Jellyfin.Model.Tests/Dlna/ContainerProfileTests.cs b/tests/Jellyfin.Model.Tests/Dlna/ContainerProfileTests.cs deleted file mode 100644 index cca056c28..000000000 --- a/tests/Jellyfin.Model.Tests/Dlna/ContainerProfileTests.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediaBrowser.Model.Dlna; -using Xunit; - -namespace Jellyfin.Model.Tests.Dlna -{ - public class ContainerProfileTests - { - private readonly ContainerProfile _emptyContainerProfile = new ContainerProfile(); - - [Theory] - [InlineData(null)] - [InlineData("")] - [InlineData("mp4")] - public void ContainsContainer_EmptyContainerProfile_True(string? containers) - { - Assert.True(_emptyContainerProfile.ContainsContainer(containers)); - } - } -} diff --git a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs index 31ddd427c..bd2143f25 100644 --- a/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs +++ b/tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs @@ -22,37 +22,58 @@ namespace Jellyfin.Model.Tests [Theory] // Chrome [InlineData("Chrome", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)] // #6450 - [InlineData("Chrome", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Chrome", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450 - [InlineData("Chrome", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioIsExternal)] // #6450 - [InlineData("Chrome", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Chrome", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")] - [InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode")] - [InlineData("Chrome", "mp4-hevc-ac3-aacDef-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode")] - [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported, "Remux")] // #6450 - [InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 + [InlineData("Chrome", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioIsExternal, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mp4-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mkv-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)] + [InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] + [InlineData("Chrome", "mp4-hevc-ac3-aacDef-srt-15200k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux", "HLS.mp4")] + [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported, "Remux", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] // #6450 + [InlineData("Chrome", "mp4-h264-hi10p-aac-5000k", PlayMethod.DirectPlay)] + [InlineData("Chrome", "mkv-h264-hi10p-aac-5000k-brokenfps", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported, "Remux", "HLS.mp4")] + [InlineData("Chrome", "mp4-dvh1.05-eac3-15200k", PlayMethod.Transcode, TranscodeReason.VideoRangeTypeNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Chrome", "mkv-dvhe.05-eac3-28000k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.VideoRangeTypeNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Chrome", "mkv-dvhe.08-eac3-15200k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.VideoRangeTypeNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Chrome", "mp4-dvhe.08-eac3-15200k", PlayMethod.Transcode, TranscodeReason.VideoRangeTypeNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode", "HLS.mp4")] // Firefox [InlineData("Firefox", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)] // #6450 - [InlineData("Firefox", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Firefox", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450 - [InlineData("Firefox", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioIsExternal)] // #6450 - [InlineData("Firefox", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Firefox", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")] - [InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode")] - [InlineData("Firefox", "mp4-hevc-ac3-aacDef-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode")] - [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported, "Remux")] // #6450 - [InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 + [InlineData("Firefox", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioIsExternal, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mp4-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mkv-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Firefox", "mp4-hevc-ac3-aacDef-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported, "Remux", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] // #6450 + [InlineData("Firefox", "mp4-h264-hi10p-aac-5000k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.VideoProfileNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Firefox", "mkv-h264-hi10p-aac-5000k-brokenfps", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.VideoProfileNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Firefox", "mp4-dvh1.05-eac3-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Firefox", "mkv-dvhe.05-eac3-28000k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Firefox", "mkv-dvhe.08-eac3-15200k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Firefox", "mp4-dvhe.08-eac3-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode", "HLS.mp4")] // Safari [InlineData("SafariNext", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)] // #6450 [InlineData("SafariNext", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)] // #6450 [InlineData("SafariNext", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectPlay)] // #6450 [InlineData("SafariNext", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.DirectPlay)] // #6450 [InlineData("SafariNext", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)] // #6450 - [InlineData("SafariNext", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Remux", "HLS.mp4")] // #6450 - [InlineData("SafariNext", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] // #6450 - [InlineData("SafariNext", "mp4-hevc-ac3-aacExt-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("SafariNext", "mkv-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("SafariNext", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecTagNotSupported, "Remux", "HLS.mp4")] // #6450 + [InlineData("SafariNext", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecTagNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("SafariNext", "mp4-hevc-ac3-aacExt-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecTagNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("SafariNext", "mp4-h264-hi10p-aac-5000k", PlayMethod.Transcode, TranscodeReason.VideoProfileNotSupported, "Remux", "HLS.mp4")] + [InlineData("SafariNext", "mkv-h264-hi10p-aac-5000k-brokenfps", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.VideoProfileNotSupported, "Remux", "HLS.mp4")] + [InlineData("SafariNext", "mp4-dvh1.05-eac3-15200k", PlayMethod.DirectPlay)] + [InlineData("SafariNext", "mkv-dvhe.05-eac3-28000k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.VideoCodecTagNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] + [InlineData("SafariNext", "mkv-dvhe.08-eac3-15200k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.VideoCodecTagNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] + [InlineData("SafariNext", "mp4-dvhe.08-eac3-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecTagNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] // AndroidPixel [InlineData("AndroidPixel", "mp4-h264-aac-srt-2600k", PlayMethod.DirectPlay)] // #6450 [InlineData("AndroidPixel", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)] // #6450 @@ -62,21 +83,21 @@ namespace Jellyfin.Model.Tests [InlineData("AndroidPixel", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.ContainerBitrateExceedsLimit, "Transcode")] // Yatse [InlineData("Yatse", "mp4-h264-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 - [InlineData("Yatse", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Yatse", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450 - [InlineData("Yatse", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] + [InlineData("Yatse", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("Yatse", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450 + [InlineData("Yatse", "mp4-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] [InlineData("Yatse", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 - [InlineData("Yatse", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Yatse", "mp4-hevc-ac3-aacDef-srt-15200k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450 + [InlineData("Yatse", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "Transcode")] // Full transcode because profile only has ts which does not allow hevc + [InlineData("Yatse", "mp4-hevc-ac3-aacDef-srt-15200k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Transcode")] // Full transcode because profile only has ts which does not allow hevc // RokuSSPlus [InlineData("RokuSSPlus", "mp4-h264-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 - [InlineData("RokuSSPlus", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("RokuSSPlus", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] // #6450 [InlineData("RokuSSPlus", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 should be DirectPlay - [InlineData("RokuSSPlus", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("RokuSSPlus", "mp4-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] // #6450 [InlineData("RokuSSPlus", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 - [InlineData("RokuSSPlus", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("RokuSSPlus", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "Transcode")] // Full transcode because profile only has ts which does not allow hevc [InlineData("RokuSSPlus", "mp4-hevc-ac3-aacDef-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 - [InlineData("RokuSSPlus", "mp4-hevc-ac3-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("RokuSSPlus", "mp4-hevc-ac3-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "Transcode")] // Full transcode because profile only has ts which does not allow hevc // JellyfinMediaPlayer [InlineData("JellyfinMediaPlayer", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 [InlineData("JellyfinMediaPlayer", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 @@ -86,18 +107,18 @@ namespace Jellyfin.Model.Tests [InlineData("JellyfinMediaPlayer", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] // #6450 [InlineData("JellyfinMediaPlayer", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] // #6450 [InlineData("JellyfinMediaPlayer", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] // #6450 - // Chrome-NoHLS + // Non-HLS Progressive transcoding [InlineData("Chrome-NoHLS", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)] // #6450 - [InlineData("Chrome-NoHLS", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Chrome-NoHLS", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450 - [InlineData("Chrome-NoHLS", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioIsExternal)] // #6450 - [InlineData("Chrome-NoHLS", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("Chrome-NoHLS", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "http")] // #6450 + [InlineData("Chrome-NoHLS", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux", "http")] // #6450 + [InlineData("Chrome-NoHLS", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioIsExternal, "Remux", "http")] // #6450 + [InlineData("Chrome-NoHLS", "mp4-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "http")] // #6450 [InlineData("Chrome-NoHLS", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode", "http")] [InlineData("Chrome-NoHLS", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode", "http")] [InlineData("Chrome-NoHLS", "mp4-hevc-ac3-aacDef-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode", "http")] - [InlineData("Chrome-NoHLS", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported, "Remux")] // #6450 - [InlineData("Chrome-NoHLS", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Chrome-NoHLS", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 + [InlineData("Chrome-NoHLS", "mkv-vp9-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported, "DirectStream", "http")] // webm requested, aac not supported + [InlineData("Chrome-NoHLS", "mkv-vp9-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported, "DirectStream", "http")] // #6450 + [InlineData("Chrome-NoHLS", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux", "http")] // #6450 // TranscodeMedia [InlineData("TranscodeMedia", "mp4-h264-aac-vtt-2600k", PlayMethod.Transcode, TranscodeReason.DirectPlayError, "Remux", "HLS.mp4")] [InlineData("TranscodeMedia", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.DirectPlayError, "DirectStream", "HLS.mp4")] @@ -147,7 +168,7 @@ namespace Jellyfin.Model.Tests [InlineData("AndroidTVExoPlayer", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)] [InlineData("AndroidTVExoPlayer", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("AndroidTVExoPlayer", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] - [InlineData("AndroidTVExoPlayer", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] + [InlineData("AndroidTVExoPlayer", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "Transcode")] // Full transcode because profile only has ts which does not allow vp9 // Tizen 3 Stereo [InlineData("Tizen3-stereo", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)] @@ -155,7 +176,7 @@ namespace Jellyfin.Model.Tests [InlineData("Tizen3-stereo", "mp4-h264-dts-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen3-stereo", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)] [InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)] - [InlineData("Tizen3-stereo", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] + [InlineData("Tizen3-stereo", "mp4-hevc-truehd-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] [InlineData("Tizen3-stereo", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen3-stereo", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen3-stereo", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] @@ -163,13 +184,18 @@ namespace Jellyfin.Model.Tests [InlineData("Tizen4-4K-5.1", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)] - [InlineData("Tizen4-4K-5.1", "mp4-h264-dts-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] + [InlineData("Tizen4-4K-5.1", "mp4-h264-dts-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] [InlineData("Tizen4-4K-5.1", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)] - [InlineData("Tizen4-4K-5.1", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] + [InlineData("Tizen4-4K-5.1", "mp4-hevc-truehd-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] + // WebOS 23 + [InlineData("WebOS-23", "mkv-dvhe.08-eac3-15200k", PlayMethod.Transcode, TranscodeReason.VideoRangeTypeNotSupported, "Remux")] + [InlineData("WebOS-23", "mp4-dvh1.05-eac3-15200k", PlayMethod.DirectPlay)] + [InlineData("WebOS-23", "mp4-dvhe.08-eac3-15200k", PlayMethod.DirectPlay)] + [InlineData("WebOS-23", "mkv-dvhe.05-eac3-28000k", PlayMethod.Transcode, TranscodeReason.VideoRangeTypeNotSupported, "Remux")] public async Task BuildVideoItemSimple(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = default, string transcodeMode = "DirectStream", string transcodeProtocol = "") { var options = await GetMediaOptions(deviceName, mediaSource); @@ -179,24 +205,24 @@ namespace Jellyfin.Model.Tests [Theory] // Chrome [InlineData("Chrome", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)] // #6450 - [InlineData("Chrome", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Chrome", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 <BUG: this is direct played> - [InlineData("Chrome", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Chrome", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Chrome", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")] - [InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode")] - [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported, "Remux")] // #6450 - [InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 + [InlineData("Chrome", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 <BUG: this is direct played> + [InlineData("Chrome", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mp4-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)] + [InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] + [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported, "Remux", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux", "HLS.mp4")] // #6450 // Firefox [InlineData("Firefox", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)] // #6450 - [InlineData("Firefox", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Firefox", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Firefox", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Firefox", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")] - [InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode")] - [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported, "Remux")] // #6450 - [InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("Firefox", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mp4-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioCodecNotSupported, "Transcode", "HLS.mp4")] + [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported, "Remux", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.ContainerNotSupported | TranscodeReason.AudioCodecNotSupported, "DirectStream", "HLS.mp4")] // #6450 [InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 // Safari [InlineData("SafariNext", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)] // #6450 @@ -204,9 +230,10 @@ namespace Jellyfin.Model.Tests [InlineData("SafariNext", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectPlay)] // #6450 [InlineData("SafariNext", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.DirectPlay)] // #6450 [InlineData("SafariNext", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)] // #6450 - [InlineData("SafariNext", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Remux", "HLS.mp4")] // #6450 - [InlineData("SafariNext", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] // #6450 - [InlineData("SafariNext", "mp4-hevc-ac3-aacExt-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("SafariNext", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecTagNotSupported, "Remux", "HLS.mp4")] // #6450 + [InlineData("SafariNext", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecTagNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("SafariNext", "mp4-hevc-ac3-aacExt-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecTagNotSupported | TranscodeReason.AudioChannelsNotSupported, "DirectStream", "HLS.mp4")] // #6450 + // AndroidPixel [InlineData("AndroidPixel", "mp4-h264-aac-srt-2600k", PlayMethod.DirectPlay)] // #6450 [InlineData("AndroidPixel", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectPlay)] // #6450 @@ -215,19 +242,19 @@ namespace Jellyfin.Model.Tests [InlineData("AndroidPixel", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.ContainerBitrateExceedsLimit, "Transcode")] // Yatse [InlineData("Yatse", "mp4-h264-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 - [InlineData("Yatse", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Yatse", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("Yatse", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] + [InlineData("Yatse", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("Yatse", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("Yatse", "mp4-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] [InlineData("Yatse", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 - [InlineData("Yatse", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("Yatse", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "Transcode")] // Full transcode because profile only has ts which does not allow hevc // RokuSSPlus [InlineData("RokuSSPlus", "mp4-h264-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 - [InlineData("RokuSSPlus", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 should be DirectPlay - [InlineData("RokuSSPlus", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("RokuSSPlus", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("RokuSSPlus", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] // #6450 should be DirectPlay + [InlineData("RokuSSPlus", "mp4-h264-ac3-aacDef-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("RokuSSPlus", "mp4-h264-ac3-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] // #6450 [InlineData("RokuSSPlus", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 - [InlineData("RokuSSPlus", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 - [InlineData("RokuSSPlus", "mp4-hevc-ac3-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450 + [InlineData("RokuSSPlus", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "Transcode")] // Full transcode because profile only has ts which does not allow hevc + [InlineData("RokuSSPlus", "mp4-hevc-ac3-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "Transcode")] // Full transcode because profile only has ts which does not allow hevc // JellyfinMediaPlayer [InlineData("JellyfinMediaPlayer", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 [InlineData("JellyfinMediaPlayer", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 @@ -245,7 +272,7 @@ namespace Jellyfin.Model.Tests [InlineData("AndroidTVExoPlayer", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)] [InlineData("AndroidTVExoPlayer", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("AndroidTVExoPlayer", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] - [InlineData("AndroidTVExoPlayer", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] + [InlineData("AndroidTVExoPlayer", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported, "Transcode")] // Full transcode because profile only has ts which does not allow vp9 // Tizen 3 Stereo [InlineData("Tizen3-stereo", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)] @@ -253,7 +280,7 @@ namespace Jellyfin.Model.Tests [InlineData("Tizen3-stereo", "mp4-h264-dts-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen3-stereo", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)] [InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)] - [InlineData("Tizen3-stereo", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] + [InlineData("Tizen3-stereo", "mp4-hevc-truehd-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] [InlineData("Tizen3-stereo", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen3-stereo", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen3-stereo", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] @@ -261,10 +288,10 @@ namespace Jellyfin.Model.Tests [InlineData("Tizen4-4K-5.1", "mp4-h264-aac-vtt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectPlay)] - [InlineData("Tizen4-4K-5.1", "mp4-h264-dts-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] + [InlineData("Tizen4-4K-5.1", "mp4-h264-dts-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] [InlineData("Tizen4-4K-5.1", "mp4-hevc-aac-srt-15200k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay)] - [InlineData("Tizen4-4K-5.1", "mp4-hevc-truehd-srt-15200k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] + [InlineData("Tizen4-4K-5.1", "mp4-hevc-truehd-srt-15200k", PlayMethod.Transcode, TranscodeReason.AudioCodecNotSupported)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectPlay)] [InlineData("Tizen4-4K-5.1", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay)] @@ -281,34 +308,37 @@ namespace Jellyfin.Model.Tests [Theory] // Chrome - [InlineData("Chrome", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450 - [InlineData("Chrome", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] - [InlineData("Chrome", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioIsExternal)] // #6450 - [InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode")] + [InlineData("Chrome", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux", "HLS.mp4")] + [InlineData("Chrome", "mp4-h264-ac3-aacExt-srt-2600k", PlayMethod.Transcode, TranscodeReason.AudioIsExternal, "DirectStream", "HLS.mp4")] // #6450 + [InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux", "HLS.mp4")] // Firefox - [InlineData("Firefox", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450 - [InlineData("Firefox", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] - [InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode")] + [InlineData("Firefox", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux", "HLS.mp4")] // #6450 + [InlineData("Firefox", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux", "HLS.mp4")] + [InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported | TranscodeReason.SecondaryAudioNotSupported, "Transcode", "HLS.mp4")] // Yatse - [InlineData("Yatse", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450 - [InlineData("Yatse", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] - [InlineData("Yatse", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450 + [InlineData("Yatse", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // #6450 + [InlineData("Yatse", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux")] + [InlineData("Yatse", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Transcode")] // Full transcode because profile only has ts which does not allow hevc // RokuSSPlus [InlineData("RokuSSPlus", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 [InlineData("RokuSSPlus", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450 // no streams - [InlineData("Chrome", "no-streams", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")] // #6450 + [InlineData("Chrome", "no-streams", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode", "HLS.mp4")] // #6450 // AndroidTV [InlineData("AndroidTVExoPlayer", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] [InlineData("AndroidTVExoPlayer", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // Tizen 3 Stereo - [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] - [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] - [InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] + [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux")] + [InlineData("Tizen3-stereo", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux")] + [InlineData("Tizen3-stereo", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux")] // Tizen 4 4K 5.1 - [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] - [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] - [InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.DirectStream, TranscodeReason.SecondaryAudioNotSupported, "Remux")] + [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux")] + [InlineData("Tizen4-4K-5.1", "mp4-h264-ac3-aac-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux")] + [InlineData("Tizen4-4K-5.1", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.SecondaryAudioNotSupported, "Remux")] + // TranscodeMedia + [InlineData("TranscodeMedia", "mp4-h264-ac3-aac-srt-2600k", PlayMethod.Transcode, TranscodeReason.DirectPlayError, "Remux", "HLS.mp4")] + [InlineData("TranscodeMedia", "mp4-h264-ac3-aac-mp3-srt-2600k", PlayMethod.Transcode, TranscodeReason.DirectPlayError, "Remux", "HLS.ts")] public async Task BuildVideoItemWithDirectPlayExplicitStreams(string deviceName, string mediaSource, PlayMethod? playMethod, TranscodeReason why = default, string transcodeMode = "DirectStream", string transcodeProtocol = "") { var options = await GetMediaOptions(deviceName, mediaSource); @@ -328,7 +358,7 @@ namespace Jellyfin.Model.Tests { if (string.IsNullOrEmpty(transcodeProtocol)) { - transcodeProtocol = playMethod == PlayMethod.DirectStream ? "http" : "HLS.ts"; + transcodeProtocol = "HLS.ts"; } var builder = GetStreamBuilder(); @@ -359,25 +389,30 @@ namespace Jellyfin.Model.Tests if (playMethod == PlayMethod.DirectPlay) { // Check expected container - var containers = ContainerProfile.SplitValue(mediaSource.Container); + var containers = mediaSource.Container.Split(','); + Assert.Contains(uri.Extension, containers); // TODO: Test transcode too - // Assert.Contains(uri.Extension, containers); // Check expected video codec (1) - Assert.Contains(targetVideoStream?.Codec, streamInfo.TargetVideoCodec); - Assert.Single(streamInfo.TargetVideoCodec); + if (targetVideoStream?.Codec is not null) + { + Assert.Contains(targetVideoStream?.Codec, streamInfo.TargetVideoCodec); + Assert.Single(streamInfo.TargetVideoCodec); + } - // Check expected audio codecs (1) - Assert.Contains(targetAudioStream?.Codec, streamInfo.TargetAudioCodec); - Assert.Single(streamInfo.TargetAudioCodec); - // Assert.Single(val.AudioCodecs); + if (targetAudioStream?.Codec is not null) + { + // Check expected audio codecs (1) + Assert.Contains(targetAudioStream?.Codec, streamInfo.TargetAudioCodec); + Assert.Single(streamInfo.TargetAudioCodec); + } if (transcodeMode.Equals("DirectStream", StringComparison.Ordinal)) { Assert.Equal(streamInfo.Container, uri.Extension); } } - else if (playMethod == PlayMethod.DirectStream || playMethod == PlayMethod.Transcode) + else if (playMethod == PlayMethod.Transcode) { Assert.NotNull(streamInfo.Container); Assert.NotEmpty(streamInfo.VideoCodecs); @@ -409,7 +444,7 @@ namespace Jellyfin.Model.Tests // Full transcode if (transcodeMode.Equals("Transcode", StringComparison.Ordinal)) { - if ((streamInfo.TranscodeReasons & (StreamBuilder.ContainerReasons | TranscodeReason.DirectPlayError)) == 0) + if ((streamInfo.TranscodeReasons & (StreamBuilder.ContainerReasons | TranscodeReason.DirectPlayError | TranscodeReason.VideoRangeTypeNotSupported)) == 0) { Assert.All( videoStreams, @@ -547,6 +582,7 @@ namespace Jellyfin.Model.Tests Profile = dp, AllowAudioStreamCopy = true, AllowVideoStreamCopy = true, + EnableDirectStream = false // This is disabled in server }; } diff --git a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Chrome.json b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Chrome.json index 81bb97ac8..e2f75b569 100644 --- a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Chrome.json +++ b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Chrome.json @@ -16,324 +16,200 @@ "DirectPlayProfiles": [ { "Container": "webm", - "AudioCodec": "vorbis,opus", - "VideoCodec": "vp8,vp9,av1", "Type": "Video", - "$type": "DirectPlayProfile" + "VideoCodec": "vp8,vp9,av1", + "AudioCodec": "vorbis,opus" }, { "Container": "mp4,m4v", - "AudioCodec": "aac,mp3,opus,flac,alac,vorbis", - "VideoCodec": "h264,vp8,vp9,av1", "Type": "Video", - "$type": "DirectPlayProfile" + "VideoCodec": "h264,hevc,vp9,av1", + "AudioCodec": "aac,mp3,mp2,opus,flac,vorbis" }, { "Container": "mov", - "AudioCodec": "aac,mp3,opus,flac,alac,vorbis", - "VideoCodec": "h264", "Type": "Video", - "$type": "DirectPlayProfile" + "VideoCodec": "h264", + "AudioCodec": "aac,mp3,mp2,opus,flac,vorbis" }, { "Container": "opus", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "webm", "AudioCodec": "opus", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" + }, + { + "Container": "ts", + "AudioCodec": "mp3", + "Type": "Audio" }, { "Container": "mp3", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "aac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "m4a", "AudioCodec": "aac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "m4b", "AudioCodec": "aac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "flac", - "Type": "Audio", - "$type": "DirectPlayProfile" - }, - { - "Container": "alac", - "Type": "Audio", - "$type": "DirectPlayProfile" - }, - { - "Container": "m4a", - "AudioCodec": "alac", - "Type": "Audio", - "$type": "DirectPlayProfile" - }, - { - "Container": "m4b", - "AudioCodec": "alac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "webma", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "webm", "AudioCodec": "webma", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "wav", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "ogg", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" + }, + { + "Container": "hls", + "Type": "Video", + "VideoCodec": "av1,hevc,h264,vp9", + "AudioCodec": "aac,mp2,opus,flac" + }, + { + "Container": "hls", + "Type": "Video", + "VideoCodec": "h264", + "AudioCodec": "aac,mp3,mp2" } ], "TranscodingProfiles": [ { - "Container": "ts", + "Container": "mp4", "Type": "Audio", "AudioCodec": "aac", - "Protocol": "hls", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 2, - "SegmentLength": 0, + "Protocol": "hls", + "MaxAudioChannels": "2", + "MinSegments": "2", "BreakOnNonKeyFrames": true, - "$type": "TranscodingProfile" + "EnableAudioVbrEncoding": true }, { "Container": "aac", "Type": "Audio", "AudioCodec": "aac", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "2" }, { "Container": "mp3", "Type": "Audio", "AudioCodec": "mp3", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "2" }, { "Container": "opus", "Type": "Audio", "AudioCodec": "opus", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "2" }, { "Container": "wav", "Type": "Audio", "AudioCodec": "wav", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "2" }, { "Container": "opus", "Type": "Audio", "AudioCodec": "opus", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Static", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "2" }, { "Container": "mp3", "Type": "Audio", "AudioCodec": "mp3", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Static", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "2" }, { "Container": "aac", "Type": "Audio", "AudioCodec": "aac", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Static", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "2" }, { "Container": "wav", "Type": "Audio", "AudioCodec": "wav", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Static", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" - }, - { - "Container": "ts", - "Type": "Video", - "VideoCodec": "h264", - "AudioCodec": "aac,mp3", - "Protocol": "hls", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, - "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 2, - "SegmentLength": 0, - "BreakOnNonKeyFrames": true, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "2" }, { - "Container": "webm", + "Container": "mp4", "Type": "Video", - "VideoCodec": "vp8,vp9,av1,vpx", - "AudioCodec": "vorbis,opus", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, + "AudioCodec": "aac,mp2,opus,flac", + "VideoCodec": "av1,hevc,h264,vp9", "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "hls", + "MaxAudioChannels": "2", + "MinSegments": "2", + "BreakOnNonKeyFrames": true }, { - "Container": "mp4", + "Container": "ts", "Type": "Video", + "AudioCodec": "aac,mp3,mp2", "VideoCodec": "h264", - "AudioCodec": "aac,mp3,opus,flac,alac,vorbis", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, - "Context": "Static", - "EnableSubtitlesInManifest": false, - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Context": "Streaming", + "Protocol": "hls", + "MaxAudioChannels": "2", + "MinSegments": "2", + "BreakOnNonKeyFrames": true } ], + "ContainerProfiles": [], "CodecProfiles": [ { "Type": "VideoAudio", + "Codec": "aac", "Conditions": [ { "Condition": "Equals", "Property": "IsSecondaryAudio", "Value": "false", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false } - ], - "Codec": "aac", - "$type": "CodecProfile" + ] }, { "Type": "VideoAudio", @@ -342,107 +218,144 @@ "Condition": "Equals", "Property": "IsSecondaryAudio", "Value": "false", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false } - ], - "$type": "CodecProfile" + ] }, { "Type": "Video", + "Codec": "h264", "Conditions": [ { "Condition": "NotEquals", "Property": "IsAnamorphic", "Value": "true", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false }, { "Condition": "EqualsAny", "Property": "VideoProfile", "Value": "high|main|baseline|constrained baseline|high 10", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR", + "IsRequired": false }, { "Condition": "LessThanEqual", "Property": "VideoLevel", "Value": "52", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false }, { "Condition": "NotEquals", "Property": "IsInterlaced", "Value": "true", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false } - ], - "Codec": "h264", - "$type": "CodecProfile" + ] }, { "Type": "Video", + "Codec": "hevc", "Conditions": [ { "Condition": "NotEquals", "Property": "IsAnamorphic", "Value": "true", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false }, { "Condition": "EqualsAny", "Property": "VideoProfile", - "Value": "main", - "IsRequired": false, - "$type": "ProfileCondition" + "Value": "main|main 10", + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR|HDR10|HLG", + "IsRequired": false }, { "Condition": "LessThanEqual", "Property": "VideoLevel", - "Value": "120", - "IsRequired": false, - "$type": "ProfileCondition" + "Value": "183", + "IsRequired": false }, { "Condition": "NotEquals", "Property": "IsInterlaced", "Value": "true", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false } - ], - "Codec": "hevc", - "$type": "CodecProfile" - } - ], - "ResponseProfiles": [ + ] + }, { - "Container": "m4v", "Type": "Video", - "MimeType": "video/mp4", - "$type": "ResponseProfile" + "Codec": "vp9", + "Conditions": [ + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR|HDR10|HLG", + "IsRequired": false + } + ] + }, + { + "Type": "Video", + "Codec": "av1", + "Conditions": [ + { + "Condition": "NotEquals", + "Property": "IsAnamorphic", + "Value": "true", + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoProfile", + "Value": "main", + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR|HDR10|HLG", + "IsRequired": false + }, + { + "Condition": "LessThanEqual", + "Property": "VideoLevel", + "Value": "19", + "IsRequired": false + } + ] } ], "SubtitleProfiles": [ { "Format": "vtt", - "Method": "External", - "$type": "SubtitleProfile" + "Method": "External" }, { "Format": "ass", - "Method": "External", - "$type": "SubtitleProfile" + "Method": "External" }, { "Format": "ssa", - "Method": "External", - "$type": "SubtitleProfile" + "Method": "External" } ], - "$type": "DeviceProfile" + "ResponseProfiles": [ + { + "Type": "Video", + "Container": "m4v", + "MimeType": "video/mp4" + } + ] } diff --git a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Firefox.json b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Firefox.json index 9874793d3..21ae7e5cb 100644 --- a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Firefox.json +++ b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Firefox.json @@ -15,426 +15,357 @@ "IgnoreTranscodeByteRangeRequests": false, "DirectPlayProfiles": [ { - "Container": "webm", "AudioCodec": "vorbis,opus", - "VideoCodec": "vp8,vp9,av1", + "Container": "webm", "Type": "Video", - "$type": "DirectPlayProfile" + "VideoCodec": "vp8,vp9,av1" }, { + "AudioCodec": "aac,mp3,mp2,opus,flac,vorbis", "Container": "mp4,m4v", - "AudioCodec": "aac,mp3,opus,flac,alac,vorbis", - "VideoCodec": "h264,vp8,vp9,av1", "Type": "Video", - "$type": "DirectPlayProfile" + "VideoCodec": "h264,vp9,av1" }, { "Container": "opus", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { - "Container": "webm", "AudioCodec": "opus", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Container": "webm", + "Type": "Audio" + }, + { + "AudioCodec": "mp3", + "Container": "ts", + "Type": "Audio" }, { "Container": "mp3", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "aac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { - "Container": "m4a", "AudioCodec": "aac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Container": "m4a", + "Type": "Audio" }, { - "Container": "m4b", "AudioCodec": "aac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Container": "m4b", + "Type": "Audio" }, { "Container": "flac", - "Type": "Audio", - "$type": "DirectPlayProfile" - }, - { - "Container": "alac", - "Type": "Audio", - "$type": "DirectPlayProfile" - }, - { - "Container": "m4a", - "AudioCodec": "alac", - "Type": "Audio", - "$type": "DirectPlayProfile" - }, - { - "Container": "m4b", - "AudioCodec": "alac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "webma", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { - "Container": "webm", "AudioCodec": "webma", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Container": "webm", + "Type": "Audio" }, { "Container": "wav", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "ogg", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" + }, + { + "AudioCodec": "aac,mp2,opus,flac", + "Container": "hls", + "Type": "Video", + "VideoCodec": "av1,h264,vp9" + }, + { + "AudioCodec": "aac,mp3,mp2", + "Container": "hls", + "Type": "Video", + "VideoCodec": "h264" } ], "TranscodingProfiles": [ { - "Container": "ts", - "Type": "Audio", "AudioCodec": "aac", - "Protocol": "hls", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, - "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 2, - "SegmentLength": 0, "BreakOnNonKeyFrames": true, - "$type": "TranscodingProfile" + "Container": "mp4", + "Context": "Streaming", + "EnableAudioVbrEncoding": true, + "MaxAudioChannels": "2", + "MinSegments": "2", + "Protocol": "hls", + "Type": "Audio" }, { - "Container": "aac", - "Type": "Audio", "AudioCodec": "aac", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, + "Container": "aac", "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "MaxAudioChannels": "2", + "Protocol": "http", + "Type": "Audio" }, { - "Container": "mp3", - "Type": "Audio", "AudioCodec": "mp3", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, + "Container": "mp3", "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "MaxAudioChannels": "2", + "Protocol": "http", + "Type": "Audio" }, { - "Container": "opus", - "Type": "Audio", "AudioCodec": "opus", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, + "Container": "opus", "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "MaxAudioChannels": "2", + "Protocol": "http", + "Type": "Audio" }, { - "Container": "wav", - "Type": "Audio", "AudioCodec": "wav", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, + "Container": "wav", "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "MaxAudioChannels": "2", + "Protocol": "http", + "Type": "Audio" }, { - "Container": "opus", - "Type": "Audio", "AudioCodec": "opus", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, + "Container": "opus", "Context": "Static", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "MaxAudioChannels": "2", + "Protocol": "http", + "Type": "Audio" }, { - "Container": "mp3", - "Type": "Audio", "AudioCodec": "mp3", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, + "Container": "mp3", "Context": "Static", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "MaxAudioChannels": "2", + "Protocol": "http", + "Type": "Audio" }, { - "Container": "aac", - "Type": "Audio", "AudioCodec": "aac", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, + "Container": "aac", "Context": "Static", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "MaxAudioChannels": "2", + "Protocol": "http", + "Type": "Audio" }, { - "Container": "wav", - "Type": "Audio", "AudioCodec": "wav", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, + "Container": "wav", "Context": "Static", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "MaxAudioChannels": "2", + "Protocol": "http", + "Type": "Audio" }, { - "Container": "ts", - "Type": "Video", - "VideoCodec": "h264", - "AudioCodec": "aac,mp3", - "Protocol": "hls", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, - "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 2, - "SegmentLength": 0, + "AudioCodec": "aac,mp2,opus,flac", "BreakOnNonKeyFrames": true, - "$type": "TranscodingProfile" - }, - { - "Container": "webm", - "Type": "Video", - "VideoCodec": "vp8,vp9,av1,vpx", - "AudioCodec": "vorbis,opus", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, + "Container": "mp4", "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "MaxAudioChannels": "2", + "MinSegments": "2", + "Protocol": "hls", + "Type": "Video", + "VideoCodec": "av1,h264,vp9" }, { - "Container": "mp4", + "AudioCodec": "aac,mp3,mp2", + "BreakOnNonKeyFrames": true, + "Container": "ts", + "Context": "Streaming", + "MaxAudioChannels": "2", + "MinSegments": "2", + "Protocol": "hls", "Type": "Video", - "VideoCodec": "h264", - "AudioCodec": "aac,mp3,opus,flac,alac,vorbis", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, - "Context": "Static", - "EnableSubtitlesInManifest": false, - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "VideoCodec": "h264" } ], "CodecProfiles": [ { - "Type": "VideoAudio", + "Codec": "aac", "Conditions": [ { "Condition": "Equals", + "IsRequired": false, "Property": "IsSecondaryAudio", - "Value": "false", + "Value": "false" + } + ], + "Type": "VideoAudio" + }, + { + "Conditions": [ + { + "Condition": "LessThanEqual", "IsRequired": false, - "$type": "ProfileCondition" + "Property": "AudioChannels", + "Value": "2" } ], - "Codec": "aac", - "$type": "CodecProfile" + "Type": "Audio" }, { - "Type": "VideoAudio", "Conditions": [ { + "Condition": "LessThanEqual", + "IsRequired": false, + "Property": "AudioChannels", + "Value": "2" + }, + { "Condition": "Equals", - "Property": "IsSecondaryAudio", - "Value": "false", "IsRequired": false, - "$type": "ProfileCondition" + "Property": "IsSecondaryAudio", + "Value": "false" } ], - "$type": "CodecProfile" + "Type": "VideoAudio" }, { - "Type": "Video", + "Codec": "h264", "Conditions": [ { "Condition": "NotEquals", - "Property": "IsAnamorphic", - "Value": "true", "IsRequired": false, - "$type": "ProfileCondition" + "Property": "IsAnamorphic", + "Value": "true" }, { "Condition": "EqualsAny", + "IsRequired": false, "Property": "VideoProfile", - "Value": "high|main|baseline|constrained baseline", + "Value": "high|main|baseline|constrained baseline" + }, + { + "Condition": "EqualsAny", "IsRequired": false, - "$type": "ProfileCondition" + "Property": "VideoRangeType", + "Value": "SDR" }, { "Condition": "LessThanEqual", - "Property": "VideoLevel", - "Value": "52", "IsRequired": false, - "$type": "ProfileCondition" + "Property": "VideoLevel", + "Value": "52" }, { "Condition": "NotEquals", - "Property": "IsInterlaced", - "Value": "true", "IsRequired": false, - "$type": "ProfileCondition" + "Property": "IsInterlaced", + "Value": "true" } ], - "Codec": "h264", - "$type": "CodecProfile" + "Type": "Video" }, { - "Type": "Video", + "Codec": "hevc", "Conditions": [ { "Condition": "NotEquals", - "Property": "IsAnamorphic", - "Value": "true", "IsRequired": false, - "$type": "ProfileCondition" + "Property": "IsAnamorphic", + "Value": "true" }, { "Condition": "EqualsAny", + "IsRequired": false, "Property": "VideoProfile", - "Value": "main", + "Value": "main" + }, + { + "Condition": "EqualsAny", "IsRequired": false, - "$type": "ProfileCondition" + "Property": "VideoRangeType", + "Value": "SDR" }, { "Condition": "LessThanEqual", - "Property": "VideoLevel", - "Value": "120", "IsRequired": false, - "$type": "ProfileCondition" + "Property": "VideoLevel", + "Value": "120" }, { "Condition": "NotEquals", + "IsRequired": false, "Property": "IsInterlaced", - "Value": "true", + "Value": "true" + } + ], + "Type": "Video" + }, + { + "Codec": "vp9", + "Conditions": [ + { + "Condition": "EqualsAny", "IsRequired": false, - "$type": "ProfileCondition" + "Property": "VideoRangeType", + "Value": "SDR" } ], - "Codec": "hevc", - "$type": "CodecProfile" + "Type": "Video" + }, + { + "Codec": "av1", + "Conditions": [ + { + "Condition": "NotEquals", + "IsRequired": false, + "Property": "IsAnamorphic", + "Value": "true" + }, + { + "Condition": "EqualsAny", + "IsRequired": false, + "Property": "VideoProfile", + "Value": "main" + }, + { + "Condition": "EqualsAny", + "IsRequired": false, + "Property": "VideoRangeType", + "Value": "SDR" + }, + { + "Condition": "LessThanEqual", + "IsRequired": false, + "Property": "VideoLevel", + "Value": "19" + } + ], + "Type": "Video" } ], "ResponseProfiles": [ { "Container": "m4v", - "Type": "Video", "MimeType": "video/mp4", - "$type": "ResponseProfile" + "Type": "Video" } ], "SubtitleProfiles": [ { "Format": "vtt", - "Method": "External", - "$type": "SubtitleProfile" + "Method": "External" }, { "Format": "ass", - "Method": "External", - "$type": "SubtitleProfile" + "Method": "External" }, { "Format": "ssa", - "Method": "External", - "$type": "SubtitleProfile" + "Method": "External" } ], "$type": "DeviceProfile" diff --git a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-SafariNext.json b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-SafariNext.json index 3b5a0c254..f61d0e36b 100644 --- a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-SafariNext.json +++ b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-SafariNext.json @@ -16,211 +16,160 @@ "DirectPlayProfiles": [ { "Container": "webm", - "AudioCodec": "vorbis", - "VideoCodec": "vp8,vp9", "Type": "Video", - "$type": "DirectPlayProfile" + "VideoCodec": "vp8", + "AudioCodec": "vorbis,opus" }, { "Container": "mp4,m4v", - "AudioCodec": "aac,mp3,ac3,eac3,flac,alac,vorbis", - "VideoCodec": "h264,vp8,vp9", "Type": "Video", - "$type": "DirectPlayProfile" + "VideoCodec": "h264,hevc,vp9", + "AudioCodec": "aac,ac3,eac3,opus,flac,alac" }, { "Container": "mov", - "AudioCodec": "aac,mp3,ac3,eac3,flac,alac,vorbis", - "VideoCodec": "h264", "Type": "Video", - "$type": "DirectPlayProfile" + "VideoCodec": "h264", + "AudioCodec": "aac,ac3,eac3,opus,flac,alac" + }, + { + "Container": "ts", + "AudioCodec": "mp3", + "Type": "Audio" }, { "Container": "mp3", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "aac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "m4a", "AudioCodec": "aac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "m4b", "AudioCodec": "aac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { - "Container": "flac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Container": "mp4", + "AudioCodec": "flac", + "Type": "Audio" }, { "Container": "alac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "m4a", "AudioCodec": "alac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "m4b", "AudioCodec": "alac", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "webma", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "webm", "AudioCodec": "webma", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" }, { "Container": "wav", - "Type": "Audio", - "$type": "DirectPlayProfile" + "Type": "Audio" + }, + { + "Container": "mp4", + "AudioCodec": "opus", + "Type": "Audio" + }, + { + "Container": "hls", + "Type": "Video", + "VideoCodec": "hevc,h264,vp9", + "AudioCodec": "aac,ac3,eac3,opus,flac,alac" + }, + { + "Container": "hls", + "Type": "Video", + "VideoCodec": "h264", + "AudioCodec": "aac,mp3,ac3,eac3" } ], "TranscodingProfiles": [ { - "Container": "aac", + "Container": "mp4", "Type": "Audio", "AudioCodec": "aac", - "Protocol": "hls", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Streaming", - "EnableSubtitlesInManifest": false, + "Protocol": "hls", "MaxAudioChannels": "6", - "MinSegments": 2, - "SegmentLength": 0, + "MinSegments": "2", "BreakOnNonKeyFrames": true, - "$type": "TranscodingProfile" + "EnableAudioVbrEncoding": true }, { "Container": "aac", "Type": "Audio", "AudioCodec": "aac", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "6" }, { "Container": "mp3", "Type": "Audio", "AudioCodec": "mp3", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "6" }, { "Container": "wav", "Type": "Audio", "AudioCodec": "wav", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Streaming", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "6" }, { "Container": "mp3", "Type": "Audio", "AudioCodec": "mp3", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Static", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "6" }, { "Container": "aac", "Type": "Audio", "AudioCodec": "aac", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Static", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "6" }, { "Container": "wav", "Type": "Audio", "AudioCodec": "wav", - "Protocol": "http", - "EstimateContentLength": false, - "EnableMpegtsM2TsMode": false, - "TranscodeSeekInfo": "Auto", - "CopyTimestamps": false, "Context": "Static", - "EnableSubtitlesInManifest": false, - "MaxAudioChannels": "6", - "MinSegments": 0, - "SegmentLength": 0, - "BreakOnNonKeyFrames": false, - "$type": "TranscodingProfile" + "Protocol": "http", + "MaxAudioChannels": "6" }, { "Container": "mp4", "Type": "Video", - "AudioCodec": "aac,ac3,eac3,flac,alac", - "VideoCodec": "hevc,h264", + "AudioCodec": "aac,ac3,eac3,opus,flac,alac", + "VideoCodec": "hevc,h264,vp9", "Context": "Streaming", "Protocol": "hls", "MaxAudioChannels": "2", @@ -237,121 +186,170 @@ "MaxAudioChannels": "2", "MinSegments": "2", "BreakOnNonKeyFrames": true - }, - { - "Container": "webm", - "Type": "Video", - "AudioCodec": "vorbis", - "VideoCodec": "vp8,vpx", - "Context": "Streaming", - "Protocol": "http", - "MaxAudioChannels": "2" - }, - { - "Container": "mp4", - "Type": "Video", - "AudioCodec": "aac,mp3,ac3,eac3,flac,alac,vorbis", - "VideoCodec": "h264", - "Context": "Static", - "Protocol": "http" } ], + "ContainerProfiles": [], "CodecProfiles": [ { "Type": "Video", + "Container": "hls", + "SubContainer": "mp4", + "Codec": "h264", + "Conditions": [ + { + "Condition": "EqualsAny", + "Property": "VideoProfile", + "Value": "high|main|baseline|constrained baseline|high 10", + "IsRequired": false + } + ] + }, + { + "Type": "Video", + "Codec": "h264", "Conditions": [ { "Condition": "NotEquals", "Property": "IsAnamorphic", "Value": "true", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false }, { "Condition": "EqualsAny", "Property": "VideoProfile", "Value": "high|main|baseline|constrained baseline", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR", + "IsRequired": false }, { "Condition": "LessThanEqual", "Property": "VideoLevel", "Value": "52", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false }, { "Condition": "NotEquals", "Property": "IsInterlaced", "Value": "true", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false } - ], - "Codec": "h264", - "$type": "CodecProfile" + ] }, { "Type": "Video", + "Codec": "hevc", "Conditions": [ { "Condition": "NotEquals", "Property": "IsAnamorphic", "Value": "true", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false }, { "Condition": "EqualsAny", "Property": "VideoProfile", "Value": "main|main 10", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR|HDR10|HLG|DOVI|DOVIWithHDR10|DOVIWithHLG|DOVIWithSDR", + "IsRequired": false }, { "Condition": "LessThanEqual", "Property": "VideoLevel", "Value": "183", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false }, { "Condition": "NotEquals", "Property": "IsInterlaced", "Value": "true", - "IsRequired": false, - "$type": "ProfileCondition" + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoCodecTag", + "Value": "hvc1|dvh1", + "IsRequired": true + }, + { + "Condition": "LessThanEqual", + "Property": "VideoFramerate", + "Value": "60", + "IsRequired": true } - ], - "Codec": "hevc", - "$type": "CodecProfile" - } - ], - "ResponseProfiles": [ + ] + }, + { + "Type": "Video", + "Codec": "vp9", + "Conditions": [ + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR|HDR10|HLG", + "IsRequired": false + } + ] + }, { - "Container": "m4v", "Type": "Video", - "MimeType": "video/mp4", - "$type": "ResponseProfile" + "Codec": "av1", + "Conditions": [ + { + "Condition": "NotEquals", + "Property": "IsAnamorphic", + "Value": "true", + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoProfile", + "Value": "main", + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR|HDR10|HLG", + "IsRequired": false + }, + { + "Condition": "LessThanEqual", + "Property": "VideoLevel", + "Value": "15", + "IsRequired": false + } + ] } ], "SubtitleProfiles": [ { "Format": "vtt", - "Method": "External", - "$type": "SubtitleProfile" + "Method": "External" }, { "Format": "ass", - "Method": "External", - "$type": "SubtitleProfile" + "Method": "External" }, { "Format": "ssa", - "Method": "External", - "$type": "SubtitleProfile" + "Method": "External" } ], - "$type": "DeviceProfile" + "ResponseProfiles": [ + { + "Type": "Video", + "Container": "m4v", + "MimeType": "video/mp4" + } + ] } diff --git a/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-WebOS-23.json b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-WebOS-23.json new file mode 100644 index 000000000..094b0723b --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-WebOS-23.json @@ -0,0 +1,355 @@ +{ + "MaxStreamingBitrate": 120000000, + "MaxStaticBitrate": 100000000, + "MusicStreamingTranscodingBitrate": 384000, + "DirectPlayProfiles": [ + { + "Container": "webm", + "Type": "Video", + "VideoCodec": "vp8,vp9,av1", + "AudioCodec": "vorbis,opus" + }, + { + "Container": "mp4,m4v", + "Type": "Video", + "VideoCodec": "h264,hevc,mpeg2video,vc1,vp9,av1", + "AudioCodec": "aac,ac3,eac3,mp2,pcm_s16le,pcm_s24le,opus,flac,vorbis" + }, + { + "Container": "mkv", + "Type": "Video", + "VideoCodec": "h264,hevc,mpeg2video,vc1,vp9,av1", + "AudioCodec": "aac,ac3,eac3,mp2,pcm_s16le,pcm_s24le,opus,flac,vorbis" + }, + { + "Container": "m2ts", + "Type": "Video", + "VideoCodec": "h264,vc1,mpeg2video", + "AudioCodec": "aac,ac3,eac3,mp2,pcm_s16le,pcm_s24le,opus,flac,vorbis" + }, + { + "Container": "wmv", + "Type": "Video", + "VideoCodec": "", + "AudioCodec": "" + }, + { + "Container": "ts,mpegts", + "Type": "Video", + "VideoCodec": "h264,hevc,vc1,mpeg2video", + "AudioCodec": "aac,ac3,eac3,mp2,pcm_s16le,pcm_s24le,opus,flac,vorbis" + }, + { + "Container": "asf", + "Type": "Video", + "VideoCodec": "", + "AudioCodec": "" + }, + { + "Container": "avi", + "Type": "Video", + "VideoCodec": "", + "AudioCodec": "aac,ac3,eac3,mp2,pcm_s16le,pcm_s24le,opus,flac,vorbis" + }, + { + "Container": "mpg", + "Type": "Video", + "VideoCodec": "", + "AudioCodec": "aac,ac3,eac3,mp2,pcm_s16le,pcm_s24le,opus,flac,vorbis" + }, + { + "Container": "mpeg", + "Type": "Video", + "VideoCodec": "", + "AudioCodec": "aac,ac3,eac3,mp2,pcm_s16le,pcm_s24le,opus,flac,vorbis" + }, + { + "Container": "mov", + "Type": "Video", + "VideoCodec": "h264", + "AudioCodec": "aac,ac3,eac3,mp2,pcm_s16le,pcm_s24le,opus,flac,vorbis" + }, + { + "Container": "opus", + "Type": "Audio" + }, + { + "Container": "webm", + "AudioCodec": "opus", + "Type": "Audio" + }, + { + "Container": "ts", + "AudioCodec": "mp3", + "Type": "Audio" + }, + { + "Container": "mp3", + "Type": "Audio" + }, + { + "Container": "aac", + "Type": "Audio" + }, + { + "Container": "m4a", + "AudioCodec": "aac", + "Type": "Audio" + }, + { + "Container": "m4b", + "AudioCodec": "aac", + "Type": "Audio" + }, + { + "Container": "mp4", + "AudioCodec": "flac", + "Type": "Audio" + }, + { + "Container": "webma", + "Type": "Audio" + }, + { + "Container": "webm", + "AudioCodec": "webma", + "Type": "Audio" + }, + { + "Container": "wav", + "Type": "Audio" + }, + { + "Container": "hls", + "Type": "Video", + "VideoCodec": "h264,hevc", + "AudioCodec": "aac,ac3,eac3,mp2" + } + ], + "TranscodingProfiles": [ + { + "Container": "ts", + "Type": "Audio", + "AudioCodec": "aac", + "Context": "Streaming", + "Protocol": "hls", + "MaxAudioChannels": "6", + "MinSegments": "1", + "BreakOnNonKeyFrames": false, + "EnableAudioVbrEncoding": true + }, + { + "Container": "aac", + "Type": "Audio", + "AudioCodec": "aac", + "Context": "Streaming", + "Protocol": "http", + "MaxAudioChannels": "6" + }, + { + "Container": "mp3", + "Type": "Audio", + "AudioCodec": "mp3", + "Context": "Streaming", + "Protocol": "http", + "MaxAudioChannels": "6" + }, + { + "Container": "opus", + "Type": "Audio", + "AudioCodec": "opus", + "Context": "Streaming", + "Protocol": "http", + "MaxAudioChannels": "6" + }, + { + "Container": "wav", + "Type": "Audio", + "AudioCodec": "wav", + "Context": "Streaming", + "Protocol": "http", + "MaxAudioChannels": "6" + }, + { + "Container": "opus", + "Type": "Audio", + "AudioCodec": "opus", + "Context": "Static", + "Protocol": "http", + "MaxAudioChannels": "6" + }, + { + "Container": "mp3", + "Type": "Audio", + "AudioCodec": "mp3", + "Context": "Static", + "Protocol": "http", + "MaxAudioChannels": "6" + }, + { + "Container": "aac", + "Type": "Audio", + "AudioCodec": "aac", + "Context": "Static", + "Protocol": "http", + "MaxAudioChannels": "6" + }, + { + "Container": "wav", + "Type": "Audio", + "AudioCodec": "wav", + "Context": "Static", + "Protocol": "http", + "MaxAudioChannels": "6" + }, + { + "Container": "ts", + "Type": "Video", + "AudioCodec": "aac,ac3,eac3,mp2", + "VideoCodec": "h264,hevc", + "Context": "Streaming", + "Protocol": "hls", + "MaxAudioChannels": "6", + "MinSegments": "1", + "BreakOnNonKeyFrames": false + } + ], + "ContainerProfiles": [], + "CodecProfiles": [ + { + "Type": "VideoAudio", + "Codec": "flac", + "Conditions": [ + { + "Condition": "LessThanEqual", + "Property": "AudioChannels", + "Value": "2", + "IsRequired": false + } + ] + }, + { + "Type": "Video", + "Codec": "h264", + "Conditions": [ + { + "Condition": "NotEquals", + "Property": "IsAnamorphic", + "Value": "true", + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoProfile", + "Value": "high|main|baseline|constrained baseline", + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR", + "IsRequired": false + }, + { + "Condition": "LessThanEqual", + "Property": "VideoLevel", + "Value": "52", + "IsRequired": false + } + ] + }, + { + "Type": "Video", + "Container": "-mp4,ts", + "Codec": "hevc", + "Conditions": [ + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR|HDR10|HLG", + "IsRequired": false + } + ] + }, + { + "Type": "Video", + "Codec": "hevc", + "Conditions": [ + { + "Condition": "NotEquals", + "Property": "IsAnamorphic", + "Value": "true", + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoProfile", + "Value": "main|main 10", + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR|HDR10|HLG|DOVI|DOVIWithHDR10|DOVIWithHLG|DOVIWithSDR", + "IsRequired": false + }, + { + "Condition": "LessThanEqual", + "Property": "VideoLevel", + "Value": "183", + "IsRequired": false + } + ] + }, + { + "Type": "Video", + "Codec": "vp9", + "Conditions": [ + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR|HDR10|HLG", + "IsRequired": false + } + ] + }, + { + "Type": "Video", + "Codec": "av1", + "Conditions": [ + { + "Condition": "NotEquals", + "Property": "IsAnamorphic", + "Value": "true", + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoProfile", + "Value": "main", + "IsRequired": false + }, + { + "Condition": "EqualsAny", + "Property": "VideoRangeType", + "Value": "SDR|HDR10|HLG", + "IsRequired": false + }, + { + "Condition": "LessThanEqual", + "Property": "VideoLevel", + "Value": "15", + "IsRequired": false + } + ] + } + ], + "SubtitleProfiles": [], + "ResponseProfiles": [ + { + "Type": "Video", + "Container": "m4v", + "MimeType": "video/mp4" + } + ] +} diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-dvhe.05-eac3-28000k.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-dvhe.05-eac3-28000k.json new file mode 100644 index 000000000..2fdd33276 --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-dvhe.05-eac3-28000k.json @@ -0,0 +1,95 @@ +{ + "Id": "e313fd4bfdfcab326b1fea833cffd779", + "Path": "/Media/MyVideo-dovi-p5.mkv", + "Type": "Default", + "Container": "mkv", + "Size": 199246498, + "Name": "MyVideo-dovi-p5", + "IsRemote": false, + "ETag": "3c932ee1cd94e3fecebcc3fac15053e9", + "RunTimeTicks": 562000000, + "SupportsTranscoding": true, + "SupportsDirectStream": false, + "SupportsDirectPlay": true, + "SupportsProbing": true, + "VideoType": "VideoFile", + "MediaStreams": [ + { + "Codec": "hevc", + "CodecTag": "dvhe", + "Language": "und", + "DvVersionMajor": 1, + "DvVersionMinor": 0, + "DvProfile": 5, + "DvLevel": 9, + "RpuPresentFlag": 1, + "ElPresentFlag": 0, + "BlPresentFlag": 1, + "DvBlSignalCompatibilityId": 0, + "TimeBase": "1/60000", + "VideoRange": "HDR", + "VideoRangeType": "DOVI", + "VideoDoViTitle": "Dolby Vision Profile 5", + "AudioSpatialFormat": "None", + "DisplayTitle": "4K HEVC Dolby Vision Profile 5", + "IsInterlaced": false, + "IsAVC": false, + "BitRate": 27713921, + "BitDepth": 10, + "RefFrames": 1, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Height": 2160, + "Width": 3840, + "AverageFrameRate": 60, + "RealFrameRate": 60, + "ReferenceFrameRate": 60, + "Profile": "Main 10", + "Type": "Video", + "AspectRatio": "16:9", + "Index": 0, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "PixelFormat": "yuv420p10le", + "Level": 153, + "IsAnamorphic": false + }, + { + "Codec": "eac3", + "CodecTag": "ec-3", + "Language": "und", + "TimeBase": "1/48000", + "Title": "sound handler", + "VideoRange": "Unknown", + "VideoRangeType": "Unknown", + "AudioSpatialFormat": "DolbyAtmos", + "LocalizedDefault": "Default", + "LocalizedExternal": "External", + "DisplayTitle": "sound handler - Dolby Digital Plus + Dolby Atmos - 5.1 - Default", + "IsInterlaced": false, + "IsAVC": false, + "ChannelLayout": "5.1", + "BitRate": 640000, + "Channels": 6, + "SampleRate": 48000, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Profile": "Dolby Digital Plus + Dolby Atmos", + "Type": "Audio", + "Index": 1, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "Level": 0 + } + ], + "MediaAttachments": [], + "Bitrate": 28362490, + "RequiredHttpHeaders": {}, + "DefaultAudioStreamIndex": 1, + "DefaultSubtitleStreamIndex": -1, + "HasSegments": false +} diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-dvhe.08-eac3-15200k.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-dvhe.08-eac3-15200k.json new file mode 100644 index 000000000..c4197fe31 --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-dvhe.08-eac3-15200k.json @@ -0,0 +1,97 @@ +{ + "Protocol": "File", + "Id": "ac2a9824755fbeffd891b8ff2634901a", + "Path": "/Media/MyVideo-dovi-p8.mkv", + "Type": "Default", + "Container": "mkv", + "Size": 344509829, + "Name": "MyVideo-dovi-p8", + "ETag": "8ac40cacc99e4748bc9218045b38d184", + "RunTimeTicks": 1781120000, + "SupportsTranscoding": true, + "SupportsDirectStream": false, + "SupportsDirectPlay": true, + "SupportsProbing": true, + "VideoType": "VideoFile", + "MediaStreams": [ + { + "Codec": "hevc", + "CodecTag": "hev1", + "Language": "und", + "ColorSpace": "bt2020nc", + "ColorTransfer": "smpte2084", + "ColorPrimaries": "bt2020", + "DvVersionMajor": 1, + "DvVersionMinor": 0, + "DvProfile": 8, + "DvLevel": 5, + "RpuPresentFlag": 1, + "ElPresentFlag": 0, + "BlPresentFlag": 1, + "DvBlSignalCompatibilityId": 1, + "TimeBase": "1/60000", + "VideoRange": "HDR", + "VideoRangeType": "DOVIWithHDR10", + "VideoDoViTitle": "Dolby Vision Profile 8.1 (HDR10)", + "AudioSpatialFormat": "None", + "DisplayTitle": "1080p HEVC Dolby Vision Profile 8.1 (HDR10)", + "IsInterlaced": false, + "IsAVC": false, + "BitRate": 15091058, + "BitDepth": 10, + "RefFrames": 1, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Height": 1080, + "Width": 1920, + "AverageFrameRate": 59.94006, + "RealFrameRate": 59.94006, + "ReferenceFrameRate": 59.94006, + "Profile": "Main 10", + "Type": "Video", + "AspectRatio": "16:9", + "Index": 0, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "PixelFormat": "yuv420p10le", + "Level": 153, + "IsAnamorphic": false + }, + { + "Codec": "eac3", + "CodecTag": "ec-3", + "Language": "und", + "TimeBase": "1/48000", + "Title": "Bento4 Sound Handler", + "VideoRange": "Unknown", + "VideoRangeType": "Unknown", + "AudioSpatialFormat": "DolbyAtmos", + "LocalizedDefault": "Default", + "LocalizedExternal": "External", + "DisplayTitle": "Bento4 Sound Handler - Dolby Digital Plus + Dolby Atmos - 5.1 - Default", + "IsInterlaced": false, + "IsAVC": false, + "ChannelLayout": "5.1", + "BitRate": 640000, + "Channels": 6, + "SampleRate": 48000, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Profile": "Dolby Digital Plus + Dolby Atmos", + "Type": "Audio", + "Index": 1, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "Level": 0 + } + ], + "MediaAttachments": [], + "Formats": [], + "Bitrate": 15473851, + "DefaultAudioStreamIndex": 1, + "HasSegments": false +} diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-h264-ac3-srt-2600k.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-h264-ac3-srt-2600k.json new file mode 100644 index 000000000..4f6d5bf00 --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-h264-ac3-srt-2600k.json @@ -0,0 +1,71 @@ +{ + "Id": "a766d122b58e45d9492d17af77748bf5", + "Path": "/Media/MyVideo-720p.mkv", + "Container": "mkv", + "Size": 835317696, + "Name": "MyVideo-720p", + "ETag": "579a34c6d5dfb21d81539a51220b6a23", + "RunTimeTicks": 25801230336, + "SupportsTranscoding": true, + "SupportsDirectStream": true, + "SupportsDirectPlay": true, + "SupportsProbing": true, + "MediaStreams": [ + { + "Codec": "h264", + "CodecTag": "avc1", + "Language": "eng", + "TimeBase": "1/11988", + "VideoRange": "SDR", + "DisplayTitle": "720p H264 SDR", + "NalLengthSize": "0", + "BitRate": 2032876, + "BitDepth": 8, + "RefFrames": 1, + "IsDefault": true, + "Height": 720, + "Width": 1280, + "AverageFrameRate": 23.976, + "RealFrameRate": 23.976, + "Profile": "High", + "Type": 1, + "AspectRatio": "16:9", + "PixelFormat": "yuv420p", + "Level": 41 + }, + { + "Codec": "ac3", + "CodecTag": "ac-3", + "Language": "eng", + "TimeBase": "1/48000", + "DisplayTitle": "En - Dolby Digital - 5.1 - Default", + "ChannelLayout": "5.1", + "BitRate": 384000, + "Channels": 6, + "SampleRate": 48000, + "IsDefault": true, + "Index": 1, + "Score": 202 + }, + { + "Codec": "srt", + "Language": "eng", + "TimeBase": "1/1000000", + "localizedUndefined": "Undefined", + "localizedDefault": "Default", + "localizedForced": "Forced", + "DisplayTitle": "En - Default", + "BitRate": 92, + "IsDefault": true, + "Type": 2, + "Index": 2, + "Score": 6421, + "IsExternal": true, + "IsTextSubtitleStream": true, + "SupportsExternalStream": true + } + ], + "Bitrate": 2590008, + "DefaultAudioStreamIndex": 1, + "DefaultSubtitleStreamIndex": 2 +} diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-h264-hi10p-aac-5000k-brokenfps.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-h264-hi10p-aac-5000k-brokenfps.json new file mode 100644 index 000000000..b2dda6c5d --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-h264-hi10p-aac-5000k-brokenfps.json @@ -0,0 +1,82 @@ +{ + "Protocol": "File", + "Id": "a6e78000340509437325708e41b9e3bb", + "Path": "/Media/hi10p.mkv", + "Type": "Default", + "Container": "mkv", + "Size": 58211635, + "Name": "MyVideo-hi10p-brokenfps", + "IsRemote": false, + "ETag": "60c03cb8a315fb6538439d3bb7e6944b", + "RunTimeTicks": 920115000, + "SupportsTranscoding": true, + "SupportsDirectStream": true, + "SupportsDirectPlay": true, + "VideoType": "VideoFile", + "MediaStreams": [ + { + "Codec": "h264", + "TimeBase": "1/1000", + "VideoRange": "SDR", + "VideoRangeType": "SDR", + "AudioSpatialFormat": "None", + "DisplayTitle": "720p H264 SDR", + "NalLengthSize": "4", + "IsInterlaced": false, + "IsAVC": true, + "BitRate": 5075104, + "BitDepth": 10, + "RefFrames": 1, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Height": 720, + "Width": 1280, + "AverageFrameRate": 1000, + "RealFrameRate": 23.976025, + "ReferenceFrameRate": 23.976025, + "Profile": "High 10", + "Type": "Video", + "AspectRatio": "16:9", + "Index": 0, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "PixelFormat": "yuv420p10le", + "Level": 51, + "IsAnamorphic": false + }, + { + "Codec": "aac", + "TimeBase": "1/1000", + "VideoRange": "Unknown", + "VideoRangeType": "Unknown", + "AudioSpatialFormat": "None", + "LocalizedDefault": "Default", + "LocalizedExternal": "External", + "DisplayTitle": "AAC - Stereo - Default", + "IsInterlaced": false, + "IsAVC": false, + "ChannelLayout": "stereo", + "BitRate": 192000, + "Channels": 2, + "SampleRate": 48000, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Profile": "LC", + "Type": "Audio", + "Index": 1, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "Level": 0 + } + ], + "MediaAttachments": [], + "Formats": [], + "Bitrate": 5061248, + "DefaultAudioStreamIndex": 1, + "DefaultSubtitleStreamIndex": -1, + "HasSegments": false +} diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-dvh1.05-eac3-15200k.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-dvh1.05-eac3-15200k.json new file mode 100644 index 000000000..96e3caffc --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-dvh1.05-eac3-15200k.json @@ -0,0 +1,94 @@ +{ + "Id": "a5365160a83cb0c518cc1c9ead31dbc7", + "Path": "/Media/MyVideo-dovi-p5.mp4", + "Type": "Default", + "Container": "mp4", + "Size": 345485021, + "Name": "MyVideo-dovi-p5", + "IsRemote": false, + "ETag": "a1aa7e722b9af5125b7387d0f58d463e", + "RunTimeTicks": 1781120000, + "SupportsTranscoding": true, + "SupportsDirectStream": true, + "SupportsDirectPlay": true, + "SupportsProbing": true, + "VideoType": "VideoFile", + "MediaStreams": [ + { + "Codec": "hevc", + "CodecTag": "dvh1", + "Language": "und", + "DvVersionMajor": 1, + "DvVersionMinor": 0, + "DvProfile": 5, + "DvLevel": 5, + "RpuPresentFlag": 1, + "ElPresentFlag": 0, + "BlPresentFlag": 1, + "DvBlSignalCompatibilityId": 0, + "TimeBase": "1/60000", + "VideoRange": "HDR", + "VideoRangeType": "DOVI", + "VideoDoViTitle": "Dolby Vision Profile 5", + "AudioSpatialFormat": "None", + "DisplayTitle": "1080p HEVC Dolby Vision Profile 5", + "IsInterlaced": false, + "IsAVC": false, + "BitRate": 15135631, + "BitDepth": 10, + "RefFrames": 1, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Height": 1080, + "Width": 1920, + "AverageFrameRate": 59.94006, + "RealFrameRate": 59.94006, + "ReferenceFrameRate": 59.94006, + "Profile": "Main 10", + "Type": "Video", + "AspectRatio": "16:9", + "Index": 0, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "PixelFormat": "yuv420p10le", + "Level": 153, + "IsAnamorphic": false + }, + { + "Codec": "eac3", + "CodecTag": "ec-3", + "Language": "und", + "TimeBase": "1/48000", + "Title": "Bento4 Sound Handler", + "VideoRange": "Unknown", + "VideoRangeType": "Unknown", + "AudioSpatialFormat": "DolbyAtmos", + "LocalizedDefault": "Default", + "LocalizedExternal": "External", + "DisplayTitle": "Bento4 Sound Handler - Dolby Digital Plus + Dolby Atmos - 5.1 - Default", + "IsInterlaced": false, + "IsAVC": false, + "ChannelLayout": "5.1", + "BitRate": 640000, + "Channels": 6, + "SampleRate": 48000, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Profile": "Dolby Digital Plus + Dolby Atmos", + "Type": "Audio", + "Index": 1, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "Level": 0 + } + ], + "MediaAttachments": [], + "Bitrate": 15517652, + "DefaultAudioStreamIndex": 1, + "DefaultSubtitleStreamIndex": -1, + "HasSegments": false +} diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-dvhe.08-eac3-15200k.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-dvhe.08-eac3-15200k.json new file mode 100644 index 000000000..6f77a8805 --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-dvhe.08-eac3-15200k.json @@ -0,0 +1,97 @@ +{ + "Protocol": "File", + "Id": "ac2a9824755fbeffd891b8ff2634901a", + "Path": "/Media/MyVideo-dovi-p8.mp4", + "Type": "Default", + "Container": "mp4", + "Size": 344509829, + "Name": "MyVideo-dovi-p8", + "ETag": "8ac40cacc99e4748bc9218045b38d184", + "RunTimeTicks": 1781120000, + "SupportsTranscoding": true, + "SupportsDirectStream": false, + "SupportsDirectPlay": true, + "SupportsProbing": true, + "VideoType": "VideoFile", + "MediaStreams": [ + { + "Codec": "hevc", + "CodecTag": "hev1", + "Language": "und", + "ColorSpace": "bt2020nc", + "ColorTransfer": "smpte2084", + "ColorPrimaries": "bt2020", + "DvVersionMajor": 1, + "DvVersionMinor": 0, + "DvProfile": 8, + "DvLevel": 5, + "RpuPresentFlag": 1, + "ElPresentFlag": 0, + "BlPresentFlag": 1, + "DvBlSignalCompatibilityId": 1, + "TimeBase": "1/60000", + "VideoRange": "HDR", + "VideoRangeType": "DOVIWithHDR10", + "VideoDoViTitle": "Dolby Vision Profile 8.1 (HDR10)", + "AudioSpatialFormat": "None", + "DisplayTitle": "1080p HEVC Dolby Vision Profile 8.1 (HDR10)", + "IsInterlaced": false, + "IsAVC": false, + "BitRate": 15091058, + "BitDepth": 10, + "RefFrames": 1, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Height": 1080, + "Width": 1920, + "AverageFrameRate": 59.94006, + "RealFrameRate": 59.94006, + "ReferenceFrameRate": 59.94006, + "Profile": "Main 10", + "Type": "Video", + "AspectRatio": "16:9", + "Index": 0, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "PixelFormat": "yuv420p10le", + "Level": 153, + "IsAnamorphic": false + }, + { + "Codec": "eac3", + "CodecTag": "ec-3", + "Language": "und", + "TimeBase": "1/48000", + "Title": "Bento4 Sound Handler", + "VideoRange": "Unknown", + "VideoRangeType": "Unknown", + "AudioSpatialFormat": "DolbyAtmos", + "LocalizedDefault": "Default", + "LocalizedExternal": "External", + "DisplayTitle": "Bento4 Sound Handler - Dolby Digital Plus + Dolby Atmos - 5.1 - Default", + "IsInterlaced": false, + "IsAVC": false, + "ChannelLayout": "5.1", + "BitRate": 640000, + "Channels": 6, + "SampleRate": 48000, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Profile": "Dolby Digital Plus + Dolby Atmos", + "Type": "Audio", + "Index": 1, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "Level": 0 + } + ], + "MediaAttachments": [], + "Formats": [], + "Bitrate": 15473851, + "DefaultAudioStreamIndex": 1, + "HasSegments": false +} diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-ac3-aac-mp3-srt-2600k.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-ac3-aac-mp3-srt-2600k.json new file mode 100644 index 000000000..2e05e70d6 --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-ac3-aac-mp3-srt-2600k.json @@ -0,0 +1,100 @@ +{ + "Id": "a766d122b58e45d9492d17af77748bf5", + "Path": "/Media/MyVideo-720p.mp4", + "Container": "mov,mp4,m4a,3gp,3g2,mj2", + "Size": 835317696, + "Name": "MyVideo-720p", + "ETag": "579a34c6d5dfb21d81539a51220b6a23", + "RunTimeTicks": 25801230336, + "SupportsTranscoding": true, + "SupportsDirectStream": true, + "SupportsDirectPlay": true, + "SupportsProbing": true, + "MediaStreams": [ + { + "Codec": "h264", + "CodecTag": "avc1", + "Language": "eng", + "TimeBase": "1/11988", + "VideoRange": "SDR", + "DisplayTitle": "720p H264 SDR", + "NalLengthSize": "0", + "BitRate": 2032876, + "BitDepth": 8, + "RefFrames": 1, + "IsDefault": true, + "Height": 720, + "Width": 1280, + "AverageFrameRate": 23.976, + "RealFrameRate": 23.976, + "Profile": "High", + "Type": 1, + "AspectRatio": "16:9", + "PixelFormat": "yuv420p", + "Level": 41 + }, + { + "Codec": "ac3", + "CodecTag": "ac-3", + "Language": "eng", + "TimeBase": "1/48000", + "DisplayTitle": "En - Dolby Digital - 5.1 - Default", + "ChannelLayout": "5.1", + "BitRate": 384000, + "Channels": 6, + "SampleRate": 48000, + "IsDefault": true, + "Index": 1, + "Score": 202 + }, + { + "Codec": "aac", + "CodecTag": "mp4a", + "Language": "eng", + "TimeBase": "1/48000", + "DisplayTitle": "En - AAC - Stereo", + "ChannelLayout": "stereo", + "BitRate": 164741, + "Channels": 2, + "SampleRate": 48000, + "IsDefault": false, + "Profile": "LC", + "Index": 2, + "Score": 203 + }, + { + "Codec": "mp3", + "Language": "eng", + "TimeBase": "1/48000", + "DisplayTitle": "En - MP3 - Stereo", + "ChannelLayout": "stereo", + "BitRate": 164741, + "Channels": 2, + "SampleRate": 48000, + "IsDefault": false, + "Index": 3, + "Score": 203 + }, + { + "Codec": "srt", + "Language": "eng", + "TimeBase": "1/1000000", + "localizedUndefined": "Undefined", + "localizedDefault": "Default", + "localizedForced": "Forced", + "DisplayTitle": "En - Default", + "BitRate": 92, + "IsDefault": true, + "Type": 2, + "Index": 4, + "Score": 6421, + "IsExternal": true, + "IsTextSubtitleStream": true, + "SupportsExternalStream": true, + "Path": "/Media/MyVideo-WEBDL-2160p.default.eng.srt" + } + ], + "Bitrate": 2590008, + "DefaultAudioStreamIndex": 1, + "DefaultSubtitleStreamIndex": 4 +} diff --git a/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-hi10p-aac-5000k.json b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-hi10p-aac-5000k.json new file mode 100644 index 000000000..1296bece5 --- /dev/null +++ b/tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-hi10p-aac-5000k.json @@ -0,0 +1,86 @@ +{ + "Protocol": "File", + "Id": "a6e78000340509437325708e41b9e3bb", + "Path": "/Media/hi10p.mp4", + "Type": "Default", + "Container": "mov", + "Size": 58211635, + "Name": "MyVideo-hi10p", + "IsRemote": false, + "ETag": "8ad487e37ce9578122bbd8c42be2a392", + "RunTimeTicks": 920115000, + "SupportsTranscoding": true, + "SupportsDirectStream": true, + "SupportsDirectPlay": true, + "VideoType": "VideoFile", + "MediaStreams": [ + { + "Codec": "h264", + "CodecTag": "avc1", + "Language": "und", + "TimeBase": "1/16000", + "VideoRange": "SDR", + "VideoRangeType": "SDR", + "AudioSpatialFormat": "None", + "DisplayTitle": "720p H264 SDR", + "NalLengthSize": "4", + "IsInterlaced": false, + "IsAVC": true, + "BitRate": 4820299, + "BitDepth": 10, + "RefFrames": 1, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Height": 720, + "Width": 1280, + "AverageFrameRate": 24.007952, + "RealFrameRate": 23.976025, + "ReferenceFrameRate": 24.007952, + "Profile": "High 10", + "Type": "Video", + "AspectRatio": "16:9", + "Index": 0, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "PixelFormat": "yuv420p10le", + "Level": 51, + "IsAnamorphic": false + }, + { + "Codec": "aac", + "CodecTag": "mp4a", + "Language": "und", + "TimeBase": "1/48000", + "VideoRange": "Unknown", + "VideoRangeType": "Unknown", + "AudioSpatialFormat": "None", + "LocalizedDefault": "Default", + "LocalizedExternal": "External", + "DisplayTitle": "AAC - Stereo - Default", + "IsInterlaced": false, + "IsAVC": false, + "ChannelLayout": "stereo", + "BitRate": 257358, + "Channels": 2, + "SampleRate": 48000, + "IsDefault": true, + "IsForced": false, + "IsHearingImpaired": false, + "Profile": "LC", + "Type": "Audio", + "Index": 1, + "IsExternal": false, + "IsTextSubtitleStream": false, + "SupportsExternalStream": false, + "Level": 0 + } + ], + "MediaAttachments": [], + "Formats": [], + "Bitrate": 5061248, + "DefaultAudioStreamIndex": 1, + "DefaultSubtitleStreamIndex": -1, + "HasSegments": false +} diff --git a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs index 183ec8984..6b1398695 100644 --- a/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs +++ b/tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs @@ -25,8 +25,8 @@ namespace Jellyfin.Naming.Tests.Video files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); - Assert.Single(result.Where(v => v.ExtraType is null)); - Assert.Single(result.Where(v => v.ExtraType is not null)); + Assert.Single(result, v => v.ExtraType is null); + Assert.Single(result, v => v.ExtraType is not null); } [Fact] @@ -44,8 +44,8 @@ namespace Jellyfin.Naming.Tests.Video files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), _namingOptions).ToList(); - Assert.Single(result.Where(v => v.ExtraType is null)); - Assert.Single(result.Where(v => v.ExtraType is not null)); + Assert.Single(result, v => v.ExtraType is null); + Assert.Single(result, v => v.ExtraType is not null); Assert.Equal(2, result[0].AlternateVersions.Count); } @@ -357,6 +357,45 @@ namespace Jellyfin.Naming.Tests.Video } [Fact] + public void TestMultiVersion13() + { + var files = new[] + { + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - Theatrical Release.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - Directors Cut.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 2160p.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p Directors Cut.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 2160p Remux.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p Theatrical Release.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 720p.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p Remux.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 720p Directors Cut.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p High Bitrate.mkv", + "/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016).mkv", + }; + + var result = VideoListResolver.Resolve( + files.Select(i => VideoResolver.Resolve(i, false, _namingOptions)).OfType<VideoFileInfo>().ToList(), + _namingOptions).ToList(); + + Assert.Single(result); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016).mkv", result[0].Files[0].Path); + Assert.Equal(11, result[0].AlternateVersions.Count); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 2160p.mkv", result[0].AlternateVersions[0].Path); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 2160p Remux.mkv", result[0].AlternateVersions[1].Path); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p.mkv", result[0].AlternateVersions[2].Path); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p Directors Cut.mkv", result[0].AlternateVersions[3].Path); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p High Bitrate.mkv", result[0].AlternateVersions[4].Path); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p Remux.mkv", result[0].AlternateVersions[5].Path); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 1080p Theatrical Release.mkv", result[0].AlternateVersions[6].Path); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 720p.mkv", result[0].AlternateVersions[7].Path); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - 720p Directors Cut.mkv", result[0].AlternateVersions[8].Path); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - Directors Cut.mkv", result[0].AlternateVersions[9].Path); + Assert.Equal("/movies/X-Men Apocalypse (2016)/X-Men Apocalypse (2016) - Theatrical Release.mkv", result[0].AlternateVersions[10].Path); + } + + [Fact] public void Resolve_GivenFolderNameWithBracketsAndHyphens_GroupsBasedOnFolderName() { var files = new[] diff --git a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs index 5dd3eb8ab..0c7d2487c 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs @@ -580,6 +580,7 @@ namespace Jellyfin.Providers.Tests.Manager CallBase = true }; item.Setup(m => m.IsSaveLocalMetadataEnabled()).Returns(false); + item.Setup(m => m.GetInternalMetadataPath()).Returns(string.Empty); var path = validPaths ? _testDataImagePath.Format : "invalid path {0}"; for (int i = 0; i < count; i++) diff --git a/tests/Jellyfin.Providers.Tests/Manager/ProviderManagerTests.cs b/tests/Jellyfin.Providers.Tests/Manager/ProviderManagerTests.cs index cced2b1e2..c227883b5 100644 --- a/tests/Jellyfin.Providers.Tests/Manager/ProviderManagerTests.cs +++ b/tests/Jellyfin.Providers.Tests/Manager/ProviderManagerTests.cs @@ -574,7 +574,8 @@ namespace Jellyfin.Providers.Tests.Manager libraryManager.Object, baseItemManager!, Mock.Of<ILyricManager>(), - Mock.Of<IMemoryCache>()); + Mock.Of<IMemoryCache>(), + Mock.Of<IMediaSegmentManager>()); return providerManager; } diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/SessionControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/SessionControllerTests.cs deleted file mode 100644 index c267d3dd3..000000000 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/SessionControllerTests.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Net; -using System.Threading.Tasks; -using Xunit; - -namespace Jellyfin.Server.Integration.Tests.Controllers; - -public class SessionControllerTests : IClassFixture<JellyfinApplicationFactory> -{ - private readonly JellyfinApplicationFactory _factory; - private static string? _accessToken; - - public SessionControllerTests(JellyfinApplicationFactory factory) - { - _factory = factory; - } - - [Fact] - public async Task GetSessions_NonExistentUserId_NotFound() - { - var client = _factory.CreateClient(); - client.DefaultRequestHeaders.AddAuthHeader(_accessToken ??= await AuthHelper.CompleteStartupAsync(client)); - - using var response = await client.GetAsync($"Sessions?controllableByUserId={Guid.NewGuid()}"); - Assert.Equal(HttpStatusCode.NotFound, response.StatusCode); - } -} diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs index 3721d1f7a..12d6e1934 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs @@ -157,7 +157,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers _parser.Fetch(result, "Test Data/Sonarr-Thumb.nfo", CancellationToken.None); - Assert.Single(result.RemoteImages.Where(x => x.Type == ImageType.Primary)); + Assert.Single(result.RemoteImages, x => x.Type == ImageType.Primary); Assert.Equal("https://artworks.thetvdb.com/banners/episodes/359095/7081317.jpg", result.RemoteImages.First(x => x.Type == ImageType.Primary).Url); } diff --git a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs index 20a8f6152..b9833c225 100644 --- a/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs +++ b/tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs @@ -220,7 +220,7 @@ namespace Jellyfin.XbmcMetadata.Tests.Parsers _parser.Fetch(result, "Test Data/Fanart.nfo", CancellationToken.None); - Assert.Single(result.RemoteImages.Where(x => x.Type == ImageType.Backdrop)); + Assert.Single(result.RemoteImages, x => x.Type == ImageType.Backdrop); Assert.Equal("https://assets.fanart.tv/fanart/movies/141052/moviebackground/justice-league-5a5332c7b5e77.jpg", result.RemoteImages.First(x => x.Type == ImageType.Backdrop).Url); } |
