Browse Source

remove standard output redirect on image extractions

Luke Pulverenti 9 năm trước cách đây
mục cha
commit
00634b62c5

+ 3 - 3
MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs

@@ -35,7 +35,7 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// <param name="imageStreamIndex">Index of the image stream.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{Stream}.</returns>
-        Task<Stream> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken);
+        Task<string> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken);
 
         /// <summary>
         /// Extracts the video image.
@@ -46,9 +46,9 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// <param name="offset">The offset.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{Stream}.</returns>
-        Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
+        Task<string> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
 
-        Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken);
+        Task<string> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken);
 
         /// <summary>
         /// Extracts the video images on interval.

+ 1 - 4
MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs

@@ -117,8 +117,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
                     Arguments = arguments,
                     WindowStyle = ProcessWindowStyle.Hidden,
                     ErrorDialog = false,
-                    RedirectStandardOutput = true,
-                    //RedirectStandardError = true
+                    RedirectStandardOutput = true
                 }
             };
 
@@ -128,8 +127,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
 
                 try
                 {
-                    //process.BeginErrorReadLine();
-
                     return process.StandardOutput.ReadToEnd();
                 }
                 catch

+ 13 - 24
MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs

@@ -767,22 +767,22 @@ namespace MediaBrowser.MediaEncoding.Encoder
         /// </summary>
         protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
 
-        public Task<Stream> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken)
+        public Task<string> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken)
         {
             return ExtractImage(new[] { path }, imageStreamIndex, MediaProtocol.File, true, null, null, cancellationToken);
         }
 
-        public Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
+        public Task<string> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
         {
             return ExtractImage(inputFiles, null, protocol, false, threedFormat, offset, cancellationToken);
         }
 
-        public Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken)
+        public Task<string> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken)
         {
             return ExtractImage(inputFiles, imageStreamIndex, protocol, false, null, null, cancellationToken);
         }
 
