Răsfoiți Sursa

Merge pull request #12639 from gnattu/more-streambuilder-test

Cody Robibero 8 luni în urmă
părinte
comite
93b40b04cb

+ 6 - 4
MediaBrowser.Model/Dlna/StreamBuilder.cs

@@ -19,8 +19,10 @@ namespace MediaBrowser.Model.Dlna
     {
         // Aliases
         internal const TranscodeReason ContainerReasons = TranscodeReason.ContainerNotSupported | TranscodeReason.ContainerBitrateExceedsLimit;
-        internal const TranscodeReason AudioReasons = TranscodeReason.AudioCodecNotSupported | TranscodeReason.AudioBitrateNotSupported | TranscodeReason.AudioChannelsNotSupported | TranscodeReason.AudioProfileNotSupported | TranscodeReason.AudioSampleRateNotSupported | TranscodeReason.SecondaryAudioNotSupported | TranscodeReason.AudioBitDepthNotSupported | TranscodeReason.AudioIsExternal;
-        internal const TranscodeReason VideoReasons = TranscodeReason.VideoCodecNotSupported | TranscodeReason.VideoResolutionNotSupported | TranscodeReason.AnamorphicVideoNotSupported | TranscodeReason.InterlacedVideoNotSupported | TranscodeReason.VideoBitDepthNotSupported | TranscodeReason.VideoBitrateNotSupported | TranscodeReason.VideoFramerateNotSupported | TranscodeReason.VideoLevelNotSupported | TranscodeReason.RefFramesNotSupported | TranscodeReason.VideoRangeTypeNotSupported | TranscodeReason.VideoProfileNotSupported;
+        internal const TranscodeReason AudioCodecReasons = TranscodeReason.AudioBitrateNotSupported | TranscodeReason.AudioChannelsNotSupported | TranscodeReason.AudioProfileNotSupported | TranscodeReason.AudioSampleRateNotSupported | TranscodeReason.SecondaryAudioNotSupported | TranscodeReason.AudioBitDepthNotSupported | TranscodeReason.AudioIsExternal;
+        internal const TranscodeReason AudioReasons = TranscodeReason.AudioCodecNotSupported | AudioCodecReasons;
+        internal const TranscodeReason VideoCodecReasons = TranscodeReason.VideoResolutionNotSupported | TranscodeReason.AnamorphicVideoNotSupported | TranscodeReason.InterlacedVideoNotSupported | TranscodeReason.VideoBitDepthNotSupported | TranscodeReason.VideoBitrateNotSupported | TranscodeReason.VideoFramerateNotSupported | TranscodeReason.VideoLevelNotSupported | TranscodeReason.RefFramesNotSupported | TranscodeReason.VideoRangeTypeNotSupported | TranscodeReason.VideoProfileNotSupported;
+        internal const TranscodeReason VideoReasons = TranscodeReason.VideoCodecNotSupported | VideoCodecReasons;
         internal const TranscodeReason DirectStreamReasons = AudioReasons | TranscodeReason.ContainerNotSupported | TranscodeReason.VideoCodecTagNotSupported;
 
         private readonly ILogger _logger;
@@ -1314,7 +1316,7 @@ namespace MediaBrowser.Model.Dlna
                 }
             }
 
-            var rankings = new[] { VideoReasons, AudioReasons, ContainerReasons };
+            var rankings = new[] { TranscodeReason.VideoCodecNotSupported, VideoCodecReasons, TranscodeReason.AudioCodecNotSupported, AudioCodecReasons, ContainerReasons };
             var rank = (ref TranscodeReason a) =>
                 {
                     var index = 1;
@@ -1417,7 +1419,7 @@ namespace MediaBrowser.Model.Dlna
 
             var failureReasons = analyzedProfiles[false]
                 .Select(analysis => analysis.Result)
-                .Where(result => !containerSupported || (result.TranscodeReason & TranscodeReason.ContainerNotSupported) == 0)
+                .Where(result => !containerSupported || !result.TranscodeReason.HasFlag(TranscodeReason.ContainerNotSupported))
                 .FirstOrDefault().TranscodeReason;
             if (failureReasons == 0)
             {

+ 124 - 96
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,34 @@ 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")]
@@ -331,7 +358,7 @@ namespace Jellyfin.Model.Tests
         {
             if (string.IsNullOrEmpty(transcodeProtocol))
             {
-                transcodeProtocol = playMethod == PlayMethod.DirectStream ? "http" : "HLS.ts";
+                transcodeProtocol = "HLS.ts";
             }
 
             var builder = GetStreamBuilder();
@@ -380,7 +407,7 @@ namespace Jellyfin.Model.Tests
                     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);
@@ -412,7 +439,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,
@@ -550,6 +577,7 @@ namespace Jellyfin.Model.Tests
                 Profile = dp,
                 AllowAudioStreamCopy = true,
                 AllowVideoStreamCopy = true,
+                EnableDirectStream = false // This is disabled in server
             };
         }
 

+ 151 - 238
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"
+        }
+    ]
 }

+ 188 - 257
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"

+ 160 - 162
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"
+        }
+    ]
 }

+ 355 - 0
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"
+        }
+    ]
+}

+ 95 - 0
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
+}

+ 97 - 0
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
+}

+ 71 - 0
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
+}

+ 82 - 0
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
+}

+ 94 - 0
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
+}

+ 97 - 0
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
+}

+ 86 - 0
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
+}