diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 8541a60ef..d4c0ddc70 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -107,8 +107,7 @@ namespace MediaBrowser.Api.Playback.Hls throw; } - var waitCount = isLive ? 2 : 2; - await WaitForMinimumSegmentCount(playlist, waitCount, cancellationTokenSource.Token).ConfigureAwait(false); + await WaitForMinimumSegmentCount(playlist, 3, cancellationTokenSource.Token).ConfigureAwait(false); } } finally diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index dd6189bc5..cdb52ec66 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1519,6 +1519,7 @@ namespace MediaBrowser.Controller.Entities image.Path = file.FullName; image.DateModified = imageInfo.DateModified; + image.Length = imageInfo.Length; } } @@ -1623,11 +1624,14 @@ namespace MediaBrowser.Controller.Entities return null; } + var fileInfo = new FileInfo(path); + return new ItemImageInfo { Path = path, - DateModified = FileSystem.GetLastWriteTimeUtc(path), - Type = imageType + DateModified = FileSystem.GetLastWriteTimeUtc(fileInfo), + Type = imageType, + Length = fileInfo.Length }; } @@ -1686,6 +1690,7 @@ namespace MediaBrowser.Controller.Entities else { existing.DateModified = FileSystem.GetLastWriteTimeUtc(newImage); + existing.Length = ((FileInfo) newImage).Length; } } @@ -1700,7 +1705,8 @@ namespace MediaBrowser.Controller.Entities { Path = file.FullName, Type = type, - DateModified = FileSystem.GetLastWriteTimeUtc(file) + DateModified = FileSystem.GetLastWriteTimeUtc(file), + Length = ((FileInfo)file).Length }; } @@ -1739,9 +1745,15 @@ namespace MediaBrowser.Controller.Entities FileSystem.SwapFiles(path1, path2); + var file1 = new FileInfo(info1.Path); + var file2 = new FileInfo(info2.Path); + // Refresh these values - info1.DateModified = FileSystem.GetLastWriteTimeUtc(info1.Path); - info2.DateModified = FileSystem.GetLastWriteTimeUtc(info2.Path); + info1.DateModified = FileSystem.GetLastWriteTimeUtc(file1); + info2.DateModified = FileSystem.GetLastWriteTimeUtc(file2); + + info1.Length = file1.Length; + info2.Length = file2.Length; return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); } diff --git a/MediaBrowser.Controller/Entities/ItemImageInfo.cs b/MediaBrowser.Controller/Entities/ItemImageInfo.cs index b36b818ff..1122de403 100644 --- a/MediaBrowser.Controller/Entities/ItemImageInfo.cs +++ b/MediaBrowser.Controller/Entities/ItemImageInfo.cs @@ -11,6 +11,12 @@ namespace MediaBrowser.Controller.Entities /// The path. public string Path { get; set; } + /// + /// Gets or sets the length. + /// + /// The length. + public long Length { get; set; } + /// /// Gets or sets the type. /// diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index ef99e444f..c5b74c5c1 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -690,8 +690,9 @@ namespace MediaBrowser.Model.ApiClient /// Stops the transcoding processes. /// /// The device identifier. + /// The stream identifier. /// Task. - Task StopTranscodingProcesses(string deviceId); + Task StopTranscodingProcesses(string deviceId, string streamId); /// /// Sets the index of the audio stream. diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 3c75aa20a..533e843ea 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -386,6 +386,7 @@ namespace MediaBrowser.Providers.Manager else { currentImage.DateModified = _fileSystem.GetLastWriteTimeUtc(image.FileInfo); + currentImage.Length = ((FileInfo) image.FileInfo).Length; } } } diff --git a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs index 79e5a0cf0..a9affe1ec 100644 --- a/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs +++ b/MediaBrowser.Server.Implementations/Drawing/ImageProcessor.cs @@ -144,7 +144,7 @@ namespace MediaBrowser.Server.Implementations.Drawing { var tmpPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + ".webp"); Directory.CreateDirectory(Path.GetDirectoryName(tmpPath)); - + using (var wand = new MagickWand(1, 1, new PixelWand("none", 1))) { wand.SaveImage(tmpPath); @@ -186,21 +186,31 @@ namespace MediaBrowser.Server.Implementations.Drawing } var dateModified = options.Image.DateModified; + var length = options.Image.Length; if (options.CropWhiteSpace) { - var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified).ConfigureAwait(false); + var tuple = await GetWhitespaceCroppedImage(originalImagePath, dateModified, length).ConfigureAwait(false); originalImagePath = tuple.Item1; dateModified = tuple.Item2; + length = tuple.Item3; } if (options.Enhancers.Count > 0) { - var tuple = await GetEnhancedImage(options.Image, options.Item, options.ImageIndex, options.Enhancers).ConfigureAwait(false); + var tuple = await GetEnhancedImage(new ItemImageInfo + { + Length = length, + DateModified = dateModified, + Type = options.Image.Type, + Path = originalImagePath + + }, options.Item, options.ImageIndex, options.Enhancers).ConfigureAwait(false); originalImagePath = tuple.Item1; dateModified = tuple.Item2; + length = tuple.Item3; } var originalImageSize = GetImageSize(originalImagePath, dateModified); @@ -217,7 +227,7 @@ namespace MediaBrowser.Server.Implementations.Drawing var quality = options.Quality ?? 90; var outputFormat = GetOutputFormat(options.OutputFormat); - var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.BackgroundColor); + var cacheFilePath = GetCacheFilePath(originalImagePath, newSize, quality, dateModified, length, outputFormat, options.AddPlayedIndicator, options.PercentPlayed, options.UnplayedCount, options.BackgroundColor); var semaphore = GetLock(cacheFilePath); @@ -341,13 +351,11 @@ namespace MediaBrowser.Server.Implementations.Drawing /// /// Crops whitespace from an image, caches the result, and returns the cached path /// - /// The original image path. - /// The date modified. - /// System.String. - private async Task> GetWhitespaceCroppedImage(string originalImagePath, DateTime dateModified) + private async Task> GetWhitespaceCroppedImage(string originalImagePath, DateTime dateModified, long length) { var name = originalImagePath; name += "datemodified=" + dateModified.Ticks; + name += "length=" + length; var croppedImagePath = GetCachePath(CroppedWhitespaceImageCachePath, name, Path.GetExtension(originalImagePath)); @@ -359,7 +367,7 @@ namespace MediaBrowser.Server.Implementations.Drawing if (File.Exists(croppedImagePath)) { semaphore.Release(); - return new Tuple(croppedImagePath, _fileSystem.GetLastWriteTimeUtc(croppedImagePath)); + return GetResult(croppedImagePath); } try @@ -377,14 +385,21 @@ namespace MediaBrowser.Server.Implementations.Drawing // We have to have a catch-all here because some of the .net image methods throw a plain old Exception _logger.ErrorException("Error cropping image {0}", ex, originalImagePath); - return new Tuple(originalImagePath, dateModified); + return new Tuple(originalImagePath, dateModified, length); } finally { semaphore.Release(); } - return new Tuple(croppedImagePath, _fileSystem.GetLastWriteTimeUtc(croppedImagePath)); + return GetResult(croppedImagePath); + } + + private Tuple GetResult(string path) + { + var file = new FileInfo(path); + + return new Tuple(path, _fileSystem.GetLastWriteTimeUtc(file), file.Length); } /// @@ -395,7 +410,7 @@ namespace MediaBrowser.Server.Implementations.Drawing /// /// Gets the cache file path based on a set of parameters /// - private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, string backgroundColor) + private string GetCacheFilePath(string originalPath, ImageSize outputSize, int quality, DateTime dateModified, long length, ImageFormat format, bool addPlayedIndicator, double percentPlayed, int? unwatchedCount, string backgroundColor) { var filename = originalPath; @@ -406,6 +421,7 @@ namespace MediaBrowser.Server.Implementations.Drawing filename += "quality=" + quality; filename += "datemodified=" + dateModified.Ticks; + filename += "length=" + length; filename += "f=" + format; @@ -601,16 +617,17 @@ namespace MediaBrowser.Server.Implementations.Drawing var originalImagePath = image.Path; var dateModified = image.DateModified; var imageType = image.Type; + var length = image.Length; // Optimization if (imageEnhancers.Count == 0) { - return (originalImagePath + dateModified.Ticks).GetMD5().ToString("N"); + return (originalImagePath + dateModified.Ticks + string.Empty + length).GetMD5().ToString("N"); } // Cache name is created with supported enhancers combined with the last config change so we pick up new config changes var cacheKeys = imageEnhancers.Select(i => i.GetConfigurationCacheKey(item, imageType)).ToList(); - cacheKeys.Add(originalImagePath + dateModified.Ticks); + cacheKeys.Add(originalImagePath + dateModified.Ticks + string.Empty + length); return string.Join("|", cacheKeys.ToArray()).GetMD5().ToString("N"); } @@ -633,7 +650,7 @@ namespace MediaBrowser.Server.Implementations.Drawing return result.Item1; } - private async Task> GetEnhancedImage(ItemImageInfo image, + private async Task> GetEnhancedImage(ItemImageInfo image, IHasImages item, int imageIndex, List enhancers) @@ -641,6 +658,7 @@ namespace MediaBrowser.Server.Implementations.Drawing var originalImagePath = image.Path; var dateModified = image.DateModified; var imageType = image.Type; + var length = image.Length; try { @@ -652,9 +670,7 @@ namespace MediaBrowser.Server.Implementations.Drawing // If the path changed update dateModified if (!ehnancedImagePath.Equals(originalImagePath, StringComparison.OrdinalIgnoreCase)) { - dateModified = _fileSystem.GetLastWriteTimeUtc(ehnancedImagePath); - - return new Tuple(ehnancedImagePath, dateModified); + return GetResult(ehnancedImagePath); } } catch (Exception ex) @@ -662,7 +678,7 @@ namespace MediaBrowser.Server.Implementations.Drawing _logger.Error("Error enhancing image", ex); } - return new Tuple(originalImagePath, dateModified); + return new Tuple(originalImagePath, dateModified, length); } /// diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 887a94ab3..b28f26946 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -765,11 +765,14 @@ namespace MediaBrowser.Server.Implementations.Dto if (!string.IsNullOrEmpty(chapterInfo.ImagePath)) { + var file = new FileInfo(chapterInfo.ImagePath); + dto.ImageTag = GetImageCacheTag(item, new ItemImageInfo { Path = chapterInfo.ImagePath, Type = ImageType.Chapter, - DateModified = _fileSystem.GetLastWriteTimeUtc(chapterInfo.ImagePath) + DateModified = _fileSystem.GetLastWriteTimeUtc(file), + Length = file.Length }); }