diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2017-12-01 12:04:32 -0500 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2017-12-01 12:04:32 -0500 |
| commit | dec3b1bbb0f53e1dafcf0bd9238aaefbfd18f335 (patch) | |
| tree | a6359ce484a67d002253e2cb1567c2f670729fc1 /Emby.Drawing/ImageProcessor.cs | |
| parent | d7a1a87009eed638d28d070e6a47c8a5bee38c2e (diff) | |
improve image processing performance
Diffstat (limited to 'Emby.Drawing/ImageProcessor.cs')
| -rw-r--r-- | Emby.Drawing/ImageProcessor.cs | 104 |
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() { |
