Browse Source

Merge pull request #10990 from Shadowghost/bdmv-fixes

BDMV fixes
Bond-009 1 year ago
parent
commit
0bf1c10c44

+ 2 - 4
Jellyfin.Api/Controllers/VideosController.cs

@@ -458,10 +458,8 @@ public class VideosController : BaseJellyfinApiController
             return BadRequest($"Input protocol {state.InputProtocol} cannot be streamed statically");
             return BadRequest($"Input protocol {state.InputProtocol} cannot be streamed statically");
         }
         }
 
 
-        var outputPath = state.OutputFilePath;
-
         // Static stream
         // Static stream
-        if (@static.HasValue && @static.Value)
+        if (@static.HasValue && @static.Value && !(state.MediaSource.VideoType == VideoType.BluRay || state.MediaSource.VideoType == VideoType.Dvd))
         {
         {
             var contentType = state.GetMimeType("." + state.OutputContainer, false) ?? state.GetMimeType(state.MediaPath);
             var contentType = state.GetMimeType("." + state.OutputContainer, false) ?? state.GetMimeType(state.MediaPath);
 
 
@@ -478,7 +476,7 @@ public class VideosController : BaseJellyfinApiController
 
 
         // Need to start ffmpeg (because media can't be returned directly)
         // Need to start ffmpeg (because media can't be returned directly)
         var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
         var encodingOptions = _serverConfigurationManager.GetEncodingOptions();
-        var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, outputPath, "superfast");
+        var ffmpegCommandLineArguments = _encodingHelper.GetProgressiveVideoFullCommandLine(state, encodingOptions, "superfast");
         return await FileStreamResponseHelpers.GetTranscodedFile(
         return await FileStreamResponseHelpers.GetTranscodedFile(
             state,
             state,
             isHeadRequest,
             isHeadRequest,

+ 20 - 1
Jellyfin.Api/Helpers/StreamingHelpers.cs

@@ -225,7 +225,7 @@ public static class StreamingHelpers
 
 
         var ext = string.IsNullOrWhiteSpace(state.OutputContainer)
         var ext = string.IsNullOrWhiteSpace(state.OutputContainer)
             ? GetOutputFileExtension(state, mediaSource)
             ? GetOutputFileExtension(state, mediaSource)
-            : ("." + state.OutputContainer);
+            : ("." + GetContainerFileExtension(state.OutputContainer));
 
 
         state.OutputFilePath = GetOutputFilePath(state, ext, serverConfigurationManager, streamingRequest.DeviceId, streamingRequest.PlaySessionId);
         state.OutputFilePath = GetOutputFilePath(state, ext, serverConfigurationManager, streamingRequest.DeviceId, streamingRequest.PlaySessionId);
 
 
@@ -559,4 +559,23 @@ public static class StreamingHelpers
             }
             }
         }
         }
     }
     }
+
+    /// <summary>
+    /// Parses the container into its file extension.
+    /// </summary>
+    /// <param name="container">The container.</param>
+    private static string? GetContainerFileExtension(string? container)
+    {
+        if (string.Equals(container, "mpegts", StringComparison.OrdinalIgnoreCase))
+        {
+            return "ts";
+        }
+
+        if (string.Equals(container, "matroska", StringComparison.OrdinalIgnoreCase))
+        {
+            return "mkv";
+        }
+
+        return container;
+    }
 }
 }

+ 2 - 1
MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs

@@ -6541,13 +6541,14 @@ namespace MediaBrowser.Controller.MediaEncoding
             return " -codec:s:0 " + codec + " -disposition:s:0 default";
             return " -codec:s:0 " + codec + " -disposition:s:0 default";
         }
         }
 
 
-        public string GetProgressiveVideoFullCommandLine(EncodingJobInfo state, EncodingOptions encodingOptions, string outputPath, string defaultPreset)
+        public string GetProgressiveVideoFullCommandLine(EncodingJobInfo state, EncodingOptions encodingOptions, string defaultPreset)
         {
         {
             // Get the output codec name
             // Get the output codec name
             var videoCodec = GetVideoEncoder(state, encodingOptions);
             var videoCodec = GetVideoEncoder(state, encodingOptions);
 
 
             var format = string.Empty;
             var format = string.Empty;
             var keyFrame = string.Empty;
             var keyFrame = string.Empty;
+            var outputPath = state.OutputFilePath;
 
 
             if (Path.GetExtension(outputPath.AsSpan()).Equals(".mp4", StringComparison.OrdinalIgnoreCase)
             if (Path.GetExtension(outputPath.AsSpan()).Equals(".mp4", StringComparison.OrdinalIgnoreCase)
                 && state.BaseRequest.Context == EncodingContext.Streaming)
                 && state.BaseRequest.Context == EncodingContext.Streaming)

+ 23 - 23
MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs

@@ -1111,6 +1111,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
             return allVobs
             return allVobs
                 .Where(vob => titles.Contains(_fileSystem.GetFileNameWithoutExtension(vob).AsSpan().RightPart('_').ToString()))
                 .Where(vob => titles.Contains(_fileSystem.GetFileNameWithoutExtension(vob).AsSpan().RightPart('_').ToString()))
                 .Select(i => i.FullName)
                 .Select(i => i.FullName)
+                .Order()
                 .ToList();
                 .ToList();
         }
         }
 
 
