浏览代码

update interlaced detection

Luke Pulverenti 9 年之前
父节点
当前提交
c8f65e7589

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

@@ -35,9 +35,10 @@ namespace MediaBrowser.Controller.MediaEncoding
         /// Extracts the audio image.
         /// </summary>
         /// <param name="path">The path.</param>
+        /// <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, CancellationToken cancellationToken);
+        Task<Stream> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken);
 
         /// <summary>
         /// Extracts the video image.

+ 0 - 1
MediaBrowser.Controller/MediaEncoding/MediaInfoRequest.cs

@@ -15,7 +15,6 @@ namespace MediaBrowser.Controller.MediaEncoding
         public IIsoMount MountedIso { get; set; }
         public VideoType VideoType { get; set; }
         public List<string> PlayableStreamFileNames { get; set; }
-        public bool ExtractKeyFrameInterval { get; set; }
 
         public MediaInfoRequest()
         {

+ 1 - 1
MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs

@@ -505,7 +505,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
             {
                 return "libx264";
             }
-            if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase))
+            if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase))
             {
                 return "libx265";
             }

+ 43 - 30
MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs

@@ -258,17 +258,17 @@ namespace MediaBrowser.MediaEncoding.Encoder
 
                     var mediaInfo = new ProbeResultNormalizer(_logger, FileSystem).GetMediaInfo(result, videoType, isAudio, primaryPath, protocol);
 
-                    //var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
+                    var videoStream = mediaInfo.MediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
 
-                    //if (videoStream != null)
-                    //{
-                    //    var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false);
+                    if (videoStream != null)
+                    {
+                        var isInterlaced = await DetectInterlaced(mediaInfo, videoStream, inputPath, probeSizeArgument).ConfigureAwait(false);
 
-                    //    if (isInterlaced)
-                    //    {
-                    //        videoStream.IsInterlaced = true;
-                    //    }
-                    //}
+                        if (isInterlaced)
+                        {
+                            videoStream.IsInterlaced = true;
+                        }
+                    }
 
                     return mediaInfo;
                 }
@@ -292,19 +292,22 @@ namespace MediaBrowser.MediaEncoding.Encoder
                 return false;
             }
 
-            var formats = (video.Container ?? string.Empty).Split(',').ToList();
-
-            // Take a shortcut and limit this to containers that are likely to have interlaced content
-            if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) &&
-                !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) &&
-                !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) &&
-                !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) &&
-                !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase))
+            // If the video codec is not some form of mpeg, then take a shortcut and limit this to containers that are likely to have interlaced content
+            if ((videoStream.Codec ?? string.Empty).IndexOf("mpeg", StringComparison.OrdinalIgnoreCase) == -1)
             {
-                return false;
+                var formats = (video.Container ?? string.Empty).Split(',').ToList();
+
+                if (!formats.Contains("vob", StringComparer.OrdinalIgnoreCase) &&
+                    !formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) &&
+                    !formats.Contains("ts", StringComparer.OrdinalIgnoreCase) &&
+                    !formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) &&
+                    !formats.Contains("wtv", StringComparer.OrdinalIgnoreCase))
+                {
+                    return false;
+                }
             }
 
-            var args = "{0} -i {1} -map 0:v:{2} -filter:v idet -frames:v 500 -an -f null /dev/null";
+            var args = "{0} -i {1} -map 0:v:{2} -an -filter:v idet -frames:v 500 -an -f null /dev/null";
 
             var process = new Process
             {
@@ -444,7 +447,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
                 return false;
             }
 
-            if (((tff + bff) / total) >= .65)
+            if (((tff + bff) / total) >= .4)
             {
                 return true;
             }
@@ -469,29 +472,37 @@ namespace MediaBrowser.MediaEncoding.Encoder
         /// </summary>
         protected readonly CultureInfo UsCulture = new CultureInfo("en-US");
 
