aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorJPVenson <github@jpb.email>2024-10-08 09:34:34 +0000
committerJPVenson <github@jpb.email>2024-10-08 09:34:34 +0000
commitd3a3d9fce3b891eb0be274a0cdc45a989e557652 (patch)
treebd232ef477c259f1fafa204016f6efd4dcb8691f /tests
parentee1bdf4e222125ed7382165fd7e09599ca4bd4aa (diff)
parentaaf20592bb0bbdf4f0f0d99fed091758e68ae850 (diff)
Merge remote-tracking branch 'jellyfinorigin/master' into feature/EFUserData
Diffstat (limited to 'tests')
-rw-r--r--tests/Jellyfin.Controller.Tests/Entities/BaseItemTests.cs29
-rw-r--r--tests/Jellyfin.Extensions.Tests/FormattingStreamWriterTests.cs23
-rw-r--r--tests/Jellyfin.Extensions.Tests/Json/Converters/JsonCommaDelimitedArrayTests.cs16
-rw-r--r--tests/Jellyfin.Model.Tests/Dlna/ContainerHelperTests.cs83
-rw-r--r--tests/Jellyfin.Model.Tests/Dlna/ContainerProfileTests.cs19
-rw-r--r--tests/Jellyfin.Model.Tests/Dlna/StreamBuilderTests.cs244
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Chrome.json389
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-Firefox.json445
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-SafariNext.json322
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/DeviceProfile-WebOS-23.json355
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-dvhe.05-eac3-28000k.json95
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-dvhe.08-eac3-15200k.json97
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-h264-ac3-srt-2600k.json71
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mkv-h264-hi10p-aac-5000k-brokenfps.json82
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-dvh1.05-eac3-15200k.json94
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-dvhe.08-eac3-15200k.json97
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-ac3-aac-mp3-srt-2600k.json100
-rw-r--r--tests/Jellyfin.Model.Tests/Test Data/MediaSourceInfo-mp4-h264-hi10p-aac-5000k.json86
-rw-r--r--tests/Jellyfin.Naming.Tests/Video/MultiVersionTests.cs47
-rw-r--r--tests/Jellyfin.Providers.Tests/Manager/ItemImageProviderTests.cs1
-rw-r--r--tests/Jellyfin.Providers.Tests/Manager/ProviderManagerTests.cs3
-rw-r--r--tests/Jellyfin.Server.Integration.Tests/Controllers/SessionControllerTests.cs27
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Parsers/EpisodeNfoProviderTests.cs2
-rw-r--r--tests/Jellyfin.XbmcMetadata.Tests/Parsers/MovieNfoParserTests.cs2
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);
}