mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-04 03:27:21 -05:00 
			
		
		
		
	Add MediaStream.ReferenceFrameRate for problematic video files (#12603)
Co-authored-by: Nyanmisaka <nst799610810@gmail.com>
This commit is contained in:
		
							parent
							
								
									57452d65ef
								
							
						
					
					
						commit
						5a8a19e07b
					
				@ -738,7 +738,7 @@ public class DynamicHlsHelper
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            var width = state.VideoStream.Width ?? 0;
 | 
					            var width = state.VideoStream.Width ?? 0;
 | 
				
			||||||
            var height = state.VideoStream.Height ?? 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;
 | 
					            var bitDepth = state.VideoStream.BitDepth ?? 8;
 | 
				
			||||||
            return HlsCodecStringHelpers.GetVp9String(
 | 
					            return HlsCodecStringHelpers.GetVp9String(
 | 
				
			||||||
                width,
 | 
					                width,
 | 
				
			||||||
 | 
				
			|||||||
@ -1534,7 +1534,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (maxrate.HasValue && state.VideoStream is not null)
 | 
					            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)
 | 
					                if (contentRate.HasValue && contentRate.Value > maxrate.Value)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@ -2218,7 +2218,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
				
			|||||||
            var requestedFramerate = request.MaxFramerate ?? request.Framerate;
 | 
					            var requestedFramerate = request.MaxFramerate ?? request.Framerate;
 | 
				
			||||||
            if (requestedFramerate.HasValue)
 | 
					            if (requestedFramerate.HasValue)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var videoFrameRate = videoStream.AverageFrameRate ?? videoStream.RealFrameRate;
 | 
					                var videoFrameRate = videoStream.ReferenceFrameRate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (!videoFrameRate.HasValue || videoFrameRate.Value > requestedFramerate.Value)
 | 
					                if (!videoFrameRate.HasValue || videoFrameRate.Value > requestedFramerate.Value)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@ -3234,7 +3234,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public static string GetSwDeinterlaceFilter(EncodingJobInfo state, EncodingOptions options)
 | 
					        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(
 | 
					            return string.Format(
 | 
				
			||||||
                CultureInfo.InvariantCulture,
 | 
					                CultureInfo.InvariantCulture,
 | 
				
			||||||
                "{0}={1}:-1:0",
 | 
					                "{0}={1}:-1:0",
 | 
				
			||||||
@ -3244,7 +3244,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public string GetHwDeinterlaceFilter(EncodingJobInfo state, EncodingOptions options, string hwDeintSuffix)
 | 
					        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))
 | 
					            if (hwDeintSuffix.Contains("cuda", StringComparison.OrdinalIgnoreCase))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                var useBwdif = string.Equals(options.DeinterlaceMethod, "bwdif", StringComparison.OrdinalIgnoreCase)
 | 
					                var useBwdif = string.Equals(options.DeinterlaceMethod, "bwdif", StringComparison.OrdinalIgnoreCase)
 | 
				
			||||||
@ -3598,7 +3598,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
				
			|||||||
            var isSwEncoder = !isNvencEncoder;
 | 
					            var isSwEncoder = !isNvencEncoder;
 | 
				
			||||||
            var isCuInCuOut = isNvDecoder && 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 doDeintH264 = state.DeInterlace("h264", true) || state.DeInterlace("avc", true);
 | 
				
			||||||
            var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
 | 
					            var doDeintHevc = state.DeInterlace("h265", true) || state.DeInterlace("hevc", true);
 | 
				
			||||||
            var doDeintH2645 = doDeintH264 || doDeintHevc;
 | 
					            var doDeintH2645 = doDeintH264 || doDeintHevc;
 | 
				
			||||||
 | 
				
			|||||||
@ -305,7 +305,7 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
				
			|||||||
                if (BaseRequest.Static
 | 
					                if (BaseRequest.Static
 | 
				
			||||||
                    || EncodingHelper.IsCopyCodec(OutputVideoCodec))
 | 
					                    || EncodingHelper.IsCopyCodec(OutputVideoCodec))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    return VideoStream is null ? null : (VideoStream.AverageFrameRate ?? VideoStream.RealFrameRate);
 | 
					                    return VideoStream?.ReferenceFrameRate;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return BaseRequest.MaxFramerate ?? BaseRequest.Framerate;
 | 
					                return BaseRequest.MaxFramerate ?? BaseRequest.Framerate;
 | 
				
			||||||
 | 
				
			|||||||
@ -810,7 +810,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
            if (options.AllowVideoStreamCopy)
 | 
					            if (options.AllowVideoStreamCopy)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // prefer direct copy profile
 | 
					                // 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;
 | 
					                TransportStreamTimestamp? timestamp = videoStream is null ? TransportStreamTimestamp.None : item.Timestamp;
 | 
				
			||||||
                int? numAudioStreams = item.GetStreamCount(MediaStreamType.Audio);
 | 
					                int? numAudioStreams = item.GetStreamCount(MediaStreamType.Audio);
 | 
				
			||||||
                int? numVideoStreams = item.GetStreamCount(MediaStreamType.Video);
 | 
					                int? numVideoStreams = item.GetStreamCount(MediaStreamType.Video);
 | 
				
			||||||
@ -875,7 +875,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
            playlistItem.VideoCodecs = videoCodecs;
 | 
					            playlistItem.VideoCodecs = videoCodecs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Copy video codec options as a starting point, this applies to transcode and direct-stream
 | 
					            // 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;
 | 
					            var qualifier = videoStream?.Codec;
 | 
				
			||||||
            if (videoStream?.Level is not null)
 | 
					            if (videoStream?.Level is not null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -949,7 +949,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
            double? videoLevel = videoStream?.Level;
 | 
					            double? videoLevel = videoStream?.Level;
 | 
				
			||||||
            string? videoProfile = videoStream?.Profile;
 | 
					            string? videoProfile = videoStream?.Profile;
 | 
				
			||||||
            VideoRangeType? videoRangeType = videoStream?.VideoRangeType;
 | 
					            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? isAnamorphic = videoStream?.IsAnamorphic;
 | 
				
			||||||
            bool? isInterlaced = videoStream?.IsInterlaced;
 | 
					            bool? isInterlaced = videoStream?.IsInterlaced;
 | 
				
			||||||
            string? videoCodecTag = videoStream?.CodecTag;
 | 
					            string? videoCodecTag = videoStream?.CodecTag;
 | 
				
			||||||
@ -1208,7 +1208,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
            double? videoLevel = videoStream?.Level;
 | 
					            double? videoLevel = videoStream?.Level;
 | 
				
			||||||
            string? videoProfile = videoStream?.Profile;
 | 
					            string? videoProfile = videoStream?.Profile;
 | 
				
			||||||
            VideoRangeType? videoRangeType = videoStream?.VideoRangeType;
 | 
					            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? isAnamorphic = videoStream?.IsAnamorphic;
 | 
				
			||||||
            bool? isInterlaced = videoStream?.IsInterlaced;
 | 
					            bool? isInterlaced = videoStream?.IsInterlaced;
 | 
				
			||||||
            string? videoCodecTag = videoStream?.CodecTag;
 | 
					            string? videoCodecTag = videoStream?.CodecTag;
 | 
				
			||||||
 | 
				
			|||||||
@ -217,7 +217,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
                var stream = TargetVideoStream;
 | 
					                var stream = TargetVideoStream;
 | 
				
			||||||
                return MaxFramerate.HasValue && !IsDirectStream
 | 
					                return MaxFramerate.HasValue && !IsDirectStream
 | 
				
			||||||
                    ? MaxFramerate
 | 
					                    ? MaxFramerate
 | 
				
			||||||
                    : stream is null ? null : stream.AverageFrameRate ?? stream.RealFrameRate;
 | 
					                    : stream?.ReferenceFrameRate;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -525,6 +525,23 @@ namespace MediaBrowser.Model.Entities
 | 
				
			|||||||
        /// <value>The real frame rate.</value>
 | 
					        /// <value>The real frame rate.</value>
 | 
				
			||||||
        public float? RealFrameRate { get; set; }
 | 
					        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>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets or sets the profile.
 | 
					        /// Gets or sets the profile.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
 | 
				
			|||||||
@ -348,7 +348,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
 | 
				
			|||||||
                    writer.WriteElementString("aspectratio", stream.AspectRatio);
 | 
					                    writer.WriteElementString("aspectratio", stream.AspectRatio);
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                var framerate = stream.AverageFrameRate ?? stream.RealFrameRate;
 | 
					                var framerate = stream.ReferenceFrameRate;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (framerate.HasValue)
 | 
					                if (framerate.HasValue)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user