Browse Source

improve embedded image extraction

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

+ 2 - 0
MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs

@@ -51,6 +51,8 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// <returns>Task{Stream}.</returns>
         Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
 
+        Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken);
+
         /// <summary>
         /// Extracts the video images on interval.
         /// </summary>

+ 6 - 2
MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs

@@ -484,12 +484,16 @@ namespace MediaBrowser.MediaEncoding.Encoder
             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<Stream> 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)
+        {
+            return ExtractImage(inputFiles, imageStreamIndex, protocol, false, null, null, cancellationToken);
+        }
+
         private async Task<Stream> ExtractImage(string[] inputFiles, int? imageStreamIndex, MediaProtocol protocol, bool isAudio,
             Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
         {

+ 6 - 2
MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs

@@ -138,10 +138,14 @@ namespace MediaBrowser.MediaEncoding.Probing
                     var parts = iTunEXTC.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries);
                     // Example 
                     // mpaa|G|100|For crude humor
-                    if (parts.Length == 4)
+                    if (parts.Length > 1)
                     {
                         info.OfficialRating = parts[1];
-                        info.OfficialRatingDescription = parts[3];
+
+                        if (parts.Length > 3)
+                        {
+                            info.OfficialRatingDescription = parts[3];
+                        }
                     }
                 }
 

+ 17 - 5
MediaBrowser.Model/Dlna/StreamBuilder.cs

@@ -520,7 +520,7 @@ namespace MediaBrowser.Model.Dlna
                 {
                     if (StringHelper.EqualsIgnoreCase(targetAudioCodec, "ac3"))
                     {
-                        defaultBitrate = 384000;
+                        defaultBitrate = 448000;
                     }
                     else
                     {
@@ -840,13 +840,25 @@ namespace MediaBrowser.Model.Dlna
 
         private bool IsAudioEligibleForDirectPlay(MediaSourceInfo item, int? maxBitrate)
         {
-            if (!maxBitrate.HasValue || (item.Bitrate.HasValue && item.Bitrate.Value <= maxBitrate.Value))
+            if (!maxBitrate.HasValue)
             {
-                return true;
+                _logger.Info("Cannot direct play due to unknown supported bitrate");
+                return false;
             }
 
-            _logger.Info("Bitrate exceeds DirectPlay limit");
-            return false;
+            if (!item.Bitrate.HasValue)
+            {
+                _logger.Info("Cannot direct play due to unknown content bitrate");
+                return false;
+            }
+
+            if (item.Bitrate.Value > maxBitrate.Value)
+            {
+                _logger.Info("Bitrate exceeds DirectPlay limit");
+                return false;
+            }
+
+            return true;
         }
 
         private void ValidateInput(VideoOptions options)

+ 6 - 6
MediaBrowser.Providers/Manager/ProviderUtils.cs

@@ -10,9 +10,9 @@ namespace MediaBrowser.Providers.Manager
     public static class ProviderUtils
     {
         public static void MergeBaseItemData<T>(MetadataResult<T> sourceResult,
-            MetadataResult<T> targetResult, 
-            List<MetadataFields> lockedFields, 
-            bool replaceData, 
+            MetadataResult<T> targetResult,
+            List<MetadataFields> lockedFields,
+            bool replaceData,
             bool mergeMetadataSettings)
             where T : BaseItem
         {
@@ -89,7 +89,7 @@ namespace MediaBrowser.Providers.Manager
             {
                 target.CustomRating = source.CustomRating;
             }
-            
+
             if (!lockedFields.Contains(MetadataFields.Overview))
             {
                 if (replaceData || string.IsNullOrEmpty(target.Overview))
@@ -107,7 +107,7 @@ namespace MediaBrowser.Providers.Manager
             {
                 if (replaceData || targetResult.People == null || targetResult.People.Count == 0)
                 {
-                    targetResult.People = sourceResult.People ?? new List<PersonInfo>();
+                    targetResult.People = sourceResult.People;
                 }
             }
 
@@ -238,7 +238,7 @@ namespace MediaBrowser.Providers.Manager
                 targetHasDisplayOrder.DisplayOrder = sourceHasDisplayOrder.DisplayOrder;
             }
         }
-        
+
         private static void MergeShortOverview(BaseItem source, BaseItem target, List<MetadataFields> lockedFields, bool replaceData)
         {
             var sourceHasShortOverview = source as IHasShortOverview;

+ 2 - 1
MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs

@@ -78,7 +78,8 @@ namespace MediaBrowser.Providers.MediaInfo
                         _fileSystem.CreateDirectory(Path.GetDirectoryName(path));
 
                         var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ??
-                            imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1);
+                            imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ??
+                            imageStreams.FirstOrDefault();
 
                         var imageStreamIndex = imageStream == null ? (int?)null : imageStream.Index;
 

+ 49 - 8
MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs

@@ -10,6 +10,8 @@ using MediaBrowser.Model.Logging;
 using MediaBrowser.Model.MediaInfo;
 using System;
 using System.Collections.Generic;
+using System.IO;
+using System.Linq;
 using System.Threading;
 using System.Threading.Tasks;
 using CommonIO;
@@ -93,20 +95,59 @@ namespace MediaBrowser.Providers.MediaInfo
 
             try
             {
-                // 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(Convert.ToInt64(item.RunTimeTicks.Value * .1))
-                                      : TimeSpan.FromSeconds(10);
-
                 var protocol = item.LocationType == LocationType.Remote
                     ? MediaProtocol.Http
                     : MediaProtocol.File;
 
                 var inputPath = MediaEncoderHelpers.GetInputArgument(_fileSystem, item.Path, protocol, isoMount, item.PlayableStreamFileNames);
 
-                var stream = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
+                var mediaStreams =
+                    item.GetMediaSources(false)
+                        .Take(1)
+                        .SelectMany(i => i.MediaStreams)
+                        .ToList();
+
+                var imageStreams =
+                    mediaStreams
+                        .Where(i => i.Type == MediaStreamType.EmbeddedImage)
+                        .ToList();
+
+                var imageStream = imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("front", StringComparison.OrdinalIgnoreCase) != -1) ??
+                    imageStreams.FirstOrDefault(i => (i.Comment ?? string.Empty).IndexOf("cover", StringComparison.OrdinalIgnoreCase) != -1) ??
+                    imageStreams.FirstOrDefault();
+
+                Stream stream;
+
+                if (imageStream != null)
+                {
+                    // Instead of using the raw stream index, we need to use nth video/embedded image stream
+                    var videoIndex = -1;
+                    foreach (var mediaStream in mediaStreams)
+                    {
+                        if (mediaStream.Type == MediaStreamType.Video ||
+                            mediaStream.Type == MediaStreamType.EmbeddedImage)
+                        {
+                            videoIndex++;
+                        }
+                        if (mediaStream == imageStream)
+                        {
+                            break;
+                        }
+                    }
+
+                    stream = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, videoIndex, cancellationToken).ConfigureAwait(false);
+                }
+                else
+                {
+                    // 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(Convert.ToInt64(item.RunTimeTicks.Value * .1))
+                                          : TimeSpan.FromSeconds(10);
+
+                    stream = await _mediaEncoder.ExtractVideoImage(inputPath, protocol, item.Video3DFormat, imageOffset, cancellationToken).ConfigureAwait(false);
+                }
 
                 return new DynamicImageResponse
                 {

+ 4 - 2
MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs

@@ -85,8 +85,6 @@ namespace MediaBrowser.XbmcMetadata.Parsers
         /// <param name="cancellationToken">The cancellation token.</param>
         private void Fetch(MetadataResult<T> item, string metadataFile, XmlReaderSettings settings, CancellationToken cancellationToken)
         {
-            item.ResetPeople();
-
             if (!SupportsUrlAfterClosingXmlTag)
             {
                 using (var streamReader = BaseNfoSaver.GetStreamReader(metadataFile))
@@ -94,6 +92,8 @@ namespace MediaBrowser.XbmcMetadata.Parsers
                     // Use XmlReader for best performance
                     using (var reader = XmlReader.Create(streamReader, settings))
                     {
+                        item.ResetPeople();
+
                         reader.MoveToContent();
 
                         // Loop through each element
@@ -113,6 +113,8 @@ namespace MediaBrowser.XbmcMetadata.Parsers
 
             using (var streamReader = BaseNfoSaver.GetStreamReader(metadataFile))
             {
+                item.ResetPeople();
+
                 // Need to handle a url after the xml data
                 // http://kodi.wiki/view/NFO_files/movies