ソースを参照

Add remuxing support for VP9

Add VP9 as a valid HLS format to enable remuxing. This is useful when audio processing is required, but the VP9 video can be passed as-is to avoid unnecessary video transcoding.

No VP9 encoder is enabled and should not be enabled. AV1 and HEVC should be preferred over VP9 if video transcoding is required.

Signed-off-by: gnattu <gnattuoc@me.com>
gnattu 1 年間 前
コミット
5df171b3f9

+ 15 - 0
Jellyfin.Api/Helpers/DynamicHlsHelper.cs

@@ -714,6 +714,21 @@ public class DynamicHlsHelper
             return HlsCodecStringHelpers.GetAv1String(profile, level, false, bitDepth);
         }
 
+        // VP9 HLS is for video remuxing only, everything is probed from the original video
+        if (string.Equals(codec, "vp9", StringComparison.OrdinalIgnoreCase))
+        {
+            var width = state.VideoStream.Width ?? 0;
+            var height = state.VideoStream.Height ?? 0;
+            var framerate = state.VideoStream.AverageFrameRate ?? 30;
+            var bitDepth = state.VideoStream.BitDepth ?? 8;
+            return HlsCodecStringHelpers.GetVp9String(
+                width,
+                height,
+                state.VideoStream.PixelFormat,
+                framerate,
+                bitDepth);
+        }
+
         return string.Empty;
     }
 

+ 62 - 0
Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs

@@ -182,6 +182,68 @@ public static class HlsCodecStringHelpers
         return result.ToString();
     }
 
+    /// <summary>
+    /// Gets a VP9 codec string.
+    /// </summary>
+    /// <param name="width">Video width.</param>
+    /// <param name="height">Video height.</param>
+    /// <param name="pixelFormat">Video pixel format.</param>
+    /// <param name="framerate">Video framerate.</param>
+    /// <param name="bitDepth">Video bitDepth.</param>
+    /// <returns>The VP9 codec string.</returns>
+    public static string GetVp9String(int width, int height, string pixelFormat, float framerate, int bitDepth)
+    {
+        // refer: https://www.webmproject.org/vp9/mp4/
+        StringBuilder result = new StringBuilder("vp09", 13);
+
+        var profileString = pixelFormat switch
+        {
+            "yuv420p" => "00",
+            "yuvj420p" => "00",
+            "yuv422p" => "01",
+            "yuv444p" => "01",
+            "yuv420p10le" => "02",
+            "yuv420p12le" => "02",
+            "yuv422p10le" => "03",
+            "yuv422p12le" => "03",
+            "yuv444p10le" => "03",
+            "yuv444p12le" => "03",
+            _ => "00"
+        };
+
+        var lumaPictureSize = width * height;
+        var lumaSampleRate = lumaPictureSize * framerate;
+        var levelString = lumaPictureSize switch
+        {
+            <= 0 => "00",
+            <= 36864 => "10",
+            <= 73728 => "11",
+            <= 122880 => "20",
+            <= 245760 => "21",
+            <= 552960 => "30",
+            <= 983040 => "31",
+            <= 2228224 => lumaSampleRate <= 83558400 ? "40" : "41",
+            <= 8912896 => lumaSampleRate <= 311951360 ? "50" : (lumaSampleRate <= 588251136 ? "51" : "52"),
+            <= 35651584 => lumaSampleRate <= 1176502272 ? "60" : (lumaSampleRate <= 4706009088 ? "61" : "62"),
+            _ => "00" // This should not happen
+        };
+
+        if (bitDepth != 8
+            && bitDepth != 10
+            && bitDepth != 12)
+        {
+            // Default to 8 bits
+            bitDepth = 8;
+        }
+
+        result.Append('.').Append(profileString).Append('.').Append(levelString);
+        var bitDepthD2 = bitDepth.ToString("D2", CultureInfo.InvariantCulture);
+        result.Append('.')
+            .Append(bitDepthD2);
+
+        return result.ToString();
+    }
+
     /// <summary>
     /// Gets an AV1 codec string.
     /// </summary>

+ 1 - 1
MediaBrowser.Model/Dlna/StreamBuilder.cs

@@ -25,7 +25,7 @@ namespace MediaBrowser.Model.Dlna
 
         private readonly ILogger _logger;
         private readonly ITranscoderSupport _transcoderSupport;
-        private static readonly string[] _supportedHlsVideoCodecs = new string[] { "h264", "hevc", "av1" };
+        private static readonly string[] _supportedHlsVideoCodecs = new string[] { "h264", "hevc", "vp9", "av1" };
         private static readonly string[] _supportedHlsAudioCodecsTs = new string[] { "aac", "ac3", "eac3", "mp3" };
         private static readonly string[] _supportedHlsAudioCodecsMp4 = new string[] { "aac", "ac3", "eac3", "mp3", "alac", "flac", "opus", "dca", "truehd" };