diff options
Diffstat (limited to 'MediaBrowser.MediaEncoding')
4 files changed, 170 insertions, 3 deletions
diff --git a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs index ff91a60a79..a11440ced2 100644 --- a/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs +++ b/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs @@ -1,7 +1,7 @@ #pragma warning disable CS1591 using System; -using System.Collections.Concurrent; +using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; @@ -9,6 +9,7 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using AsyncKeyedLock; +using MediaBrowser.Common; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Entities; @@ -138,7 +139,8 @@ namespace MediaBrowser.MediaEncoding.Attachments var processArgs = string.Format( CultureInfo.InvariantCulture, - "-dump_attachment:t \"\" -y -i {0} -t 0 -f null null", + "-dump_attachment:t \"\" -y {0} -i {1} -t 0 -f null null", + inputPath.EndsWith(".concat\"", StringComparison.OrdinalIgnoreCase) ? "-f concat -safe 0" : string.Empty, inputPath); int exitCode; @@ -230,6 +232,8 @@ namespace MediaBrowser.MediaEncoding.Attachments MediaAttachment mediaAttachment, CancellationToken cancellationToken) { + await CacheAllAttachments(mediaPath, inputFile, mediaSource, cancellationToken).ConfigureAwait(false); + var outputPath = GetAttachmentCachePath(mediaPath, mediaSource, mediaAttachment.Index); await ExtractAttachment(inputFile, mediaSource, mediaAttachment.Index, outputPath, cancellationToken) .ConfigureAwait(false); @@ -237,6 +241,159 @@ namespace MediaBrowser.MediaEncoding.Attachments return outputPath; } + private async Task CacheAllAttachments( + string mediaPath, + string inputFile, + MediaSourceInfo mediaSource, + CancellationToken cancellationToken) + { + var outputFileLocks = new List<AsyncKeyedLockReleaser<string>>(); + var extractableAttachmentIds = new List<int>(); + + try + { + foreach (var attachment in mediaSource.MediaAttachments) + { + var outputPath = GetAttachmentCachePath(mediaPath, mediaSource, attachment.Index); + + var @outputFileLock = _semaphoreLocks.GetOrAdd(outputPath); + await @outputFileLock.SemaphoreSlim.WaitAsync(cancellationToken).ConfigureAwait(false); + + if (File.Exists(outputPath)) + { + @outputFileLock.Dispose(); + continue; + } + + outputFileLocks.Add(@outputFileLock); + extractableAttachmentIds.Add(attachment.Index); + } + + if (extractableAttachmentIds.Count > 0) + { + await CacheAllAttachmentsInternal(mediaPath, inputFile, mediaSource, extractableAttachmentIds, cancellationToken).ConfigureAwait(false); + } + } + catch (Exception ex) + { + _logger.LogWarning(ex, "Unable to cache media attachments for File:{File}", mediaPath); + } + finally + { + foreach (var @outputFileLock in outputFileLocks) + { + @outputFileLock.Dispose(); + } + } + } + + private async Task CacheAllAttachmentsInternal( + string mediaPath, + string inputFile, + MediaSourceInfo mediaSource, + List<int> extractableAttachmentIds, + CancellationToken cancellationToken) + { + var outputPaths = new List<string>(); + var processArgs = string.Empty; + + foreach (var attachmentId in extractableAttachmentIds) + { + var outputPath = GetAttachmentCachePath(mediaPath, mediaSource, attachmentId); + + Directory.CreateDirectory(Path.GetDirectoryName(outputPath) ?? throw new FileNotFoundException($"Calculated path ({outputPath}) is not valid.")); + + outputPaths.Add(outputPath); + processArgs += string.Format( + CultureInfo.InvariantCulture, + " -dump_attachment:{0} \"{1}\"", + attachmentId, + EncodingUtils.NormalizePath(outputPath)); + } + + processArgs += string.Format( + CultureInfo.InvariantCulture, + " -i \"{0}\" -t 0 -f null null", + inputFile); + + int exitCode; + + using (var process = new Process + { + StartInfo = new ProcessStartInfo + { + Arguments = processArgs, + FileName = _mediaEncoder.EncoderPath, + UseShellExecute = false, + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + ErrorDialog = false + }, + EnableRaisingEvents = true + }) + { + _logger.LogInformation("{File} {Arguments}", process.StartInfo.FileName, process.StartInfo.Arguments); + + process.Start(); + + try + { + await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false); + exitCode = process.ExitCode; + } + catch (OperationCanceledException) + { + process.Kill(true); + exitCode = -1; + } + } + + var failed = false; + + if (exitCode == -1) + { + failed = true; + + foreach (var outputPath in outputPaths) + { + try + { + _logger.LogWarning("Deleting extracted media attachment due to failure: {Path}", outputPath); + _fileSystem.DeleteFile(outputPath); + } + catch (FileNotFoundException) + { + // ffmpeg failed, so it is normal that one or more expected output files do not exist. + // There is no need to log anything for the user here. + } + catch (IOException ex) + { + _logger.LogError(ex, "Error deleting extracted media attachment {Path}", outputPath); + } + } + } + else + { + foreach (var outputPath in outputPaths) + { + if (!File.Exists(outputPath)) + { + _logger.LogError("ffmpeg media attachment extraction failed for {InputPath} to {OutputPath}", inputFile, outputPath); + failed = true; + continue; + } + + _logger.LogInformation("ffmpeg media attachment extraction completed for {InputPath} to {OutputPath}", inputFile, outputPath); + } + } + + if (failed) + { + throw new FfmpegException( + string.Format(CultureInfo.InvariantCulture, "ffmpeg media attachment extraction failed for {0}", inputFile)); + } + } + private async Task ExtractAttachment( string inputFile, MediaSourceInfo mediaSource, diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index fdca283908..6549125d36 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -128,6 +128,8 @@ namespace MediaBrowser.MediaEncoding.Encoder "overlay_vulkan", // videotoolbox "yadif_videotoolbox", + "scale_vt", + "overlay_videotoolbox", // rkrga "scale_rkrga", "vpp_rkrga", diff --git a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs index 317aba4186..5397a6752d 100644 --- a/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs +++ b/MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs @@ -79,6 +79,7 @@ namespace MediaBrowser.MediaEncoding.Probing "5/8erl in Ehr'n", "Smith/Kotzen", "We;Na", + "LSR/CITY", }; /// <summary> diff --git a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs index 8bace15c65..5d51a901ad 100644 --- a/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs +++ b/MediaBrowser.MediaEncoding/Transcoding/TranscodeManager.cs @@ -724,7 +724,14 @@ public sealed class TranscodeManager : ITranscodeManager, IDisposable foreach (var file in _fileSystem.GetFilePaths(path, true)) { - _fileSystem.DeleteFile(file); + try + { + _fileSystem.DeleteFile(file); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error deleting encoded media cache file {Path}", path); + } } } |