@@ -1127,6 +1128,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
             return directoryFiles
             return directoryFiles
                 .Where(f => validPlaybackFiles.Contains(f.Name, StringComparer.OrdinalIgnoreCase))
                 .Where(f => validPlaybackFiles.Contains(f.Name, StringComparer.OrdinalIgnoreCase))
                 .Select(f => f.FullName)
                 .Select(f => f.FullName)
+                .Order()
                 .ToList();
                 .ToList();
         }
         }
 
 
@@ -1150,31 +1152,29 @@ namespace MediaBrowser.MediaEncoding.Encoder
             }
             }
 
 
             // Generate concat configuration entries for each file and write to file
             // Generate concat configuration entries for each file and write to file
-            using (StreamWriter sw = new StreamWriter(concatFilePath))
+            using StreamWriter sw = new StreamWriter(concatFilePath);
+            foreach (var path in files)
             {
             {
-                foreach (var path in files)
-                {
-                    var mediaInfoResult = GetMediaInfo(
-                        new MediaInfoRequest
+                var mediaInfoResult = GetMediaInfo(
+                    new MediaInfoRequest
+                    {
+                        MediaType = DlnaProfileType.Video,
+                        MediaSource = new MediaSourceInfo
                         {
                         {
-                            MediaType = DlnaProfileType.Video,
-                            MediaSource = new MediaSourceInfo
-                            {
-                                Path = path,
-                                Protocol = MediaProtocol.File,
-                                VideoType = videoType
-                            }
-                        },
-                        CancellationToken.None).GetAwaiter().GetResult();
-
-                    var duration = TimeSpan.FromTicks(mediaInfoResult.RunTimeTicks.Value).TotalSeconds;
-
-                    // Add file path stanza to concat configuration
-                    sw.WriteLine("file '{0}'", path);
-
-                    // Add duration stanza to concat configuration
-                    sw.WriteLine("duration {0}", duration);
-                }
+                            Path = path,
+                            Protocol = MediaProtocol.File,
+                            VideoType = videoType
+                        }
+                    },
+                    CancellationToken.None).GetAwaiter().GetResult();
+
+                var duration = TimeSpan.FromTicks(mediaInfoResult.RunTimeTicks.Value).TotalSeconds;
+
+                // Add file path stanza to concat configuration
+                sw.WriteLine("file '{0}'", path);
+
+                // Add duration stanza to concat configuration
+                sw.WriteLine("duration {0}", duration);
             }
             }
         }
         }
 
 

+ 10 - 5
MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs

@@ -405,7 +405,7 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable
             var user = userId.IsEmpty() ? null : _userManager.GetUserById(userId);
             var user = userId.IsEmpty() ? null : _userManager.GetUserById(userId);
             if (user is not null && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding))
             if (user is not null && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding))
             {
             {
-                this.OnTranscodeFailedToStart(outputPath, transcodingJobType, state);
+                OnTranscodeFailedToStart(outputPath, transcodingJobType, state);
 
 
                 throw new ArgumentException("User does not have access to video transcoding.");
                 throw new ArgumentException("User does not have access to video transcoding.");
             }
             }
@@ -417,7 +417,12 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable
         if (state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode)
         if (state.SubtitleStream is not null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode)
         {
         {
             var attachmentPath = Path.Combine(_appPaths.CachePath, "attachments", state.MediaSource.Id);
             var attachmentPath = Path.Combine(_appPaths.CachePath, "attachments", state.MediaSource.Id);
-            if (state.VideoType != VideoType.Dvd)
+            if (state.MediaSource.VideoType == VideoType.Dvd || state.MediaSource.VideoType == VideoType.BluRay)
+            {
+                var concatPath = Path.Join(_serverConfigurationManager.GetTranscodePath(), state.MediaSource.Id + ".concat");
+                await _attachmentExtractor.ExtractAllAttachments(concatPath, state.MediaSource, attachmentPath, cancellationTokenSource.Token).ConfigureAwait(false);
+            }
+            else
             {
             {
                 await _attachmentExtractor.ExtractAllAttachments(state.MediaPath, state.MediaSource, attachmentPath, cancellationTokenSource.Token).ConfigureAwait(false);
                 await _attachmentExtractor.ExtractAllAttachments(state.MediaPath, state.MediaSource, attachmentPath, cancellationTokenSource.Token).ConfigureAwait(false);
             }
             }
@@ -432,7 +437,7 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable
             }
             }
         }
         }
 
 
-        var process = new Process
+        using var process = new Process
         {
         {
             StartInfo = new ProcessStartInfo
             StartInfo = new ProcessStartInfo
             {
             {
@@ -452,7 +457,7 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable
             EnableRaisingEvents = true
             EnableRaisingEvents = true
         };
         };
 
 
-        var transcodingJob = this.OnTranscodeBeginning(
+        var transcodingJob = OnTranscodeBeginning(
             outputPath,
             outputPath,
             state.Request.PlaySessionId,
             state.Request.PlaySessionId,
             state.MediaSource.LiveStreamId,
             state.MediaSource.LiveStreamId,
@@ -507,7 +512,7 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable
         catch (Exception ex)
         catch (Exception ex)
         {
         {
             _logger.LogError(ex, "Error starting FFmpeg");
             _logger.LogError(ex, "Error starting FFmpeg");
-            this.OnTranscodeFailedToStart(outputPath, transcodingJobType, state);
+            OnTranscodeFailedToStart(outputPath, transcodingJobType, state);
 
 
             throw;
             throw;
         }
         }