瀏覽代碼

add error handling to work around skia crashes

Luke Pulverenti 7 年之前
父節點
當前提交
5fa007d04e

+ 53 - 9
Emby.Drawing.Skia/SkiaEncoder.cs

@@ -10,22 +10,27 @@ using System.IO;
 using System.Linq;
 using System.Reflection;
 using System.Threading.Tasks;
+using MediaBrowser.Controller.Extensions;
+using System.Globalization;
+using MediaBrowser.Model.Globalization;
 
 namespace Emby.Drawing.Skia
 {
     public class SkiaEncoder : IImageEncoder
     {
         private readonly ILogger _logger;
-        private readonly IApplicationPaths _appPaths;
+        private static IApplicationPaths _appPaths;
         private readonly Func<IHttpClient> _httpClientFactory;
         private readonly IFileSystem _fileSystem;
+        private static ILocalizationManager _localizationManager;
 
-        public SkiaEncoder(ILogger logger, IApplicationPaths appPaths, Func<IHttpClient> httpClientFactory, IFileSystem fileSystem)
+        public SkiaEncoder(ILogger logger, IApplicationPaths appPaths, Func<IHttpClient> httpClientFactory, IFileSystem fileSystem, ILocalizationManager localizationManager)
         {
             _logger = logger;
             _appPaths = appPaths;
             _httpClientFactory = httpClientFactory;
             _fileSystem = fileSystem;
+            _localizationManager = localizationManager;
 
             LogVersion();
         }
@@ -190,14 +195,53 @@ namespace Emby.Drawing.Skia
             }
         }
 
+        private static bool HasDiacritics(string text)
+        {
+            return !String.Equals(text, text.RemoveDiacritics(), StringComparison.Ordinal);
+        }
+
+        private static bool RequiresSpecialCharacterHack(string path)
+        {
+            if (_localizationManager.HasUnicodeCategory(path, UnicodeCategory.OtherLetter))
+            {
+                return true;
+            }
+
+            if (HasDiacritics(path))
+            {
+                return true;
+            }
+
+            return false;
+        }
+
+        private static string NormalizePath(string path, IFileSystem fileSystem)
+        {
+            if (!RequiresSpecialCharacterHack(path))
+            {
+                return path;
+            }
+
+            var tempPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + Path.GetExtension(path) ?? string.Empty);
+
+            fileSystem.CopyFile(path, tempPath, true);
+
+            return tempPath;
+        }
+
         private static string[] TransparentImageTypes = new string[] { ".png", ".gif", ".webp" };