-        public Task<Stream> ExtractAudioImage(string path, CancellationToken cancellationToken)
+        public Task<Stream> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken)
         {
-            return ExtractImage(new[] { path }, MediaProtocol.File, true, null, null, 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)
         {
-            return ExtractImage(inputFiles, protocol, false, threedFormat, offset, cancellationToken);
+            return ExtractImage(inputFiles, null, protocol, false, threedFormat, offset, cancellationToken);
         }
 
-        private async Task<Stream> ExtractImage(string[] inputFiles, MediaProtocol protocol, bool isAudio,
+        private async Task<Stream> ExtractImage(string[] inputFiles, int? imageStreamIndex, MediaProtocol protocol, bool isAudio,
             Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken)
         {
             var resourcePool = isAudio ? _audioImageResourcePool : _videoImageResourcePool;
 
             var inputArgument = GetInputArgument(inputFiles, protocol);
 
-            if (!isAudio)
+            if (isAudio)
+            {
+                //if (imageStreamIndex.HasValue && imageStreamIndex.Value > 0)
+                //{
+                //    // It seems for audio files we need to subtract 1 (for the audio stream??)
+                //    imageStreamIndex = imageStreamIndex.Value - 1;
+                //}
+            }
+            else
             {
                 try
                 {
-                    return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
+                    return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, true, resourcePool, cancellationToken).ConfigureAwait(false);
                 }
                 catch (ArgumentException)
                 {
@@ -503,10 +514,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
                 }
             }
 
-            return await ExtractImageInternal(inputArgument, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false);
+            return await ExtractImageInternal(inputArgument, imageStreamIndex, protocol, threedFormat, offset, false, resourcePool, cancellationToken).ConfigureAwait(false);
         }
 
-        private async Task<Stream> ExtractImageInternal(string inputPath, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
+        private async Task<Stream> ExtractImageInternal(string inputPath, int? imageStreamIndex, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, bool useIFrame, SemaphoreSlim resourcePool, CancellationToken cancellationToken)
         {
             if (string.IsNullOrEmpty(inputPath))
             {
@@ -540,9 +551,11 @@ 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} -threads 1 -v quiet -vframes 1 -vf \"{2},thumbnail=30\" -f image2 \"{1}\"", inputPath, "-", vf) :
-                string.Format("-i {0} -threads 1 -v quiet -vframes 1 -vf \"{2}\" -f image2 \"{1}\"", inputPath, "-", vf);
+            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 probeSize = GetProbeSizeArgument(new[] { inputPath }, protocol);
 

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

@@ -141,6 +141,7 @@ namespace MediaBrowser.MediaEncoding.Probing
             if (streamInfo.tags != null)
             {
                 stream.Language = GetDictionaryValue(streamInfo.tags, "language");
+                stream.Comment = GetDictionaryValue(streamInfo.tags, "comment");
             }
 
             if (string.Equals(streamInfo.codec_type, "audio", StringComparison.OrdinalIgnoreCase))
@@ -872,7 +873,7 @@ namespace MediaBrowser.MediaEncoding.Probing
             }
         }
 
