瀏覽代碼

Split EmbeddedImage extracting to new provider

Joe Rogers 3 年之前
父節點
當前提交
be9ed29f63

+ 123 - 0
MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs

@@ -0,0 +1,123 @@
+#nullable enable
+#pragma warning disable CS1591
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.MediaEncoding;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Drawing;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.MediaInfo;
+using Microsoft.Extensions.Logging;
+
+namespace MediaBrowser.Providers.MediaInfo
+{
+    /// <summary>
+    /// Uses ffmpeg to extract embedded images.
+    /// </summary>
+    public class EmbeddedImageProvider : IDynamicImageProvider, IHasOrder
+    {
+        private readonly IMediaEncoder _mediaEncoder;
+        private readonly ILogger<EmbeddedImageProvider> _logger;
+
+        public EmbeddedImageProvider(IMediaEncoder mediaEncoder, ILogger<EmbeddedImageProvider> logger)
+        {
+            _mediaEncoder = mediaEncoder;
+            _logger = logger;
+        }
+
+        /// <inheritdoc />
+        public string Name => "Embedded Image Extractor";
+
+        /// <inheritdoc />
+        // Default to after internet image providers but before Screen Grabber
+        public int Order => 99;
+
+        /// <inheritdoc />
+        public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
+        {
+            return new[] { ImageType.Primary };
+        }
+
+        /// <inheritdoc />
+        public Task<DynamicImageResponse> GetImage(BaseItem item, ImageType type, CancellationToken cancellationToken)
+        {
+            var video = (Video)item;
+
+            // No support for these
+            if (video.IsPlaceHolder || video.VideoType == VideoType.Dvd)
+            {
+                return Task.FromResult(new DynamicImageResponse { HasImage = false });
+            }
+
+            // Can't extract if we didn't find any video streams in the file
+            if (!video.DefaultVideoStreamIndex.HasValue)
+            {
+                _logger.LogInformation("Skipping image extraction due to missing DefaultVideoStreamIndex for {Path}.", video.Path ?? string.Empty);
+                return Task.FromResult(new DynamicImageResponse { HasImage = false });
+            }
+
+            return GetEmbeddedImage(video, cancellationToken);
+        }
+
+        private async Task<DynamicImageResponse> GetEmbeddedImage(Video item, CancellationToken cancellationToken)
+        {
+            MediaSourceInfo mediaSource = new MediaSourceInfo
+            {
+                VideoType = item.VideoType,
+                IsoType = item.IsoType,
+                Protocol = item.PathProtocol ?? MediaProtocol.File,
+            };
+
+            var imageStreams =
+                item.GetMediaStreams()
+                    .Where(i => i.Type == MediaStreamType.EmbeddedImage)
+                    .ToList();
+
+            string extractedImagePath;
+
+            if (imageStreams.Count == 0)
+            {
+                // Can't extract if we don't have any EmbeddedImage streams
+                return new DynamicImageResponse { HasImage = false };
+            }
+            else
+            {
+                var imageStream = imageStreams.Find(i => (i.Comment ?? string.Empty).Contains("front", StringComparison.OrdinalIgnoreCase))
+                    ?? imageStreams.Find(i => (i.Comment ?? string.Empty).Contains("cover", StringComparison.OrdinalIgnoreCase))
+                    ?? imageStreams[0];
+
+                extractedImagePath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, imageStream, imageStream.Index, cancellationToken).ConfigureAwait(false);
+            }
+
+            return new DynamicImageResponse
+            {
+                Format = ImageFormat.Jpg,
+                HasImage = true,
+                Path = extractedImagePath,
+                Protocol = MediaProtocol.File
+            };
+        }
+
+        /// <inheritdoc />
+        public bool Supports(BaseItem item)
+        {
+            if (item.IsShortcut)
+            {
+                return false;
+            }
+
+            if (!item.IsFileProtocol)
+            {
+                return false;
+            }
+
+            return item is Video video && !video.IsPlaceHolder && video.IsCompleteMedia;
+        }
+    }
+}

+ 11 - 29
MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs

@@ -17,6 +17,9 @@ using Microsoft.Extensions.Logging;
 
 namespace MediaBrowser.Providers.MediaInfo
 {
+    /// <summary>
+    /// Uses ffmpeg to create still images from the main video.
+    /// </summary>
     public class VideoImageProvider : IDynamicImageProvider, IHasOrder
     {
         private readonly IMediaEncoder _mediaEncoder;
@@ -71,36 +74,15 @@ namespace MediaBrowser.Providers.MediaInfo
                 Protocol = item.PathProtocol ?? MediaProtocol.File,
             };
 
-            var mediaStreams =
-                item.GetMediaStreams();
+            // If we know the duration, grab it from 10% into the video. Otherwise just 10 seconds in.
+            // Always use 10 seconds for dvd because our duration could be out of whack
+            var imageOffset = item.VideoType != VideoType.Dvd && item.RunTimeTicks.HasValue &&
+                              item.RunTimeTicks.Value > 0
+                                  ? TimeSpan.FromTicks(item.RunTimeTicks.Value / 10)
+                                  : TimeSpan.FromSeconds(10);
 
-            var imageStreams =
-                mediaStreams
-                    .Where(i => i.Type == MediaStreamType.EmbeddedImage)
-                    .ToList();
-
-            string extractedImagePath;
-
-            if (imageStreams.Count == 0)
-            {
-                // If we know the duration, grab it from 10% into the video. Otherwise just 10 seconds in.
-                // Always use 10 seconds for dvd because our duration could be out of whack
-                var imageOffset = item.VideoType != VideoType.Dvd && item.RunTimeTicks.HasValue &&
-                                  item.RunTimeTicks.Value > 0
-                                      ? TimeSpan.FromTicks(item.RunTimeTicks.Value / 10)
-                                      : TimeSpan.FromSeconds(10);
-
-                var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
-                extractedImagePath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, videoStream, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
-            }
-            else
-            {
-                var imageStream = imageStreams.Find(i => (i.Comment ?? string.Empty).Contains("front", StringComparison.OrdinalIgnoreCase))
-                    ?? imageStreams.Find(i => (i.Comment ?? string.Empty).Contains("cover", StringComparison.OrdinalIgnoreCase))
-                    ?? imageStreams[0];
-
-                extractedImagePath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, imageStream, imageStream.Index, cancellationToken).ConfigureAwait(false);
-            }
+            var videoStream = item.GetMediaStreams().FirstOrDefault(i => i.Type == MediaStreamType.Video);
+            string extractedImagePath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, videoStream, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
 
             return new DynamicImageResponse
             {