-        internal static SKBitmap Decode(string path, bool forceCleanBitmap, out SKCodecOrigin origin)
+        internal static SKBitmap Decode(string path, bool forceCleanBitmap, IFileSystem fileSystem, out SKCodecOrigin origin)
         {
+            if (!fileSystem.FileExists(path))
+            {
+                throw new FileNotFoundException("File not found", path);
+            }
+
             var requiresTransparencyHack = TransparentImageTypes.Contains(Path.GetExtension(path) ?? string.Empty);
 
             if (requiresTransparencyHack || forceCleanBitmap)
             {
-                using (var stream = new SKFileStream(path))
+                using (var stream = new SKFileStream(NormalizePath(path, fileSystem)))
                 {
                     using (var codec = SKCodec.Create(stream))
                     {
@@ -227,11 +271,11 @@ namespace Emby.Drawing.Skia
                 }
             }
 
-            var resultBitmap = SKBitmap.Decode(path);
+            var resultBitmap = SKBitmap.Decode(NormalizePath(path, fileSystem));
 
             if (resultBitmap == null)
             {
-                return Decode(path, true, out origin);
+                return Decode(path, true, fileSystem, out origin);
             }
 
             // If we have to resize these they often end up distorted
@@ -239,7 +283,7 @@ namespace Emby.Drawing.Skia
             {
                 using (resultBitmap)
                 {
-                    return Decode(path, true, out origin);
+                    return Decode(path, true, fileSystem, out origin);
                 }
             }
 
@@ -251,13 +295,13 @@ namespace Emby.Drawing.Skia
         {
             if (cropWhitespace)
             {
-                using (var bitmap = Decode(path, forceAnalyzeBitmap, out origin))
+                using (var bitmap = Decode(path, forceAnalyzeBitmap, _fileSystem, out origin))
                 {
                     return CropWhiteSpace(bitmap);
                 }
             }
 
-            return Decode(path, forceAnalyzeBitmap, out origin);
+            return Decode(path, forceAnalyzeBitmap, _fileSystem, out origin);
         }
 
         private SKBitmap GetBitmap(string path, bool cropWhitespace, bool autoOrient)

+ 2 - 2
Emby.Drawing.Skia/StripCollageBuilder.cs

@@ -83,7 +83,7 @@ namespace Emby.Drawing.Skia
                 for (int i = 0; i < 4; i++)
                 {
                     SKCodecOrigin origin;
-                    using (var currentBitmap = SkiaEncoder.Decode(paths[imageIndex], false, out origin))
+                    using (var currentBitmap = SkiaEncoder.Decode(paths[imageIndex], false, _fileSystem, out origin))
                     {
                         // resize to the same aspect as the original
                         int iWidth = (int)Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height);
@@ -165,7 +165,7 @@ namespace Emby.Drawing.Skia
                     for (var y = 0; y < 2; y++)
                     {
                         SKCodecOrigin origin;
-                        using (var currentBitmap = SkiaEncoder.Decode(paths[imageIndex], false, out origin))
+                        using (var currentBitmap = SkiaEncoder.Decode(paths[imageIndex], false, _fileSystem, out origin))
                         {
                             using (var resizedBitmap = new SKBitmap(cellWidth, cellHeight, currentBitmap.ColorType, currentBitmap.AlphaType))
                             {

+ 4 - 2
MediaBrowser.Server.Mono/ImageEncoderHelper.cs

@@ -9,6 +9,7 @@ using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
 using Emby.Drawing.Skia;
 using MediaBrowser.Model.System;
+using MediaBrowser.Model.Globalization;
 
 namespace MediaBrowser.Server.Startup.Common
 {
@@ -20,13 +21,14 @@ namespace MediaBrowser.Server.Startup.Common
             StartupOptions startupOptions, 
             Func<IHttpClient> httpClient,
             IApplicationPaths appPaths,
-            IEnvironmentInfo environment)
+            IEnvironmentInfo environment,
+            ILocalizationManager localizationManager)
         {
             if (!startupOptions.ContainsOption("-enablegdi"))
             {
                 try
                 {
-                    return new SkiaEncoder(logManager.GetLogger("Skia"), appPaths, httpClient, fileSystem);
+                    return new SkiaEncoder(logManager.GetLogger("Skia"), appPaths, httpClient, fileSystem, localizationManager);
                 }
                 catch (Exception ex)
                 {

+ 1 - 1
MediaBrowser.Server.Mono/Program.cs

@@ -127,7 +127,7 @@ namespace MediaBrowser.Server.Mono
 
                 Task.WaitAll(task);
 
-                appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo);
+                appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => appHost.HttpClient, appPaths, environmentInfo, appHost.LocalizationManager);
 
                 Console.WriteLine("Running startup tasks");
 

+ 4 - 2
MediaBrowser.ServerApplication/ImageEncoderHelper.cs

@@ -7,6 +7,7 @@ using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Drawing;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Globalization;
 
 namespace MediaBrowser.Server.Startup.Common
 {
@@ -17,11 +18,12 @@ namespace MediaBrowser.Server.Startup.Common
             IFileSystem fileSystem,
             StartupOptions startupOptions,
             Func<IHttpClient> httpClient,
-            IApplicationPaths appPaths)
+            IApplicationPaths appPaths,
+            ILocalizationManager localizationManager)
         {
             try
             {
-                return new SkiaEncoder(logManager.GetLogger("Skia"), appPaths, httpClient, fileSystem);
+                return new SkiaEncoder(logManager.GetLogger("Skia"), appPaths, httpClient, fileSystem, localizationManager);
             }
             catch
             {

+ 15 - 2
MediaBrowser.ServerApplication/MainStartup.cs

@@ -304,6 +304,19 @@ namespace MediaBrowser.ServerApplication
             }
         }
 
+        private static string UpdatePackageFileName
+        {
+            get
+            {
+                if (Environment.Is64BitOperatingSystem)
+                {
+                    return "embyserver-win-x64-{version}.zip";
+                }
+
+                return "embyserver-win-x86-{version}.zip";
+            }
+        }
+
         /// <summary>
         /// Runs the application.
         /// </summary>
@@ -324,7 +337,7 @@ namespace MediaBrowser.ServerApplication
                 options,
                 fileSystem,
                 new PowerManagement(),
-                "emby.windows.zip",
+                UpdatePackageFileName,
                 environmentInfo,
                 new NullImageEncoder(),
                 new SystemEvents(logManager.GetLogger("SystemEvents")),
@@ -355,7 +368,7 @@ namespace MediaBrowser.ServerApplication
                 }
 
                 // set image encoder here
-                appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => appHost.HttpClient, appPaths);
+                appHost.ImageProcessor.ImageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => appHost.HttpClient, appPaths, appHost.LocalizationManager);
 
                 task = task.ContinueWith(new Action<Task>(a => appHost.RunStartupTasks()), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent);