Browse Source

Add support for OPUS and fixes for FLAC case issue in HLS

Signed-off-by: nyanmisaka <nst799610810@gmail.com>
nyanmisaka 2 years ago
parent
commit
9799136daf

+ 52 - 21
Jellyfin.Api/Helpers/DynamicHlsHelper.cs

@@ -204,6 +204,13 @@ namespace Jellyfin.Api.Helpers
 
             if (state.VideoStream != null && state.VideoRequest != null)
             {
+                // Provide a workaround for the case issue between flac and fLaC.
+                var flacWaPlaylist = ApplyFlacCaseWorkaround(state, basicPlaylist.ToString());
+                if (!String.IsNullOrEmpty(flacWaPlaylist))
+                {
+                    builder.Append(flacWaPlaylist);
+                }
+
                 var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
 
                 // Provide SDR HEVC entrance for backward compatibility.
@@ -221,26 +228,26 @@ namespace Jellyfin.Api.Helpers
                         var sdrVideoUrl = ReplaceProfile(playlistUrl, "hevc", string.Join(',', requestedVideoProfiles), "main");
                         sdrVideoUrl += "&AllowVideoStreamCopy=false";
 
-                    var sdrOutputVideoBitrate = _encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec);
-                    var sdrOutputAudioBitrate = 0;
-                    if (EncodingHelper.LosslessAudioCodecs.Contains(state.VideoRequest.AudioCodec, StringComparison.OrdinalIgnoreCase))
-                    {
-                        sdrOutputAudioBitrate = state.AudioStream.BitRate ?? 0;
-                    }
-                    else
-                    {
-                        sdrOutputAudioBitrate = _encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream, state.OutputAudioChannels) ?? 0;
-                    }
-
-                    var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate;
-                    var sdrPlaylist = AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup);
-
-                    // Provide a workaround for the case issue between flac and fLaC.
-                    flacWaPlaylist = ApplyFlacCaseWorkaround(state, sdrPlaylist.ToString());
-                    if (!string.IsNullOrEmpty(flacWaPlaylist))
-                    {
-                        builder.Append(flacWaPlaylist);
-                    }
+                        var sdrOutputVideoBitrate = _encodingHelper.GetVideoBitrateParamValue(state.VideoRequest, state.VideoStream, state.OutputVideoCodec);
+                        var sdrOutputAudioBitrate = 0;
+                        if (EncodingHelper.LosslessAudioCodecs.Contains(state.VideoRequest.AudioCodec, StringComparison.OrdinalIgnoreCase))
+                        {
+                            sdrOutputAudioBitrate = state.AudioStream.BitRate ?? 0;
+                        }
+                        else
+                        {
+                            sdrOutputAudioBitrate = _encodingHelper.GetAudioBitrateParam(state.VideoRequest, state.AudioStream, state.OutputAudioChannels) ?? 0;
+                        }
+
+                        var sdrTotalBitrate = sdrOutputAudioBitrate + sdrOutputVideoBitrate;
+                        var sdrPlaylist = AppendPlaylist(builder, state, sdrVideoUrl, sdrTotalBitrate, subtitleGroup);
+
+                        // Provide a workaround for the case issue between flac and fLaC.
+                        flacWaPlaylist = ApplyFlacCaseWorkaround(state, sdrPlaylist.ToString());
+                        if (!String.IsNullOrEmpty(flacWaPlaylist))
+                        {
+                            builder.Append(flacWaPlaylist);
+                        }
 
                         // Restore the video codec
                         state.OutputVideoCodec = "copy";
@@ -270,6 +277,13 @@ namespace Jellyfin.Api.Helpers
                     state.VideoStream.Level = originalLevel;
                     var newPlaylist = ReplacePlaylistCodecsField(basicPlaylist, playlistCodecsField, newPlaylistCodecsField);
                     builder.Append(newPlaylist);
+
+                    // Provide a workaround for the case issue between flac and fLaC.
+                    flacWaPlaylist = ApplyFlacCaseWorkaround(state, newPlaylist);
+                    if (!String.IsNullOrEmpty(flacWaPlaylist))
+                    {
+                        builder.Append(flacWaPlaylist);
+                    }
                 }
             }
 
@@ -628,6 +642,11 @@ namespace Jellyfin.Api.Helpers
                 return HlsCodecStringHelpers.GetALACString();
             }
 
+            if (string.Equals(state.ActualOutputAudioCodec, "opus", StringComparison.OrdinalIgnoreCase))
+            {
+                return HlsCodecStringHelpers.GetOPUSString();
+            }
+
             return string.Empty;
         }
 
@@ -726,7 +745,19 @@ namespace Jellyfin.Api.Helpers
             return oldPlaylist.Replace(
                 oldValue.ToString(),
                 newValue.ToString(),
-                StringComparison.OrdinalIgnoreCase);
+                StringComparison.Ordinal);
+        }
+
+        private string ApplyFlacCaseWorkaround(StreamState state, string srcPlaylist)
+        {
+            if (!string.Equals(state.ActualOutputAudioCodec, "flac", StringComparison.OrdinalIgnoreCase))
+            {
+                return string.Empty;
+            }
+
+            var newPlaylist = srcPlaylist.Replace(",flac\"", ",fLaC\"", StringComparison.Ordinal);
+
+            return newPlaylist.Contains(",fLaC\"", StringComparison.Ordinal) ? newPlaylist : string.Empty;
         }
     }
 }

+ 15 - 1
Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs

@@ -27,13 +27,18 @@ namespace Jellyfin.Api.Helpers
         /// <summary>
         /// Codec name for FLAC.
         /// </summary>
-        public const string FLAC = "fLaC";
+        public const string FLAC = "flac";
 
         /// <summary>
         /// Codec name for ALAC.
         /// </summary>
         public const string ALAC = "alac";
 
+        /// <summary>
+        /// Codec name for OPUS.
+        /// </summary>
+        public const string OPUS = "opus";
+
         /// <summary>
         /// Gets a MP3 codec string.
         /// </summary>
@@ -101,6 +106,15 @@ namespace Jellyfin.Api.Helpers
             return ALAC;
         }
 
+        /// <summary>
+        /// Gets an OPUS codec string.
+        /// </summary>
+        /// <returns>OPUS codec string.</returns>
+        public static string GetOPUSString()
+        {
+            return OPUS;
+        }
+
         /// <summary>
         /// Gets a H.264 codec string.
         /// </summary>