-        private async Task<Stream> ExtractImage(string[] inputFiles, int? imageStreamIndex, MediaProtocol protocol, bool isAudio,
+        private async Task<string> ExtractImage(string[] inputFiles, int? imageStreamIndex, MediaProtocol protocol, bool isAudio,
             Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
         {
             var resourcePool = isAudio ? _audioImageResourcePool : _videoImageResourcePool;
@@ -816,13 +816,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
             return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false);
         }
 
-        private async Task<Stream> ExtractImageInternal(string inputPath, int? imageStreamIndex, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
+        private async Task<string> ExtractImageInternal(string inputPath, int? imageStreamIndex, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
         {
             if (string.IsNullOrEmpty(inputPath))
             {
                 throw new ArgumentNullException("inputPath");
             }
 
+            var tempExtractPath = Path.Combine(ConfigurationManager.ApplicationPaths.TempDirectory, Guid.NewGuid() + ".jpg");
+            Directory.CreateDirectory(Path.GetDirectoryName(tempExtractPath));
+
             // apply some filters to thumbnail extracted below (below) crop any black lines that we made and get the correct ar then scale to width 600. 
             // This filter chain may have adverse effects on recorded tv thumbnails if ar changes during presentation ex. commercials @ diff ar
             var vf = "scale=600:trunc(600/dar/2)*2";
@@ -855,8 +858,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
             var mapArg = imageStreamIndex.HasValue ? (" -map 0:v:" + imageStreamIndex.Value.ToString(CultureInfo.InvariantCulture)) : string.Empty;
 
             // Use ffmpeg to sample 100 (we can drop this if required using thumbnail=50 for 50 frames) frames and pick the best thumbnail. Have a fall back just in case.
-            var args = useIFrame ? string.Format("-i {0}{3} -threads 1 -v quiet -vframes 1 -vf \"{2},thumbnail=30\" -f image2 \"{1}\"", inputPath, "-", vf, mapArg) :
-                string.Format("-i {0}{3} -threads 1 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf, mapArg);
+            var args = useIFrame ? string.Format("-i {0}{3} -threads 1 -v quiet -vframes 1 -vf \"{2},thumbnail=30\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg) :
+                string.Format("-i {0}{3} -threads 1 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, tempExtractPath, vf, mapArg);
 
             var probeSize = GetProbeSizeArgument(new[] { inputPath }, protocol);
 
@@ -880,8 +883,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
                     Arguments = args,
                     WindowStyle = ProcessWindowStyle.Hidden,
                     ErrorDialog = false,
-                    RedirectStandardOutput = true,
-                    RedirectStandardError = true,
                     RedirectStandardInput = true
                 }
             };
@@ -894,20 +895,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
 
                 bool ranToCompletion;
 
-                var memoryStream = new MemoryStream();
-
                 try
                 {
                     StartProcess(processWrapper);
 
-#pragma warning disable 4014
-                    // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback
-                    process.StandardOutput.BaseStream.CopyToAsync(memoryStream);
-#pragma warning restore 4014
-
-                    // MUST read both stdout and stderr asynchronously or a deadlock may occurr
-                    process.BeginErrorReadLine();
-
                     ranToCompletion = process.WaitForExit(10000);
 
                     if (!ranToCompletion)
@@ -922,11 +913,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
                 }
 
                 var exitCode = ranToCompletion ? processWrapper.ExitCode ?? 0 : -1;
+                var file = new FileInfo(tempExtractPath);
 
-                if (exitCode == -1 || memoryStream.Length == 0)
+                if (exitCode == -1 || !file.Exists || file.Length == 0)
                 {
-                    memoryStream.Dispose();
-
                     var msg = string.Format("ffmpeg image extraction failed for {0}", inputPath);
 
                     _logger.Error(msg);
@@ -934,8 +924,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
                     throw new ApplicationException(msg);
                 }
 
-                memoryStream.Position = 0;
-                return memoryStream;
+                return tempExtractPath;
             }
         }
 

+ 10 - 5
MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs

@@ -83,12 +83,17 @@ namespace MediaBrowser.Providers.MediaInfo
 
                         var imageStreamIndex = imageStream == null ? (int?)null : imageStream.Index;
 
-                        using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false))
+                        var tempFile = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false);
+
+                        File.Copy(tempFile, path, true);
+
+                        try
                         {
-                            using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
-                            {
-                                await stream.CopyToAsync(fileStream).ConfigureAwait(false);
-                            }
+                            File.Delete(tempFile);
+                        }
+                        catch
+                        {
+
                         }
                     }
                 }

+ 5 - 4
MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs

@@ -116,7 +116,7 @@ namespace MediaBrowser.Providers.MediaInfo
                     imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ??
                     imageStreams.FirstOrDefault();
 
-                Stream stream;
+                string extractedImagePath;
 
                 if (imageStream != null)
                 {
@@ -135,7 +135,7 @@ namespace MediaBrowser.Providers.MediaInfo
                         }
                     }
 
-                    stream = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, videoIndex, cancellationToken).ConfigureAwait(false);
+                    extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, videoIndex, cancellationToken).ConfigureAwait(false);
                 }
                 else
                 {
@@ -146,14 +146,15 @@ namespace MediaBrowser.Providers.MediaInfo
                                           ? TimeSpan.FromTicks(Convert.ToInt64(item.RunTimeTicks.Value * .1))
                                           : TimeSpan.FromSeconds(10);
 
-                    stream = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
+                    extractedImagePath = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
                 }
 
                 return new DynamicImageResponse
                 {
                     Format = ImageFormat.Jpg,
                     HasImage = true,
-                    Stream = stream
+                    Path = extractedImagePath,
+                    Protocol = MediaProtocol.File
                 };
             }
             finally

+ 9 - 5
MediaBrowser.Server.Implementations/MediaEncoder/EncodingManager.cs

@@ -139,12 +139,16 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
                         {
 							_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
 
-                            using (var stream = await _encoder.ExtractVideoImage(inputPath, protocol, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false))
+                            var tempFile = await _encoder.ExtractVideoImage(inputPath, protocol, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false);
+                            File.Copy(tempFile, path, true);
+
+                            try
+                            {
+                                File.Delete(tempFile);
+                            }
+                            catch
                             {
-                                using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
-                                {
-                                    await stream.CopyToAsync(fileStream).ConfigureAwait(false);
-                                }
+                                
                             }
 
                             chapter.ImagePath = path;