aboutsummaryrefslogtreecommitdiff
path: root/Emby.Drawing/ImageProcessor.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Drawing/ImageProcessor.cs')
-rw-r--r--Emby.Drawing/ImageProcessor.cs104
1 files changed, 73 insertions, 31 deletions
diff --git a/Emby.Drawing/ImageProcessor.cs b/Emby.Drawing/ImageProcessor.cs
index e28d22cf7..f91cb4675 100644
--- a/Emby.Drawing/ImageProcessor.cs
+++ b/Emby.Drawing/ImageProcessor.cs
@@ -220,7 +220,7 @@ namespace Emby.Drawing
Type = originalImage.Type,
Path = originalImagePath
- }, requiresTransparency, item, options.ImageIndex, options.Enhancers).ConfigureAwait(false);
+ }, requiresTransparency, item, options.ImageIndex, options.Enhancers, CancellationToken.None).ConfigureAwait(false);
originalImagePath = tuple.Item1;
dateModified = tuple.Item2;
@@ -256,31 +256,29 @@ namespace Emby.Drawing
var outputFormat = GetOutputFormat(options.SupportedOutputFormats, requiresTransparency);
var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.Blur, options.BackgroundColor, options.ForegroundLayer);
+ CheckDisposed();
+
+ var lockInfo = GetLock(cacheFilePath);
+
+ await lockInfo.Lock.WaitAsync().ConfigureAwait(false);
+
try
{
- CheckDisposed();
-
if (!_fileSystem.FileExists(cacheFilePath))
{
- var tmpPath = Path.ChangeExtension(Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString("N")), Path.GetExtension(cacheFilePath));
- _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
-
if (options.CropWhiteSpace && !SupportsTransparency(originalImagePath))
{
options.CropWhiteSpace = false;
}
- var resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, tmpPath, autoOrient, orientation, quality, options, outputFormat);
+ var resultPath = _imageEncoder.EncodeImage(originalImagePath, dateModified, cacheFilePath, autoOrient, orientation, quality, options, outputFormat);
if (string.Equals(resultPath, originalImagePath, StringComparison.OrdinalIgnoreCase))
{
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
- _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(cacheFilePath));
- CopyFile(tmpPath, cacheFilePath);
-
- return new Tuple<string, string, DateTime>(tmpPath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(tmpPath));
+ return new Tuple<string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath));
}
return new Tuple<string, string, DateTime>(cacheFilePath, GetMimeType(outputFormat, cacheFilePath), _fileSystem.GetLastWriteTimeUtc(cacheFilePath));
@@ -302,6 +300,10 @@ namespace Emby.Drawing
// Just spit out the original file if all the options are default
return new Tuple<string, string, DateTime>(originalImagePath, MimeTypes.GetMimeType(originalImagePath), dateModified);
}
+ finally
+ {
+ ReleaseLock(cacheFilePath, lockInfo);
+ }
}
private ImageFormat GetOutputFormat(ImageFormat[] clientSupportedFormats, bool requiresTransparency)
@@ -667,7 +669,7 @@ namespace Emby.Drawing
var inputImageSupportsTransparency = SupportsTransparency(imageInfo.Path);
- var result = await GetEnhancedImage(imageInfo, inputImageSupportsTransparency, item, imageIndex, enhancers);
+ var result = await GetEnhancedImage(imageInfo, inputImageSupportsTransparency, item, imageIndex, enhancers, CancellationToken.None);
return result.Item1;
}
@@ -676,7 +678,8 @@ namespace Emby.Drawing
bool inputImageSupportsTransparency,
IHasMetadata item,
int imageIndex,
- List<IImageEnhancer> enhancers)
+ List<IImageEnhancer> enhancers,
+ CancellationToken cancellationToken)
{
var originalImagePath = image.Path;
var dateModified = image.DateModified;
@@ -687,7 +690,7 @@ namespace Emby.Drawing
var cacheGuid = GetImageCacheTag(item, image, enhancers);
// Enhance if we have enhancers
- var ehnancedImageInfo = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid).ConfigureAwait(false);
+ var ehnancedImageInfo = await GetEnhancedImageInternal(originalImagePath, item, imageType, imageIndex, enhancers, cacheGuid, cancellationToken).ConfigureAwait(false);
var ehnancedImagePath = ehnancedImageInfo.Item1;
@@ -727,7 +730,8 @@ namespace Emby.Drawing
ImageType imageType,
int imageIndex,
List<IImageEnhancer> supportedEnhancers,
- string cacheGuid)
+ string cacheGuid,
+ CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(originalImagePath))
{
@@ -755,29 +759,28 @@ namespace Emby.Drawing
var enhancedImagePath = GetCachePath(EnhancedImageCachePath, cacheGuid + cacheExtension);
- // Check again in case of contention
- if (_fileSystem.FileExists(enhancedImagePath))
- {
- return new Tuple<string, bool>(enhancedImagePath, treatmentRequiresTransparency);
- }
+ var lockInfo = GetLock(enhancedImagePath);
- _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath));
-
- var tmpPath = Path.Combine(_appPaths.TempDirectory, Path.ChangeExtension(Guid.NewGuid().ToString(), Path.GetExtension(enhancedImagePath)));
- _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(tmpPath));
-
- await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, tmpPath, item, imageType, imageIndex).ConfigureAwait(false);
+ await lockInfo.Lock.WaitAsync(cancellationToken).ConfigureAwait(false);
try
{
- _fileSystem.CopyFile(tmpPath, enhancedImagePath, true);
+ // Check again in case of contention
+ if (_fileSystem.FileExists(enhancedImagePath))
+ {
+ return new Tuple<string, bool>(enhancedImagePath, treatmentRequiresTransparency);
+ }
+
+ _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(enhancedImagePath));
+
+ await ExecuteImageEnhancers(supportedEnhancers, originalImagePath, enhancedImagePath, item, imageType, imageIndex).ConfigureAwait(false);
+
+ return new Tuple<string, bool>(enhancedImagePath, treatmentRequiresTransparency);
}
- catch
+ finally
{
-
+ ReleaseLock(enhancedImagePath, lockInfo);
}
-
- return new Tuple<string, bool>(tmpPath, treatmentRequiresTransparency);
}
/// <summary>
@@ -896,6 +899,45 @@ namespace Emby.Drawing
return list;
}
+ private Dictionary<string, LockInfo> _locks = new Dictionary<string, LockInfo>();
+ private class LockInfo
+ {
+ public SemaphoreSlim Lock = new SemaphoreSlim(1, 1);
+ public int Count = 1;
+ }
+ private LockInfo GetLock(string key)
+ {
+ lock (_locks)
+ {
+ LockInfo info;
+ if (_locks.TryGetValue(key, out info))
+ {
+ info.Count++;
+ }
+ else
+ {
+ info = new LockInfo();
+ _locks[key] = info;
+ }
+ return info;
+ }
+ }
+
+ private void ReleaseLock(string key, LockInfo info)
+ {
+ info.Lock.Release();
+
+ lock (_locks)
+ {
+ info.Count--;
+ if (info.Count <= 0)
+ {
+ _locks.Remove(key);
+ info.Lock.Dispose();
+ }
+ }
+ }
+
private bool _disposed;
public void Dispose()
{