Browse Source

Add handling for embedded background and logo

Joe Rogers 3 years ago
parent
commit
6ce8cce12c

+ 11 - 4
MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs

@@ -735,14 +735,15 @@ namespace MediaBrowser.MediaEncoding.Probing
                 else if (string.Equals(stream.Codec, "mjpeg", StringComparison.OrdinalIgnoreCase))
                 {
                     // How to differentiate between video and embedded image?
-                    // The only difference I've seen thus far is presence of codec tag, also embedded images have high (unusual) framerates
-                    if (!string.IsNullOrWhiteSpace(stream.CodecTag))
+                    // check disposition, alternately: presence of codec tag, also embedded images have high (unusual) framerates
+                    if ((streamInfo.Disposition != null && streamInfo.Disposition.GetValueOrDefault("attached_pic") == 1) ||
+                        string.IsNullOrWhiteSpace(stream.CodecTag))
                     {
-                        stream.Type = MediaStreamType.Video;
+                        stream.Type = MediaStreamType.EmbeddedImage;
                     }
                     else
                     {
-                        stream.Type = MediaStreamType.EmbeddedImage;
+                        stream.Type = MediaStreamType.Video;
                     }
                 }
                 else
@@ -811,6 +812,12 @@ namespace MediaBrowser.MediaEncoding.Probing
                 {
                     stream.ColorPrimaries = streamInfo.ColorPrimaries;
                 }
+
+                // workaround for mkv attached_pics losing filename due to being classified as video based on codec
+                if (stream.Type == MediaStreamType.EmbeddedImage && streamInfo.Tags != null && string.IsNullOrEmpty(stream.Comment))
+                {
+                    stream.Comment = GetDictionaryValue(streamInfo.Tags, "filename");
+                }
             }
             else
             {

+ 79 - 12
MediaBrowser.Providers/MediaInfo/EmbeddedImageProvider.cs

@@ -3,10 +3,12 @@
 
 using System;
 using System.Collections.Generic;
+using System.Collections.Immutable;
 using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Entities.TV;
 using MediaBrowser.Controller.MediaEncoding;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Drawing;
@@ -22,6 +24,27 @@ namespace MediaBrowser.Providers.MediaInfo
     /// </summary>
     public class EmbeddedImageProvider : IDynamicImageProvider, IHasOrder
     {
+        private static readonly string[] _primaryImageFileNames =
+        {
+            "poster",
+            "folder",
+            "cover",
+            "default"
+        };
+
+        private static readonly string[] _backdropImageFileNames =
+        {
+            "backdrop",
+            "fanart",
+            "background",
+            "art"
+        };
+
+        private static readonly string[] _logoImageFileNames =
+        {
+            "logo",
+        };
+
         private readonly IMediaEncoder _mediaEncoder;
         private readonly ILogger<EmbeddedImageProvider> _logger;
 
@@ -41,7 +64,25 @@ namespace MediaBrowser.Providers.MediaInfo
         /// <inheritdoc />
         public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
         {
-            return new[] { ImageType.Primary };
+            if (item is Video)
+            {
+                if (item is Episode)
+                {
+                    return new List<ImageType>
+                    {
+                        ImageType.Primary,
+                    };
+                }
+
+                return new List<ImageType>
+                {
+                    ImageType.Primary,
+                    ImageType.Backdrop,
+                    ImageType.Logo,
+                };
+            }
+
+            return ImmutableList<ImageType>.Empty;
         }
 
         /// <inheritdoc />
@@ -62,10 +103,10 @@ namespace MediaBrowser.Providers.MediaInfo
                 return Task.FromResult(new DynamicImageResponse { HasImage = false });
             }
 
-            return GetEmbeddedImage(video, cancellationToken);
+            return GetEmbeddedImage(video, type, cancellationToken);
         }
 
-        private async Task<DynamicImageResponse> GetEmbeddedImage(Video item, CancellationToken cancellationToken)
+        private async Task<DynamicImageResponse> GetEmbeddedImage(Video item, ImageType type, CancellationToken cancellationToken)
         {
             MediaSourceInfo mediaSource = new MediaSourceInfo
             {
@@ -74,27 +115,53 @@ namespace MediaBrowser.Providers.MediaInfo
                 Protocol = item.PathProtocol ?? MediaProtocol.File,
             };
 
+            string[] imageFileNames;
+            switch (type)
+            {
+                case ImageType.Backdrop:
+                    imageFileNames = _backdropImageFileNames;
+                    break;
+                case ImageType.Logo:
+                    imageFileNames = _logoImageFileNames;
+                    break;
+                case ImageType.Primary:
+                default:
+                    imageFileNames = _primaryImageFileNames;
+                    break;
+            }
+
             var imageStreams =
                 item.GetMediaStreams()
                     .Where(i => i.Type == MediaStreamType.EmbeddedImage)
                     .ToList();
 
-            string extractedImagePath;
-
-            if (imageStreams.Count == 0)
+            if (!imageStreams.Any())
             {
                 // 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);
+            // Extract first stream containing an element of imageFileNames
+            var imageStream = imageStreams
+                .Where(stream => !string.IsNullOrEmpty(stream.Comment))
+                .First(stream => imageFileNames.Any(name => stream.Comment.Contains(name, StringComparison.OrdinalIgnoreCase)));
+
+            // Primary type only: default to first image if none found by label
+            if (imageStream == null)
+            {
+                if (type == ImageType.Primary)
+                {
+                    imageStream = imageStreams[0];
+                }
+                else
+                {
+                    // No streams matched, abort
+                    return new DynamicImageResponse { HasImage = false };
+                }
             }
 
+            string extractedImagePath = await _mediaEncoder.ExtractVideoImage(item.Path, item.Container, mediaSource, imageStream, imageStream.Index, cancellationToken).ConfigureAwait(false);
+
             return new DynamicImageResponse
             {
                 Format = ImageFormat.Jpg,