Explorar o código

Add MediaStream.ReferenceFrameRate for problematic video files (#12603)

Co-authored-by: Nyanmisaka <nst799610810@gmail.com>
gnattu hai 8 meses
pai
achega
5a8a19e07b

+ 1 - 1
Jellyfin.Api/Helpers/DynamicHlsHelper.cs

@@ -738,7 +738,7 @@ public class DynamicHlsHelper
         {
             var width = state.VideoStream.Width ?? 0;
             var height = state.VideoStream.Height ?? 0;
-            var framerate = state.VideoStream.AverageFrameRate ?? 30;
+            var framerate = state.VideoStream.ReferenceFrameRate ?? 30;
             var bitDepth = state.VideoStream.BitDepth ?? 8;
             return HlsCodecStringHelpers.GetVp9String(
                 width,

+ 5 - 5
MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs

@@ -1534,7 +1534,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 
             if (maxrate.HasValue && state.VideoStream is not null)
             {
-                var contentRate = state.VideoStream.AverageFrameRate ?? state.VideoStream.RealFrameRate;
+                var contentRate = state.VideoStream.ReferenceFrameRate;
 
                 if (contentRate.HasValue && contentRate.Value > maxrate.Value)
                 {
@@ -2218,7 +2218,7 @@ namespace MediaBrowser.Controller.MediaEncoding
             var requestedFramerate = request.MaxFramerate ?? request.Framerate;
             if (requestedFramerate.HasValue)
             {
-                var videoFrameRate = videoStream.AverageFrameRate ?? videoStream.RealFrameRate;
+                var videoFrameRate = videoStream.ReferenceFrameRate;
 
                 if (!videoFrameRate.HasValue || videoFrameRate.Value > requestedFramerate.Value)
                 {
@@ -3234,7 +3234,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 
         public static string GetSwDeinterlaceFilter(EncodingJobInfo state, EncodingOptions options)
         {
-            var doubleRateDeint = options.DeinterlaceDoubleRate && state.VideoStream?.AverageFrameRate <= 30;
+            var doubleRateDeint = options.DeinterlaceDoubleRate && state.VideoStream?.ReferenceFrameRate <= 30;
             return string.Format(
                 CultureInfo.InvariantCulture,
                 "{0}={1}:-1:0",
@@ -3244,7 +3244,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 
         public string GetHwDeinterlaceFilter(EncodingJobInfo state, EncodingOptions options, string hwDeintSuffix)
         {
-            var doubleRateDeint = options.DeinterlaceDoubleRate && (state.VideoStream?.AverageFrameRate ?? 60) <= 30;
+            var doubleRateDeint = options.DeinterlaceDoubleRate && (state.VideoStream?.ReferenceFrameRate ?? 60) <= 30;
             if (hwDeintSuffix.Contains("cuda", StringComparison.OrdinalIgnoreCase))
             {
                 var useBwdif = string.Equals(options.DeinterlaceMethod, "bwdif", StringComparison.OrdinalIgnoreCase)
@@ -3598,7 +3598,7 @@ namespace MediaBrowser.Controller.MediaEncoding
             var isSwEncoder = !isNvencEncoder;
             var isCuInCuOut = isNvDecoder && isNvencEncoder;
 
-            var doubleRateDeint = options.DeinterlaceDoubleRate && (state.VideoStream?.AverageFrameRate ?? 60) <= 30;
+            var doubleRateDeint = options.DeinterlaceDoubleRate && (state.VideoStream?.ReferenceFrameRate ?? 60) <= 30;
             var doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
             var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
             var doDeintH2645 = doDeintH264 || doDeintHevc;

+ 1 - 1
MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs

@@ -305,7 +305,7 @@ namespace MediaBrowser.Controller.MediaEncoding
                 if (BaseRequest.Static
                     || EncodingHelper.IsCopyCodec(OutputVideoCodec))
                 {
-                    return VideoStream is null ? null : (VideoStream.AverageFrameRate ?? VideoStream.RealFrameRate);
+                    return VideoStream?.ReferenceFrameRate;
                 }
 
                 return BaseRequest.MaxFramerate ?? BaseRequest.Framerate;

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

@@ -810,7 +810,7 @@ namespace MediaBrowser.Model.Dlna
             if (options.AllowVideoStreamCopy)
             {
                 // prefer direct copy profile
-                float videoFramerate = videoStream?.AverageFrameRate ?? videoStream?.RealFrameRate ?? 0;
+                float videoFramerate = videoStream?.ReferenceFrameRate ?? 0;
                 TransportStreamTimestamp? timestamp = videoStream is null ? TransportStreamTimestamp.None : item.Timestamp;
                 int? numAudioStreams = item.GetStreamCount(MediaStreamType.Audio);
                 int? numVideoStreams = item.GetStreamCount(MediaStreamType.Video);
@@ -875,7 +875,7 @@ namespace MediaBrowser.Model.Dlna
             playlistItem.VideoCodecs = videoCodecs;
 
             // Copy video codec options as a starting point, this applies to transcode and direct-stream
-            playlistItem.MaxFramerate = videoStream?.AverageFrameRate;
+            playlistItem.MaxFramerate = videoStream?.ReferenceFrameRate;
             var qualifier = videoStream?.Codec;
             if (videoStream?.Level is not null)
             {
@@ -949,7 +949,7 @@ namespace MediaBrowser.Model.Dlna
             double? videoLevel = videoStream?.Level;
             string? videoProfile = videoStream?.Profile;
             VideoRangeType? videoRangeType = videoStream?.VideoRangeType;
-            float videoFramerate = videoStream is null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
+            float videoFramerate = videoStream is null ? 0 : videoStream.ReferenceFrameRate ?? 0;
             bool? isAnamorphic = videoStream?.IsAnamorphic;
             bool? isInterlaced = videoStream?.IsInterlaced;
             string? videoCodecTag = videoStream?.CodecTag;
@@ -1208,7 +1208,7 @@ namespace MediaBrowser.Model.Dlna
             double? videoLevel = videoStream?.Level;
             string? videoProfile = videoStream?.Profile;
             VideoRangeType? videoRangeType = videoStream?.VideoRangeType;
-            float videoFramerate = videoStream is null ? 0 : videoStream.AverageFrameRate ?? videoStream.AverageFrameRate ?? 0;
+            float videoFramerate = videoStream is null ? 0 : videoStream.ReferenceFrameRate ?? 0;
             bool? isAnamorphic = videoStream?.IsAnamorphic;
             bool? isInterlaced = videoStream?.IsInterlaced;
             string? videoCodecTag = videoStream?.CodecTag;

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

@@ -217,7 +217,7 @@ namespace MediaBrowser.Model.Dlna
                 var stream = TargetVideoStream;
                 return MaxFramerate.HasValue && !IsDirectStream
                     ? MaxFramerate
-                    : stream is null ? null : stream.AverageFrameRate ?? stream.RealFrameRate;
+                    : stream?.ReferenceFrameRate;
             }
         }
 

+ 17 - 0
MediaBrowser.Model/Entities/MediaStream.cs

@@ -525,6 +525,23 @@ namespace MediaBrowser.Model.Entities
         /// <value>The real frame rate.</value>
         public float? RealFrameRate { get; set; }
 
+        /// <summary>
+        /// Gets the framerate used as reference.
+        /// Prefer AverageFrameRate, if that is null or an unrealistic value
+        /// then fallback to RealFrameRate.
+        /// </summary>
+        /// <value>The reference frame rate.</value>
+        public float? ReferenceFrameRate
+        {
+            get
+            {
+                // In some cases AverageFrameRate for videos will be read as 1000fps even if it is not.
+                // This is probably due to a library compatability issue.
+                // See https://github.com/jellyfin/jellyfin/pull/12603#discussion_r1748044018 for more info.
+                return AverageFrameRate < 1000 ? AverageFrameRate : RealFrameRate;
+            }
+        }
+
         /// <summary>
         /// Gets or sets the profile.
         /// </summary>

+ 1 - 1
MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs

@@ -348,7 +348,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
                     writer.WriteElementString("aspectratio", stream.AspectRatio);
                 }
 
-                var framerate = stream.AverageFrameRate ?? stream.RealFrameRate;
+                var framerate = stream.ReferenceFrameRate;
 
                 if (framerate.HasValue)
                 {