diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2015-04-23 12:50:54 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2015-04-23 12:50:54 -0400 |
| commit | 6f016525208f665502d844d151c31e9ff38fd20a (patch) | |
| tree | d9c5905af8a4684b13eb6eb00584bfbb66a4e1fc | |
| parent | 7ac8fd1c68ec9b58d17180b50a2555dd469ba535 (diff) | |
control the number of simultaneous image operations
7 files changed, 85 insertions, 48 deletions
diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs index 55c6f6455..6365bd294 100644 --- a/Emby.Drawing/ImageProcessor.cs +++ b/Emby.Drawing/ImageProcessor.cs @@ -51,6 +51,7 @@ namespace Emby.Drawing private readonly IJsonSerializer _jsonSerializer; private readonly IServerApplicationPaths _appPaths; private readonly IImageEncoder _imageEncoder; + private readonly SemaphoreSlim _imageProcessingSemaphore; public ImageProcessor(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem, IJsonSerializer jsonSerializer, IImageEncoder imageEncoder) { @@ -88,6 +89,8 @@ namespace Emby.Drawing } _cachedImagedSizes = new ConcurrentDictionary<Guid, ImageSize>(sizeDictionary); + var count = Environment.ProcessorCount; + _imageProcessingSemaphore = new SemaphoreSlim(count, count); } public string[] SupportedInputFormats @@ -201,6 +204,8 @@ namespace Emby.Drawing await semaphore.WaitAsync().ConfigureAwait(false); + var imageProcessingLockTaken = false; + try { CheckDisposed(); @@ -212,11 +217,20 @@ namespace Emby.Drawing Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + + imageProcessingLockTaken = true; + _imageEncoder.EncodeImage(originalImagePath, cacheFilePath, newWidth, newHeight, quality, options); } } finally { + if (imageProcessingLockTaken) + { + _imageProcessingSemaphore.Release(); + } + semaphore.Release(); } @@ -254,10 +268,15 @@ namespace Emby.Drawing return GetResult(croppedImagePath); } + var imageProcessingLockTaken = false; + try { Directory.CreateDirectory(Path.GetDirectoryName(croppedImagePath)); + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + imageProcessingLockTaken = true; + _imageEncoder.CropWhiteSpace(originalImagePath, croppedImagePath); } catch (Exception ex) @@ -269,6 +288,11 @@ namespace Emby.Drawing } finally { + if (imageProcessingLockTaken) + { + _imageProcessingSemaphore.Release(); + } + semaphore.Release(); } @@ -592,13 +616,25 @@ namespace Emby.Drawing return enhancedImagePath; } + var imageProcessingLockTaken = false; + try { Directory.CreateDirectory(Path.GetDirectoryName(enhancedImagePath)); + + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + + imageProcessingLockTaken = true; + await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, enhancedImagePath, item, imageType, imageIndex).ConfigureAwait(false); } finally { + if (imageProcessingLockTaken) + { + _imageProcessingSemaphore.Release(); + } + semaphore.Release(); } @@ -717,9 +753,18 @@ namespace Emby.Drawing return Path.Combine(path, filename); } - public void CreateImageCollage(ImageCollageOptions options) + public async Task CreateImageCollage(ImageCollageOptions options) { - _imageEncoder.CreateImageCollage(options); + await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false); + + try + { + _imageEncoder.CreateImageCollage(options); + } + finally + { + _imageProcessingSemaphore.Release(); + } } public IEnumerable<IImageEnhancer> GetSupportedEnhancers(IHasImages item, ImageType imageType) diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 685d2706d..aeb817392 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -104,6 +104,6 @@ namespace MediaBrowser.Controller.Drawing /// Creates the image collage. /// </summary> /// <param name="options">The options.</param> - void CreateImageCollage(ImageCollageOptions options); + Task CreateImageCollage(ImageCollageOptions options); } } diff --git a/MediaBrowser.Model/Configuration/EncodingOptions.cs b/MediaBrowser.Model/Configuration/EncodingOptions.cs index c44a7c94d..afd67eb15 100644 --- a/MediaBrowser.Model/Configuration/EncodingOptions.cs +++ b/MediaBrowser.Model/Configuration/EncodingOptions.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Model.Configuration DownMixAudioBoost = 2; EncodingQuality = EncodingQuality.Auto; EnableThrottling = true; - ThrottleThresholdSeconds = 90; + ThrottleThresholdSeconds = 120; } } } diff --git a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 3fa0df760..2106a58de 100644 --- a/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/MediaBrowser.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -88,7 +88,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints NatUtility.UnhandledException += NatUtility_UnhandledException; NatUtility.StartDiscovery(); - _timer = new Timer(s => _createdRules = new List<string>(), null, TimeSpan.FromMinutes(3), TimeSpan.FromMinutes(3)); + _timer = new Timer(s => _createdRules = new List<string>(), null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); _lastConfigIdentifier = GetConfigIdentifier(); @@ -97,17 +97,17 @@ namespace MediaBrowser.Server.Implementations.EntryPoints void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e) { - //var ex = e.ExceptionObject as Exception; - - //if (ex == null) - //{ - // _logger.Error("Unidentified error reported by Mono.Nat"); - //} - //else - //{ - // // Seeing some blank exceptions coming through here - // _logger.ErrorException("Error reported by Mono.Nat: ", ex); - //} + var ex = e.ExceptionObject as Exception; + + if (ex == null) + { + //_logger.Error("Unidentified error reported by Mono.Nat"); + } + else + { + // Seeing some blank exceptions coming through here + _logger.ErrorException("Error reported by Mono.Nat: ", ex); + } } void NatUtility_DeviceFound(object sender, DeviceEventArgs e) diff --git a/MediaBrowser.Server.Implementations/Library/UserManager.cs b/MediaBrowser.Server.Implementations/Library/UserManager.cs index 03471a8e9..02e1795f3 100644 --- a/MediaBrowser.Server.Implementations/Library/UserManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserManager.cs @@ -345,7 +345,7 @@ namespace MediaBrowser.Server.Implementations.Library { var name = MakeValidUsername(Environment.UserName); - var user = InstantiateNewUser(name, false); + var user = InstantiateNewUser(name); user.DateLastSaved = DateTime.UtcNow; @@ -552,7 +552,7 @@ namespace MediaBrowser.Server.Implementations.Library try { - var user = InstantiateNewUser(name, true); + var user = InstantiateNewUser(name); var list = Users.ToList(); list.Add(user); @@ -697,21 +697,13 @@ namespace MediaBrowser.Server.Implementations.Library /// Instantiates the new user. /// </summary> /// <param name="name">The name.</param> - /// <param name="checkId">if set to <c>true</c> [check identifier].</param> /// <returns>User.</returns> - private User InstantiateNewUser(string name, bool checkId) + private User InstantiateNewUser(string name) { - var id = ("MBUser" + name).GetMD5(); - - if (checkId && Users.Select(i => i.Id).Contains(id)) - { - id = Guid.NewGuid(); - } - return new User { Name = name, - Id = id, + Id = Guid.NewGuid(), DateCreated = DateTime.UtcNow, DateModified = DateTime.UtcNow, UsesIdForConfigurationPath = true diff --git a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs index 15c43213f..be71a6408 100644 --- a/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Photos/BaseDynamicImageProvider.cs @@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Photos { var outputPath = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid() + ".png"); Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); - var imageCreated = CreateImage(item, itemsWithImages, outputPath, imageType, 0); + var imageCreated = await CreateImage(item, itemsWithImages, outputPath, imageType, 0).ConfigureAwait(false); if (!imageCreated) { @@ -103,9 +103,9 @@ namespace MediaBrowser.Server.Implementations.Photos return parts.GetMD5().ToString("N"); } - protected void CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, bool drawText) + protected Task CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, bool drawText) { - CreateCollage(primaryItem, items, outputPath, 960, 540, drawText, primaryItem.Name); + return CreateCollage(primaryItem, items, outputPath, 960, 540, drawText, primaryItem.Name); } protected virtual IEnumerable<string> GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable<BaseItem> items) @@ -115,22 +115,22 @@ namespace MediaBrowser.Server.Implementations.Photos .Where(i => !string.IsNullOrWhiteSpace(i)); } - protected void CreatePosterCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath) + protected Task CreatePosterCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath) { - CreateCollage(primaryItem, items, outputPath, 600, 900, true, primaryItem.Name); + return CreateCollage(primaryItem, items, outputPath, 600, 900, true, primaryItem.Name); } - protected void CreateSquareCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, bool drawText) + protected Task CreateSquareCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, bool drawText) { - CreateCollage(primaryItem, items, outputPath, 800, 800, drawText, primaryItem.Name); + return CreateCollage(primaryItem, items, outputPath, 800, 800, drawText, primaryItem.Name); } - protected void CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height, bool drawText, string text) + protected Task CreateThumbCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height, bool drawText, string text) { - CreateCollage(primaryItem, items, outputPath, width, height, drawText, text); + return CreateCollage(primaryItem, items, outputPath, width, height, drawText, text); } - private void CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height, bool drawText, string text) + private Task CreateCollage(IHasImages primaryItem, List<BaseItem> items, string outputPath, int width, int height, bool drawText, string text) { Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); @@ -143,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.Photos InputPaths = GetStripCollageImagePaths(primaryItem, items).ToArray() }; - ImageProcessor.CreateImageCollage(options); + return ImageProcessor.CreateImageCollage(options); } public string Name @@ -151,7 +151,7 @@ namespace MediaBrowser.Server.Implementations.Photos get { return "Dynamic Image Provider"; } } - protected virtual bool CreateImage(IHasImages item, + protected virtual async Task<bool> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPath, ImageType imageType, @@ -166,7 +166,7 @@ namespace MediaBrowser.Server.Implementations.Photos if (imageType == ImageType.Thumb) { - CreateThumbCollage(item, itemsWithImages, outputPath, drawText); + await CreateThumbCollage(item, itemsWithImages, outputPath, drawText).ConfigureAwait(false); return true; } @@ -174,15 +174,15 @@ namespace MediaBrowser.Server.Implementations.Photos { if (item is UserView) { - CreateSquareCollage(item, itemsWithImages, outputPath, drawText); + await CreateSquareCollage(item, itemsWithImages, outputPath, drawText).ConfigureAwait(false); } else if (item is PhotoAlbum || item is Playlist) { - CreateSquareCollage(item, itemsWithImages, outputPath, drawText); + await CreateSquareCollage(item, itemsWithImages, outputPath, drawText).ConfigureAwait(false); } else { - CreatePosterCollage(item, itemsWithImages, outputPath); + await CreatePosterCollage(item, itemsWithImages, outputPath).ConfigureAwait(false); } return true; @@ -234,7 +234,7 @@ namespace MediaBrowser.Server.Implementations.Photos protected virtual List<BaseItem> GetFinalItems(List<BaseItem> items, int limit) { // Rotate the images once every x days - var random = DateTime.Now.DayOfYear % 5; + var random = DateTime.Now.DayOfYear % 7; return items .OrderBy(i => (random + "" + items.IndexOf(i)).GetMD5()) diff --git a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs index 4a4d90d14..24dc2cc1d 100644 --- a/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs +++ b/MediaBrowser.Server.Implementations/UserViews/DynamicImageProvider.cs @@ -216,7 +216,7 @@ namespace MediaBrowser.Server.Implementations.UserViews return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty); } - protected override bool CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPath, ImageType imageType, int imageIndex) + protected override async Task<bool> CreateImage(IHasImages item, List<BaseItem> itemsWithImages, string outputPath, ImageType imageType, int imageIndex) { var view = (UserView)item; if (imageType == ImageType.Primary && IsUsingCollectionStrip(view)) @@ -226,11 +226,11 @@ namespace MediaBrowser.Server.Implementations.UserViews return false; } - CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540, false, item.Name); + await CreateThumbCollage(item, itemsWithImages, outputPath, 960, 540, false, item.Name).ConfigureAwait(false); return true; } - return base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex); + return await base.CreateImage(item, itemsWithImages, outputPath, imageType, imageIndex).ConfigureAwait(false); } protected override IEnumerable<String> GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable<BaseItem> items) |