-        private void ExtractTimestamp(Model.MediaInfo.MediaInfo video)
+        private void ExtractTimestamp(MediaInfo video)
         {
             if (video.VideoType == VideoType.VideoFile)
             {

+ 3 - 0
MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj

@@ -827,6 +827,9 @@
     <Compile Include="..\MediaBrowser.Model\MediaInfo\VideoCodec.cs">
       <Link>MediaInfo\VideoCodec.cs</Link>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\Net\EndPointInfo.cs">
+      <Link>Net\EndPointInfo.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\Net\HttpException.cs">
       <Link>Net\HttpException.cs</Link>
     </Compile>

+ 3 - 0
MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj

@@ -783,6 +783,9 @@
     <Compile Include="..\MediaBrowser.Model\MediaInfo\VideoCodec.cs">
       <Link>MediaInfo\VideoCodec.cs</Link>
     </Compile>
+    <Compile Include="..\MediaBrowser.Model\Net\EndPointInfo.cs">
+      <Link>Net\EndPointInfo.cs</Link>
+    </Compile>
     <Compile Include="..\MediaBrowser.Model\Net\HttpException.cs">
       <Link>Net\HttpException.cs</Link>
     </Compile>

+ 6 - 0
MediaBrowser.Model/Entities/MediaStream.cs

@@ -30,6 +30,12 @@ namespace MediaBrowser.Model.Entities
         /// <value>The language.</value>
         public string Language { get; set; }
 
+        /// <summary>
+        /// Gets or sets the comment.
+        /// </summary>
+        /// <value>The comment.</value>
+        public string Comment { get; set; }
+        
         /// <summary>
         /// Gets or sets a value indicating whether this instance is interlaced.
         /// </summary>

+ 1 - 0
MediaBrowser.Model/MediaBrowser.Model.csproj

@@ -162,6 +162,7 @@
     <Compile Include="MediaInfo\MediaProtocol.cs" />
     <Compile Include="MediaInfo\SubtitleTrackEvent.cs" />
     <Compile Include="MediaInfo\SubtitleTrackInfo.cs" />
+    <Compile Include="Net\EndPointInfo.cs" />
     <Compile Include="Net\HttpResponse.cs" />
     <Compile Include="Net\MimeTypes.cs" />
     <Compile Include="Notifications\NotificationOption.cs" />

+ 8 - 0
MediaBrowser.Model/Net/EndPointInfo.cs

@@ -0,0 +1,8 @@
+namespace MediaBrowser.Model.Net
+{
+    public class EndPointInfo
+    {
+        public bool IsLocal { get; set; }
+        public bool IsInNetwork { get; set; }
+    }
+}

+ 21 - 8
MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using System;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
@@ -43,20 +44,27 @@ namespace MediaBrowser.Providers.MediaInfo
         {
             var audio = (Audio)item;
 
+            var imageStreams =
+                audio.GetMediaSources(false)
+                    .Take(1)
+                    .SelectMany(i => i.MediaStreams)
+                    .Where(i => i.Type == MediaStreamType.EmbeddedImage)
+                    .ToList();
+
             // Can't extract if we didn't find a video stream in the file
-            if (!audio.GetMediaSources(false).Take(1).SelectMany(i => i.MediaStreams).Any(i => i.Type == MediaStreamType.EmbeddedImage))
+            if (imageStreams.Count == 0)
             {
                 return Task.FromResult(new DynamicImageResponse { HasImage = false });
             }
 
-            return GetImage((Audio)item, cancellationToken);
+            return GetImage((Audio)item, imageStreams, cancellationToken);
         }
 
-        public async Task<DynamicImageResponse> GetImage(Audio item, CancellationToken cancellationToken)
+        public async Task<DynamicImageResponse> GetImage(Audio item, List<MediaStream> imageStreams, CancellationToken cancellationToken)
         {
             var path = GetAudioImagePath(item);
 
-			if (!_fileSystem.FileExists(path))
+            if (!_fileSystem.FileExists(path))
             {
                 var semaphore = GetLock(path);
 
@@ -66,11 +74,16 @@ namespace MediaBrowser.Providers.MediaInfo
                 try
                 {
                     // Check again in case it was saved while waiting for the lock
-					if (!_fileSystem.FileExists(path))
+                    if (!_fileSystem.FileExists(path))
                     {
-						_fileSystem.CreateDirectory(Path.GetDirectoryName(path));
+                        _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);
+
+                        var imageStreamIndex = imageStream == null ? (int?)null : imageStream.Index;
 
-                        using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, cancellationToken).ConfigureAwait(false))
+                        using (var stream = await _mediaEncoder.ExtractAudioImage(item.Path, imageStreamIndex, cancellationToken).ConfigureAwait(false))
                         {
                             using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
                             {