mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-04 03:27:21 -05:00 
			
		
		
		
	Merge pull request #7699 from Shadowghost/streambuilder-fix
This commit is contained in:
		
						commit
						b46d61dfdf
					
				@ -385,7 +385,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
            // If device requirements are satisfied then allow both direct stream and direct play
 | 
					            // If device requirements are satisfied then allow both direct stream and direct play
 | 
				
			||||||
            if (item.SupportsDirectPlay)
 | 
					            if (item.SupportsDirectPlay)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (IsItemBitrateEligibleForDirectPlay(item, options.GetMaxBitrate(true) ?? 0, PlayMethod.DirectPlay))
 | 
					                if (IsItemBitrateEligibleForDirectPlayback(item, options.GetMaxBitrate(true) ?? 0, PlayMethod.DirectPlay))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    if (options.EnableDirectPlay)
 | 
					                    if (options.EnableDirectPlay)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -401,7 +401,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
            // While options takes the network and other factors into account. Only applies to direct stream
 | 
					            // While options takes the network and other factors into account. Only applies to direct stream
 | 
				
			||||||
            if (item.SupportsDirectStream)
 | 
					            if (item.SupportsDirectStream)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                if (IsItemBitrateEligibleForDirectPlay(item, options.GetMaxBitrate(true) ?? 0, PlayMethod.DirectStream))
 | 
					                if (IsItemBitrateEligibleForDirectPlayback(item, options.GetMaxBitrate(true) ?? 0, PlayMethod.DirectStream))
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    if (options.EnableDirectStream)
 | 
					                    if (options.EnableDirectStream)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
