mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-09 03:04:24 -04:00
control the number of simultaneous image operations
This commit is contained in:
parent
7ac8fd1c68
commit
6f01652520
@ -51,6 +51,7 @@ namespace Emby.Drawing
|
|||||||
private readonly IJsonSerializer _jsonSerializer;
|
private readonly IJsonSerializer _jsonSerializer;
|
||||||
private readonly IServerApplicationPaths _appPaths;
|
private readonly IServerApplicationPaths _appPaths;
|
||||||
private readonly IImageEncoder _imageEncoder;
|
private readonly IImageEncoder _imageEncoder;
|
||||||
|
private readonly SemaphoreSlim _imageProcessingSemaphore;
|
||||||
|
|
||||||
public ImageProcessor(ILogger logger, IServerApplicationPaths appPaths, IFileSystem fileSystem, IJsonSerializer jsonSerializer, IImageEncoder imageEncoder)
|
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);
|
_cachedImagedSizes = new ConcurrentDictionary<Guid, ImageSize>(sizeDictionary);
|
||||||
|
var count = Environment.ProcessorCount;
|
||||||
|
_imageProcessingSemaphore = new SemaphoreSlim(count, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string[] SupportedInputFormats
|
public string[] SupportedInputFormats
|
||||||
@ -201,6 +204,8 @@ namespace Emby.Drawing
|
|||||||
|
|
||||||
await semaphore.WaitAsync().ConfigureAwait(false);
|
await semaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var imageProcessingLockTaken = false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
CheckDisposed();
|
CheckDisposed();
|
||||||
@ -212,11 +217,20 @@ namespace Emby.Drawing
|
|||||||
|
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
|
Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath));
|
||||||
|
|
||||||
|
await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
imageProcessingLockTaken = true;
|
||||||
|
|
||||||
_imageEncoder.EncodeImage(originalImagePath, cacheFilePath, newWidth, newHeight, quality, options);
|
_imageEncoder.EncodeImage(originalImagePath, cacheFilePath, newWidth, newHeight, quality, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
if (imageProcessingLockTaken)
|
||||||
|
{
|
||||||
|
_imageProcessingSemaphore.Release();
|
||||||
|
}
|
||||||
|
|
||||||
semaphore.Release();
|
semaphore.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,10 +268,15 @@ namespace Emby.Drawing
|
|||||||
return GetResult(croppedImagePath);
|
return GetResult(croppedImagePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var imageProcessingLockTaken = false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(croppedImagePath));
|
Directory.CreateDirectory(Path.GetDirectoryName(croppedImagePath));
|
||||||
|
|
||||||
|
await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
imageProcessingLockTaken = true;
|
||||||
|
|
||||||
_imageEncoder.CropWhiteSpace(originalImagePath, croppedImagePath);
|
_imageEncoder.CropWhiteSpace(originalImagePath, croppedImagePath);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@ -269,6 +288,11 @@ namespace Emby.Drawing
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
if (imageProcessingLockTaken)
|
||||||
|
{
|
||||||
|
_imageProcessingSemaphore.Release();
|
||||||
|
}
|
||||||
|
|
||||||
semaphore.Release();
|
semaphore.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -592,13 +616,25 @@ namespace Emby.Drawing
|
|||||||
return enhancedImagePath;
|
return enhancedImagePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var imageProcessingLockTaken = false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(enhancedImagePath));
|
Directory.CreateDirectory(Path.GetDirectoryName(enhancedImagePath));
|
||||||
|
|
||||||
|
await _imageProcessingSemaphore.WaitAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
imageProcessingLockTaken = true;
|
||||||
|
|
||||||
await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, enhancedImagePath, item, imageType, imageIndex).ConfigureAwait(false);
|
await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, enhancedImagePath, item, imageType, imageIndex).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
if (imageProcessingLockTaken)
|
||||||
|
{
|
||||||
|
_imageProcessingSemaphore.Release();
|
||||||
|
}
|
||||||
|
|
||||||
semaphore.Release();
|
semaphore.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -717,9 +753,18 @@ namespace Emby.Drawing
|
|||||||
return Path.Combine(path, filename);
|
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)
|
public IEnumerable<IImageEnhancer> GetSupportedEnhancers(IHasImages item, ImageType imageType)
|
||||||
|
@ -104,6 +104,6 @@ namespace MediaBrowser.Controller.Drawing
|
|||||||
/// Creates the image collage.
|
/// Creates the image collage.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="options">The options.</param>
|
/// <param name="options">The options.</param>
|
||||||
void CreateImageCollage(ImageCollageOptions options);
|
Task CreateImageCollage(ImageCollageOptions options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ namespace MediaBrowser.Model.Configuration
|
|||||||
DownMixAudioBoost = 2;
|
DownMixAudioBoost = 2;
|
||||||
EncodingQuality = EncodingQuality.Auto;
|
EncodingQuality = EncodingQuality.Auto;
|
||||||
EnableThrottling = true;
|
EnableThrottling = true;
|
||||||
ThrottleThresholdSeconds = 90;
|
ThrottleThresholdSeconds = 120;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
|||||||
NatUtility.UnhandledException += NatUtility_UnhandledException;
|
NatUtility.UnhandledException += NatUtility_UnhandledException;
|
||||||
NatUtility.StartDiscovery();
|
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();
|
_lastConfigIdentifier = GetConfigIdentifier();
|
||||||
|
|
||||||
@ -97,17 +97,17 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
|
|||||||
|
|
||||||
void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
void NatUtility_UnhandledException(object sender, UnhandledExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
//var ex = e.ExceptionObject as Exception;
|
var ex = e.ExceptionObject as Exception;
|
||||||
|
|
||||||
//if (ex == null)
|
if (ex == null)
|
||||||
//{
|
{
|
||||||
// _logger.Error("Unidentified error reported by Mono.Nat");
|
//_logger.Error("Unidentified error reported by Mono.Nat");
|
||||||
//}
|
}
|
||||||
//else
|
else
|
||||||
//{
|
{
|
||||||
// // Seeing some blank exceptions coming through here
|
// Seeing some blank exceptions coming through here
|
||||||
// _logger.ErrorException("Error reported by Mono.Nat: ", ex);
|
_logger.ErrorException("Error reported by Mono.Nat: ", ex);
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NatUtility_DeviceFound(object sender, DeviceEventArgs e)
|
void NatUtility_DeviceFound(object sender, DeviceEventArgs e)
|
||||||
|
@ -345,7 +345,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||||||
{
|
{
|
||||||
var name = MakeValidUsername(Environment.UserName);
|
var name = MakeValidUsername(Environment.UserName);
|
||||||
|
|
||||||
var user = InstantiateNewUser(name, false);
|
var user = InstantiateNewUser(name);
|
||||||
|
|
||||||
user.DateLastSaved = DateTime.UtcNow;
|
user.DateLastSaved = DateTime.UtcNow;
|
||||||
|
|
||||||
@ -552,7 +552,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var user = InstantiateNewUser(name, true);
|
var user = InstantiateNewUser(name);
|
||||||
|
|
||||||
var list = Users.ToList();
|
var list = Users.ToList();
|
||||||
list.Add(user);
|
list.Add(user);
|
||||||
@ -697,21 +697,13 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||||||
/// Instantiates the new user.
|
/// Instantiates the new user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="name">The name.</param>
|
/// <param name="name">The name.</param>
|
||||||
/// <param name="checkId">if set to <c>true</c> [check identifier].</param>
|
|
||||||
/// <returns>User.</returns>
|
/// <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
|
return new User
|
||||||
{
|
{
|
||||||
Name = name,
|
Name = name,
|
||||||
Id = id,
|
Id = Guid.NewGuid(),
|
||||||
DateCreated = DateTime.UtcNow,
|
DateCreated = DateTime.UtcNow,
|
||||||
DateModified = DateTime.UtcNow,
|
DateModified = DateTime.UtcNow,
|
||||||
UsesIdForConfigurationPath = true
|
UsesIdForConfigurationPath = true
|
||||||
|
@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Photos
|
|||||||
{
|
{
|
||||||
var outputPath = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid() + ".png");
|
var outputPath = Path.Combine(ApplicationPaths.TempDirectory, Guid.NewGuid() + ".png");
|
||||||
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
|
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)
|
if (!imageCreated)
|
||||||
{
|
{
|
||||||
@ -103,9 +103,9 @@ namespace MediaBrowser.Server.Implementations.Photos
|
|||||||
return parts.GetMD5().ToString("N");
|
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)
|
protected virtual IEnumerable<string> GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable<BaseItem> items)
|
||||||
@ -115,22 +115,22 @@ namespace MediaBrowser.Server.Implementations.Photos
|
|||||||
.Where(i => !string.IsNullOrWhiteSpace(i));
|
.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));
|
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.Photos
|
|||||||
InputPaths = GetStripCollageImagePaths(primaryItem, items).ToArray()
|
InputPaths = GetStripCollageImagePaths(primaryItem, items).ToArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageProcessor.CreateImageCollage(options);
|
return ImageProcessor.CreateImageCollage(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
@ -151,7 +151,7 @@ namespace MediaBrowser.Server.Implementations.Photos
|
|||||||
get { return "Dynamic Image Provider"; }
|
get { return "Dynamic Image Provider"; }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual bool CreateImage(IHasImages item,
|
protected virtual async Task<bool> CreateImage(IHasImages item,
|
||||||
List<BaseItem> itemsWithImages,
|
List<BaseItem> itemsWithImages,
|
||||||
string outputPath,
|
string outputPath,
|
||||||
ImageType imageType,
|
ImageType imageType,
|
||||||
@ -166,7 +166,7 @@ namespace MediaBrowser.Server.Implementations.Photos
|
|||||||
|
|
||||||
if (imageType == ImageType.Thumb)
|
if (imageType == ImageType.Thumb)
|
||||||
{
|
{
|
||||||
CreateThumbCollage(item, itemsWithImages, outputPath, drawText);
|
await CreateThumbCollage(item, itemsWithImages, outputPath, drawText).ConfigureAwait(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,15 +174,15 @@ namespace MediaBrowser.Server.Implementations.Photos
|
|||||||
{
|
{
|
||||||
if (item is UserView)
|
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)
|
else if (item is PhotoAlbum || item is Playlist)
|
||||||
{
|
{
|
||||||
CreateSquareCollage(item, itemsWithImages, outputPath, drawText);
|
await CreateSquareCollage(item, itemsWithImages, outputPath, drawText).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CreatePosterCollage(item, itemsWithImages, outputPath);
|
await CreatePosterCollage(item, itemsWithImages, outputPath).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -234,7 +234,7 @@ namespace MediaBrowser.Server.Implementations.Photos
|
|||||||
protected virtual List<BaseItem> GetFinalItems(List<BaseItem> items, int limit)
|
protected virtual List<BaseItem> GetFinalItems(List<BaseItem> items, int limit)
|
||||||
{
|
{
|
||||||
// Rotate the images once every x days
|
// Rotate the images once every x days
|
||||||
var random = DateTime.Now.DayOfYear % 5;
|
var random = DateTime.Now.DayOfYear % 7;
|
||||||
|
|
||||||
return items
|
return items
|
||||||
.OrderBy(i => (random + "" + items.IndexOf(i)).GetMD5())
|
.OrderBy(i => (random + "" + items.IndexOf(i)).GetMD5())
|
||||||
|
@ -216,7 +216,7 @@ namespace MediaBrowser.Server.Implementations.UserViews
|
|||||||
return collectionStripViewTypes.Contains(view.ViewType ?? string.Empty);
|
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;
|
var view = (UserView)item;
|
||||||
if (imageType == ImageType.Primary && IsUsingCollectionStrip(view))
|
if (imageType == ImageType.Primary && IsUsingCollectionStrip(view))
|
||||||
@ -226,11 +226,11 @@ namespace MediaBrowser.Server.Implementations.UserViews
|
|||||||
return false;
|
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 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)
|
protected override IEnumerable<String> GetStripCollageImagePaths(IHasImages primaryItem, IEnumerable<BaseItem> items)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user