@ -604,11 +604,11 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            var videoStream = item.VideoStream;
 | 
					            var videoStream = item.VideoStream;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var directPlayEligibilityResult = IsEligibleForDirectPlay(item, options.GetMaxBitrate(false) ?? 0, options, PlayMethod.DirectPlay);
 | 
					            var directPlayBitrateEligibility = IsBitrateEligibleForDirectPlayback(item, options.GetMaxBitrate(false) ?? 0, options, PlayMethod.DirectPlay);
 | 
				
			||||||
            var directStreamEligibilityResult = IsEligibleForDirectPlay(item, options.GetMaxBitrate(false) ?? 0, options, PlayMethod.DirectStream);
 | 
					            var directStreamBitrateEligibility = IsBitrateEligibleForDirectPlayback(item, options.GetMaxBitrate(false) ?? 0, options, PlayMethod.DirectStream);
 | 
				
			||||||
            bool isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || directPlayEligibilityResult == 0);
 | 
					            bool isEligibleForDirectPlay = options.EnableDirectPlay && (options.ForceDirectPlay || directPlayBitrateEligibility == 0);
 | 
				
			||||||
            bool isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || directPlayEligibilityResult == 0);
 | 
					            bool isEligibleForDirectStream = options.EnableDirectStream && (options.ForceDirectStream || directStreamBitrateEligibility == 0);
 | 
				
			||||||
            var transcodeReasons = directPlayEligibilityResult | directStreamEligibilityResult;
 | 
					            var transcodeReasons = directPlayBitrateEligibility | directStreamBitrateEligibility;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _logger.LogDebug(
 | 
					            _logger.LogDebug(
 | 
				
			||||||
                "Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}",
 | 
					                "Profile: {0}, Path: {1}, isEligibleForDirectPlay: {2}, isEligibleForDirectStream: {3}",
 | 
				
			||||||
@ -625,7 +625,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
                var directPlay = directPlayInfo.PlayMethod;
 | 
					                var directPlay = directPlayInfo.PlayMethod;
 | 
				
			||||||
                transcodeReasons |= directPlayInfo.TranscodeReasons;
 | 
					                transcodeReasons |= directPlayInfo.TranscodeReasons;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (directPlay != null)
 | 
					                if (directPlay.HasValue)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    directPlayProfile = directPlayInfo.Profile;
 | 
					                    directPlayProfile = directPlayInfo.Profile;
 | 
				
			||||||
                    playlistItem.PlayMethod = directPlay.Value;
 | 
					                    playlistItem.PlayMethod = directPlay.Value;
 | 
				
			||||||
@ -676,7 +676,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            playlistItem.TranscodeReasons = transcodeReasons;
 | 
					            playlistItem.TranscodeReasons = transcodeReasons;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (playlistItem.PlayMethod != PlayMethod.DirectStream || !options.EnableDirectStream)
 | 
					            if (playlistItem.PlayMethod != PlayMethod.DirectStream && playlistItem.PlayMethod != PlayMethod.DirectPlay)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Can't direct play, find the transcoding profile
 | 
					                // Can't direct play, find the transcoding profile
 | 
				
			||||||
                // If we do this for direct-stream we will overwrite the info
 | 
					                // If we do this for direct-stream we will overwrite the info
 | 
				
			||||||
@ -687,6 +687,8 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    BuildStreamVideoItem(playlistItem, options, item, videoStream, audioStream, candidateAudioStreams, transcodingProfile.Container, transcodingProfile.VideoCodec, transcodingProfile.AudioCodec);
 | 
					                    BuildStreamVideoItem(playlistItem, options, item, videoStream, audioStream, candidateAudioStreams, transcodingProfile.Container, transcodingProfile.VideoCodec, transcodingProfile.AudioCodec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    playlistItem.PlayMethod = PlayMethod.Transcode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (subtitleStream != null)
 | 
					                    if (subtitleStream != null)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        var subtitleProfile = GetSubtitleProfile(item, subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode, _transcoderSupport, transcodingProfile.Container, transcodingProfile.Protocol);
 | 
					                        var subtitleProfile = GetSubtitleProfile(item, subtitleStream, options.Profile.SubtitleProfiles, PlayMethod.Transcode, _transcoderSupport, transcodingProfile.Container, transcodingProfile.Protocol);
 | 
				
			||||||
@ -696,14 +698,9 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
                        playlistItem.SubtitleCodecs = new[] { subtitleProfile.Format };
 | 
					                        playlistItem.SubtitleCodecs = new[] { subtitleProfile.Format };
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (playlistItem.PlayMethod != PlayMethod.DirectPlay)
 | 
					                    if ((playlistItem.TranscodeReasons & (VideoReasons | TranscodeReason.ContainerBitrateExceedsLimit)) != 0)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        playlistItem.PlayMethod = PlayMethod.Transcode;
 | 
					                        ApplyTranscodingConditions(playlistItem, transcodingProfile.Conditions, null, true, true);
 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if ((playlistItem.TranscodeReasons & (VideoReasons | TranscodeReason.ContainerBitrateExceedsLimit)) != 0)
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            ApplyTranscodingConditions(playlistItem, transcodingProfile.Conditions, null, true, true);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -771,12 +768,12 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        private void BuildStreamVideoItem(StreamInfo playlistItem, VideoOptions options, MediaSourceInfo item, MediaStream videoStream, MediaStream audioStream, IEnumerable<MediaStream> candidateAudioStreams, string container, string videoCodec, string audioCodec)
 | 
					        private void BuildStreamVideoItem(StreamInfo playlistItem, VideoOptions options, MediaSourceInfo item, MediaStream videoStream, MediaStream audioStream, IEnumerable<MediaStream> candidateAudioStreams, string container, string videoCodec, string audioCodec)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // prefer matching video codecs
 | 
					            // Prefer matching video codecs
 | 
				
			||||||
            var videoCodecs = ContainerProfile.SplitValue(videoCodec);
 | 
					            var videoCodecs = ContainerProfile.SplitValue(videoCodec);
 | 
				
			||||||
            var directVideoCodec = ContainerProfile.ContainsContainer(videoCodecs, videoStream?.Codec) ? videoStream?.Codec : null;
 | 
					            var directVideoCodec = ContainerProfile.ContainsContainer(videoCodecs, videoStream?.Codec) ? videoStream?.Codec : null;
 | 
				
			||||||
            playlistItem.VideoCodecs = directVideoCodec != null ? new[] { directVideoCodec } : videoCodecs;
 | 
					            playlistItem.VideoCodecs = directVideoCodec != null ? new[] { directVideoCodec } : 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?.AverageFrameRate;
 | 
				
			||||||
            var qualifier = videoStream?.Codec;
 | 
					            var qualifier = videoStream?.Codec;
 | 
				
			||||||
            if (videoStream?.Level != null)
 | 
					            if (videoStream?.Level != null)
 | 
				
			||||||
@ -799,7 +796,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
                playlistItem.SetOption(qualifier, "level", videoStream.Level.ToString());
 | 
					                playlistItem.SetOption(qualifier, "level", videoStream.Level.ToString());
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // prefer matching audio codecs, could do better here
 | 
					            // Prefer matching audio codecs, could do better here
 | 
				
			||||||
            var audioCodecs = ContainerProfile.SplitValue(audioCodec);
 | 
					            var audioCodecs = ContainerProfile.SplitValue(audioCodec);
 | 
				
			||||||
            var directAudioStream = candidateAudioStreams.FirstOrDefault(stream => ContainerProfile.ContainsContainer(audioCodecs, stream.Codec));
 | 
					            var directAudioStream = candidateAudioStreams.FirstOrDefault(stream => ContainerProfile.ContainsContainer(audioCodecs, stream.Codec));
 | 
				
			||||||
            playlistItem.AudioCodecs = audioCodecs;
 | 
					            playlistItem.AudioCodecs = audioCodecs;
 | 
				
			||||||
@ -809,7 +806,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
                playlistItem.AudioStreamIndex = audioStream.Index;
 | 
					                playlistItem.AudioStreamIndex = audioStream.Index;
 | 
				
			||||||
                playlistItem.AudioCodecs = new[] { audioStream.Codec };
 | 
					                playlistItem.AudioCodecs = new[] { audioStream.Codec };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // copy matching audio codec options
 | 
					                // Copy matching audio codec options
 | 
				
			||||||
                playlistItem.AudioSampleRate = audioStream.SampleRate;
 | 
					                playlistItem.AudioSampleRate = audioStream.SampleRate;
 | 
				
			||||||
                playlistItem.SetOption(qualifier, "audiochannels", audioStream.Channels.ToString());
 | 
					                playlistItem.SetOption(qualifier, "audiochannels", audioStream.Channels.ToString());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1070,7 +1067,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
            DeviceProfile profile = options.Profile;
 | 
					            DeviceProfile profile = options.Profile;
 | 
				
			||||||
            string container = mediaSource.Container;
 | 
					            string container = mediaSource.Container;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // video
 | 
					            // Video
 | 
				
			||||||
            int? width = videoStream?.Width;
 | 
					            int? width = videoStream?.Width;
 | 
				
			||||||
            int? height = videoStream?.Height;
 | 
					            int? height = videoStream?.Height;
 | 
				
			||||||
            int? bitDepth = videoStream?.BitDepth;
 | 
					            int? bitDepth = videoStream?.BitDepth;
 | 
				
			||||||
@ -1082,7 +1079,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
            bool? isInterlaced = videoStream?.IsInterlaced;
 | 
					            bool? isInterlaced = videoStream?.IsInterlaced;
 | 
				
			||||||
            string videoCodecTag = videoStream?.CodecTag;
 | 
					            string videoCodecTag = videoStream?.CodecTag;
 | 
				
			||||||
            bool? isAvc = videoStream?.IsAVC;
 | 
					            bool? isAvc = videoStream?.IsAVC;
 | 
				
			||||||
            // audio
 | 
					            // Audio
 | 
				
			||||||
            var defaultLanguage = audioStream?.Language ?? string.Empty;
 | 
					            var defaultLanguage = audioStream?.Language ?? string.Empty;
 | 
				
			||||||
            var defaultMarked = audioStream?.IsDefault ?? false;
 | 
					            var defaultMarked = audioStream?.IsDefault ?? false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1211,6 +1208,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
                    return (Result: (Profile: directPlayProfile, PlayMethod: playMethod, AudioStreamIndex: selectedAudioStream?.Index, TranscodeReason: failureReasons), Order: order, Rank: ranked);
 | 
					                    return (Result: (Profile: directPlayProfile, PlayMethod: playMethod, AudioStreamIndex: selectedAudioStream?.Index, TranscodeReason: failureReasons), Order: order, Rank: ranked);
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
                .OrderByDescending(analysis => analysis.Result.PlayMethod)
 | 
					                .OrderByDescending(analysis => analysis.Result.PlayMethod)
 | 
				
			||||||
 | 
					                .ThenByDescending(analysis => analysis.Rank)
 | 
				
			||||||
                .ThenBy(analysis => analysis.Order)
 | 
					                .ThenBy(analysis => analysis.Order)
 | 
				
			||||||
                .ToArray()
 | 
					                .ToArray()
 | 
				
			||||||
                .ToLookup(analysis => analysis.Result.PlayMethod != null);
 | 
					                .ToLookup(analysis => analysis.Result.PlayMethod != null);
 | 
				
			||||||
@ -1223,7 +1221,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
                return profileMatch;
 | 
					                return profileMatch;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var failureReasons = analyzedProfiles[false].OrderBy(a => a.Result.TranscodeReason).ThenBy(analysis => analysis.Order).FirstOrDefault().Result.TranscodeReason;
 | 
					            var failureReasons = analyzedProfiles[false].Select(analysis => analysis.Result).FirstOrDefault().TranscodeReason;
 | 
				
			||||||
            if (failureReasons == 0)
 | 
					            if (failureReasons == 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                failureReasons = TranscodeReason.DirectPlayError;
 | 
					                failureReasons = TranscodeReason.DirectPlayError;
 | 
				
			||||||
@ -1269,13 +1267,13 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
                mediaSource.Path ?? "Unknown path");
 | 
					                mediaSource.Path ?? "Unknown path");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private TranscodeReason IsEligibleForDirectPlay(
 | 
					        private TranscodeReason IsBitrateEligibleForDirectPlayback(
 | 
				
			||||||
            MediaSourceInfo item,
 | 
					            MediaSourceInfo item,
 | 
				
			||||||
            long maxBitrate,
 | 
					            long maxBitrate,
 | 
				
			||||||
            VideoOptions options,
 | 
					            VideoOptions options,
 | 
				
			||||||
            PlayMethod playMethod)
 | 
					            PlayMethod playMethod)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            bool result = IsItemBitrateEligibleForDirectPlay(item, maxBitrate, playMethod);
 | 
					            bool result = IsItemBitrateEligibleForDirectPlayback(item, maxBitrate, playMethod);
 | 
				
			||||||
            if (!result)
 | 
					            if (!result)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return TranscodeReason.ContainerBitrateExceedsLimit;
 | 
					                return TranscodeReason.ContainerBitrateExceedsLimit;
 | 
				
			||||||
@ -1443,7 +1441,7 @@ namespace MediaBrowser.Model.Dlna
 | 
				
			|||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private bool IsItemBitrateEligibleForDirectPlay(MediaSourceInfo item, long maxBitrate, PlayMethod playMethod)
 | 
					        private bool IsItemBitrateEligibleForDirectPlayback(MediaSourceInfo item, long maxBitrate, PlayMethod playMethod)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // Don't restrict by bitrate if coming from an external domain
 | 
					            // Don't restrict by bitrate if coming from an external domain
 | 
				
			||||||
            if (item.IsRemote)
 | 
					            if (item.IsRemote)
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,7 @@ namespace Jellyfin.Model.Tests
 | 
				
			|||||||
        [InlineData("Chrome", "mp4-h264-ac3-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-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
				
			||||||
        [InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
					        [InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
				
			||||||
        [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
					        [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
 | 
				
			||||||
        [InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
					        [InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
				
			||||||
        [InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
 | 
					        [InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
 | 
				
			||||||
        // Firefox
 | 
					        // Firefox
 | 
				
			||||||
@ -38,7 +38,7 @@ namespace Jellyfin.Model.Tests
 | 
				
			|||||||
        [InlineData("Firefox", "mp4-h264-ac3-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-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
				
			||||||
        [InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
					        [InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
				
			||||||
        [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
					        [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
 | 
				
			||||||
        [InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
					        [InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
				
			||||||
        [InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
 | 
					        [InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
 | 
				
			||||||
        // Safari
 | 
					        // Safari
 | 
				
			||||||
@ -89,7 +89,7 @@ namespace Jellyfin.Model.Tests
 | 
				
			|||||||
        [InlineData("Chrome-NoHLS", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
					        [InlineData("Chrome-NoHLS", "mp4-h264-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
				
			||||||
        [InlineData("Chrome-NoHLS", "mp4-hevc-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode", "http")]
 | 
					        [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, "Transcode", "http")]
 | 
					        [InlineData("Chrome-NoHLS", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode", "http")]
 | 
				
			||||||
        [InlineData("Chrome-NoHLS", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
					        [InlineData("Chrome-NoHLS", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
 | 
				
			||||||
        [InlineData("Chrome-NoHLS", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
					        [InlineData("Chrome-NoHLS", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
				
			||||||
        [InlineData("Chrome-NoHLS", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
 | 
					        [InlineData("Chrome-NoHLS", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
 | 
				
			||||||
        // TranscodeMedia
 | 
					        // TranscodeMedia
 | 
				
			||||||
@ -177,7 +177,7 @@ namespace Jellyfin.Model.Tests
 | 
				
			|||||||
        [InlineData("Chrome", "mp4-h264-ac3-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-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
				
			||||||
        [InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
					        [InlineData("Chrome", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
				
			||||||
        [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
					        [InlineData("Chrome", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
 | 
				
			||||||
        [InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
					        [InlineData("Chrome", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
				
			||||||
        [InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
 | 
					        [InlineData("Chrome", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
 | 
				
			||||||
        // Firefox
 | 
					        // Firefox
 | 
				
			||||||
@ -187,7 +187,7 @@ namespace Jellyfin.Model.Tests
 | 
				
			|||||||
        [InlineData("Firefox", "mp4-h264-ac3-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-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
				
			||||||
        [InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
					        [InlineData("Firefox", "mp4-hevc-ac3-aac-srt-15200k", PlayMethod.Transcode, TranscodeReason.VideoCodecNotSupported, "Transcode")]
 | 
				
			||||||
        [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
					        [InlineData("Firefox", "mkv-vp9-aac-srt-2600k", PlayMethod.DirectStream, TranscodeReason.ContainerNotSupported)] // #6450
 | 
				
			||||||
        [InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
					        [InlineData("Firefox", "mkv-vp9-ac3-srt-2600k", PlayMethod.DirectStream, TranscodeReason.AudioCodecNotSupported)] // #6450
 | 
				
			||||||
        [InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
 | 
					        [InlineData("Firefox", "mkv-vp9-vorbis-vtt-2600k", PlayMethod.DirectPlay, (TranscodeReason)0, "Remux")] // #6450
 | 
				
			||||||
        // Safari
 | 
					        // Safari
 | 
				
			||||||
@ -338,23 +338,23 @@ namespace Jellyfin.Model.Tests
 | 
				
			|||||||
            Assert.NotNull(mediaSource);
 | 
					            Assert.NotNull(mediaSource);
 | 
				
			||||||
            var videoStreams = mediaSource.MediaStreams.Where(stream => stream.Type == MediaStreamType.Video);
 | 
					            var videoStreams = mediaSource.MediaStreams.Where(stream => stream.Type == MediaStreamType.Video);
 | 
				
			||||||
            var audioStreams = mediaSource.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio);
 | 
					            var audioStreams = mediaSource.MediaStreams.Where(stream => stream.Type == MediaStreamType.Audio);
 | 
				
			||||||
            // TODO: check AudioStreamIndex vs options.AudioStreamIndex
 | 
					            // TODO: Check AudioStreamIndex vs options.AudioStreamIndex
 | 
				
			||||||
            var inputAudioStream = mediaSource.GetDefaultAudioStream(audioStreamIndexInput ?? mediaSource.DefaultAudioStreamIndex);
 | 
					            var inputAudioStream = mediaSource.GetDefaultAudioStream(audioStreamIndexInput ?? mediaSource.DefaultAudioStreamIndex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var uri = ParseUri(val);
 | 
					            var uri = ParseUri(val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (playMethod == PlayMethod.DirectPlay)
 | 
					            if (playMethod == PlayMethod.DirectPlay)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // check expected container
 | 
					                // Check expected container
 | 
				
			||||||
                var containers = ContainerProfile.SplitValue(mediaSource.Container);
 | 
					                var containers = ContainerProfile.SplitValue(mediaSource.Container);
 | 
				
			||||||
                // TODO: test transcode too
 | 
					                // TODO: Test transcode too
 | 
				
			||||||
                // Assert.Contains(uri.Extension, containers);
 | 
					                // Assert.Contains(uri.Extension, containers);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // check expected video codec (1)
 | 
					                // Check expected video codec (1)
 | 
				
			||||||
                Assert.Contains(targetVideoStream.Codec, val.TargetVideoCodec);
 | 
					                Assert.Contains(targetVideoStream.Codec, val.TargetVideoCodec);
 | 
				
			||||||
                Assert.Single(val.TargetVideoCodec);
 | 
					                Assert.Single(val.TargetVideoCodec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // check expected audio codecs (1)
 | 
					                // Check expected audio codecs (1)
 | 
				
			||||||
                Assert.Contains(targetAudioStream.Codec, val.TargetAudioCodec);
 | 
					                Assert.Contains(targetAudioStream.Codec, val.TargetAudioCodec);
 | 
				
			||||||
                Assert.Single(val.TargetAudioCodec);
 | 
					                Assert.Single(val.TargetAudioCodec);
 | 
				
			||||||
                // Assert.Single(val.AudioCodecs);
 | 
					                // Assert.Single(val.AudioCodecs);
 | 
				
			||||||
@ -370,7 +370,7 @@ namespace Jellyfin.Model.Tests
 | 
				
			|||||||
                Assert.NotEmpty(val.VideoCodecs);
 | 
					                Assert.NotEmpty(val.VideoCodecs);
 | 
				
			||||||
                Assert.NotEmpty(val.AudioCodecs);
 | 
					                Assert.NotEmpty(val.AudioCodecs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // check expected container (todo: this could be a test param)
 | 
					                // Check expected container (todo: this could be a test param)
 | 
				
			||||||
                if (transcodeProtocol == "http")
 | 
					                if (transcodeProtocol == "http")
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    // Assert.Equal("webm", val.Container);
 | 
					                    // Assert.Equal("webm", val.Container);
 | 
				
			||||||
@ -403,32 +403,39 @@ namespace Jellyfin.Model.Tests
 | 
				
			|||||||
                            stream => Assert.DoesNotContain(stream.Codec, val.VideoCodecs));
 | 
					                            stream => Assert.DoesNotContain(stream.Codec, val.VideoCodecs));
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // todo: fill out tests here
 | 
					                    // TODO: Fill out tests here
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // DirectStream and Remux
 | 
					                // DirectStream and Remux
 | 
				
			||||||
                else
 | 
					                else
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    // check expected video codec (1)
 | 
					                    // Check expected video codec (1)
 | 
				
			||||||
                    Assert.Contains(targetVideoStream.Codec, val.TargetVideoCodec);
 | 
					                    Assert.Contains(targetVideoStream.Codec, val.TargetVideoCodec);
 | 
				
			||||||
                    Assert.Single(val.TargetVideoCodec);
 | 
					                    Assert.Single(val.TargetVideoCodec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (transcodeMode == "DirectStream")
 | 
					                    if (transcodeMode == "DirectStream")
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
 | 
					                        // Check expected audio codecs (1)
 | 
				
			||||||
                        if (!targetAudioStream.IsExternal)
 | 
					                        if (!targetAudioStream.IsExternal)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            // check expected audio codecs (1)
 | 
					                            if (val.TranscodeReasons.HasFlag(TranscodeReason.ContainerNotSupported))
 | 
				
			||||||
                            Assert.DoesNotContain(targetAudioStream.Codec, val.AudioCodecs);
 | 
					                            {
 | 
				
			||||||
 | 
					                                Assert.Contains(targetAudioStream.Codec, val.AudioCodecs);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            else
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                Assert.DoesNotContain(targetAudioStream.Codec, val.AudioCodecs);
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    else if (transcodeMode == "Remux")
 | 
					                    else if (transcodeMode == "Remux")
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        // check expected audio codecs (1)
 | 
					                        // Check expected audio codecs (1)
 | 
				
			||||||
                        Assert.Contains(targetAudioStream.Codec, val.AudioCodecs);
 | 
					                        Assert.Contains(targetAudioStream.Codec, val.AudioCodecs);
 | 
				
			||||||
                        Assert.Single(val.AudioCodecs);
 | 
					                        Assert.Single(val.AudioCodecs);
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // video details
 | 
					                    // Video details
 | 
				
			||||||
                    var videoStream = targetVideoStream;
 | 
					                    var videoStream = targetVideoStream;
 | 
				
			||||||
                    Assert.False(val.EstimateContentLength);
 | 
					                    Assert.False(val.EstimateContentLength);
 | 
				
			||||||
                    Assert.Equal(TranscodeSeekInfo.Auto, val.TranscodeSeekInfo);
 | 
					                    Assert.Equal(TranscodeSeekInfo.Auto, val.TranscodeSeekInfo);
 | 
				
			||||||
@ -437,10 +444,10 @@ namespace Jellyfin.Model.Tests
 | 
				
			|||||||
                    Assert.Equal(videoStream.BitDepth, val.TargetVideoBitDepth);
 | 
					                    Assert.Equal(videoStream.BitDepth, val.TargetVideoBitDepth);
 | 
				
			||||||
                    Assert.InRange(val.VideoBitrate.GetValueOrDefault(), videoStream.BitRate.GetValueOrDefault(), int.MaxValue);
 | 
					                    Assert.InRange(val.VideoBitrate.GetValueOrDefault(), videoStream.BitRate.GetValueOrDefault(), int.MaxValue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // audio codec not supported
 | 
					                    // Audio codec not supported
 | 
				
			||||||
                    if ((why & TranscodeReason.AudioCodecNotSupported) != 0)
 | 
					                    if ((why & TranscodeReason.AudioCodecNotSupported) != 0)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        // audio stream specified
 | 
					                        // Audio stream specified
 | 
				
			||||||
                        if (options.AudioStreamIndex >= 0)
 | 
					                        if (options.AudioStreamIndex >= 0)
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            // TODO:fixme
 | 
					                            // TODO:fixme
 | 
				
			||||||
@ -450,10 +457,10 @@ namespace Jellyfin.Model.Tests
 | 
				
			|||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        // audio stream not specified
 | 
					                        // Audio stream not specified
 | 
				
			||||||
                        else
 | 
					                        else
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
                            // TODO:fixme
 | 
					                            // TODO: Fixme
 | 
				
			||||||
                            Assert.All(audioStreams, stream =>
 | 
					                            Assert.All(audioStreams, stream =>
 | 
				
			||||||
                            {
 | 
					                            {
 | 
				
			||||||
                                if (!stream.IsExternal)
 | 
					                                if (!stream.IsExternal)
 | 
				
			||||||
 | 
				
			|||||||
@ -45,8 +45,8 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "Container": "wmv",
 | 
					            "Container": "wmv",
 | 
				
			||||||
            "AudioCodec": "",
 | 
					            "AudioCodec": "wma",
 | 
				
			||||||
            "VideoCodec": "",
 | 
					            "VideoCodec": "wmv,vc1",
 | 
				
			||||||
            "Type": "Video",
 | 
					            "Type": "Video",
 | 
				
			||||||
            "$type": "DirectPlayProfile"
 | 
					            "$type": "DirectPlayProfile"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
@ -59,8 +59,8 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "Container": "asf",
 | 
					            "Container": "asf",
 | 
				
			||||||
            "AudioCodec": "",
 | 
					            "AudioCodec": "wma",
 | 
				
			||||||
            "VideoCodec": "",
 | 
					            "VideoCodec": "wmv,vc1",
 | 
				
			||||||
            "Type": "Video",
 | 
					            "Type": "Video",
 | 
				
			||||||
            "$type": "DirectPlayProfile"
 | 
					            "$type": "DirectPlayProfile"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
				
			|||||||
@ -45,8 +45,8 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "Container": "wmv",
 | 
					            "Container": "wmv",
 | 
				
			||||||
            "AudioCodec": "",
 | 
					            "AudioCodec": "wma",
 | 
				
			||||||
            "VideoCodec": "",
 | 
					            "VideoCodec": "wmv,vc1",
 | 
				
			||||||
            "Type": "Video",
 | 
					            "Type": "Video",
 | 
				
			||||||
            "$type": "DirectPlayProfile"
 | 
					            "$type": "DirectPlayProfile"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
@ -59,8 +59,8 @@
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            "Container": "asf",
 | 
					            "Container": "asf",
 | 
				
			||||||
            "AudioCodec": "",
 | 
					            "AudioCodec": "wma",
 | 
				
			||||||
            "VideoCodec": "",
 | 
					            "VideoCodec": "wmv,vc1",
 | 
				
			||||||
            "Type": "Video",
 | 
					            "Type": "Video",
 | 
				
			||||||
            "$type": "DirectPlayProfile"
 | 
					            "$type": "DirectPlayProfile"
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user